From d2b1f357049f6b5e6766af9f3dfa134d2527feec Mon Sep 17 00:00:00 2001 From: David Turner Date: Thu, 16 Dec 1999 23:11:37 +0000 Subject: [PATCH] Initial revision --- CHANGES | 176 + Makefile | 90 + config/ansi/Makefile | 178 + config/ansi/ftconfig.h | 182 + config/ansi/ftoption.h | 162 + config/ansi/ftsys.c | 971 ++ config/ansi/ftsystem.c | 214 + config/ansi/memdebug.c | 143 + config/detect.mk | 127 + config/dos/FTCONFIG.H | 182 + config/dos/FTOPTION.H | 152 + config/dos/FTSYSTEM.C | 214 + config/dos/MAKEFILE.GCC | 172 + config/dos/detect.mk | 87 + config/dos/ftoption.h | 162 + config/dos/ftsys.c | 866 ++ config/freetype.mk | 199 + config/os2/Makefile.emx | 196 + config/os2/detect.mk | 47 + config/os2/ftconfig.h | 182 + config/os2/ftoption.h | 162 + config/os2/ftsys.c | 940 ++ config/os2/ftsystem.c | 214 + config/os2/makefile.devel | 192 + config/os2/makefile.gcc | 190 + config/unix/Makefile | 172 + config/unix/Makefile.devel | 172 + config/unix/detect.mk | 31 + config/unix/ftconfig.h | 172 + config/unix/ftoption.h | 162 + config/unix/ftsys.c | 871 ++ config/unix/ftsystem.c | 277 + config/win32/Makefile.gcc | 179 + config/win32/Makefile.lcc | 180 + config/win32/Makefile.vcc | 174 + config/win32/detect.mk | 66 + config/win32/ftconfig.h | 182 + config/win32/ftoption.h | 162 + config/win32/ftsystem.c | 214 + config/win32/lcclib.bat | 12 + demos/Makefile | 227 + demos/config/os2/gros2pm.c | 887 ++ demos/config/os2/gros2pm.def | 5 + demos/config/os2/gros2pm.h | 23 + demos/config/os2/rules.mk | 32 + demos/config/x11/grx11.c | 936 ++ demos/config/x11/grx11.h | 24 + demos/config/x11/rules.mk | 69 + demos/graph/gpm_os2.def | 5 + demos/graph/graph.h | 632 ++ demos/graph/grblit.c | 1268 +++ demos/graph/grblit.h | 25 + demos/graph/grconfig.h | 9 + demos/graph/grdevice.c | 361 + demos/graph/grdevice.h | 126 + demos/graph/grevents.h | 117 + demos/graph/grfont.c | 354 + demos/graph/grfont.h | 16 + demos/graph/grinit.c | 78 + demos/graph/grobjs.c | 213 + demos/graph/grobjs.h | 186 + demos/graph/gros2pm.c | 895 ++ demos/graph/gros2pm.h | 23 + demos/graph/grtypes.h | 52 + demos/graph/grx11.c | 936 ++ demos/graph/grx11.h | 24 + demos/graph/migs.html | 304 + demos/graph/rules.mk | 99 + demos/graph/xtest.c | 125 + demos/obj/README | 1 + demos/src/common.c | 244 + demos/src/common.h | 53 + demos/src/ftlint.c | 169 + demos/src/ftsbit.c | 313 + demos/src/fttimer.c | 460 + demos/src/fttry.c | 155 + demos/src/ftview.c | 615 ++ demos/src/t1dump.c | 1031 +++ demos/src/ttdebug.c | 1247 +++ docs/BUILD | 375 + docs/DESIGN | 216 + docs/essai | 173 + docs/glyph_conventions/bbox1.gif | Bin 0 -> 2791 bytes docs/glyph_conventions/bbox2.gif | Bin 0 -> 2468 bytes docs/glyph_conventions/body_comparison.gif | Bin 0 -> 2353 bytes docs/glyph_conventions/bravo_kerned.gif | Bin 0 -> 1279 bytes docs/glyph_conventions/bravo_unkerned.gif | Bin 0 -> 1284 bytes docs/glyph_conventions/build_diagram.gif | Bin 0 -> 4528 bytes docs/glyph_conventions/clipping.gif | Bin 0 -> 3041 bytes docs/glyph_conventions/down_flow.gif | Bin 0 -> 2705 bytes docs/glyph_conventions/glyph_conventions.html | 1626 ++++ docs/glyph_conventions/grid_1.gif | Bin 0 -> 5837 bytes docs/glyph_conventions/objects_diagram.gif | Bin 0 -> 4418 bytes docs/glyph_conventions/objects_diagram2.gif | Bin 0 -> 4000 bytes docs/glyph_conventions/points_conic.gif | Bin 0 -> 1764 bytes docs/glyph_conventions/points_conic2.gif | Bin 0 -> 2158 bytes docs/glyph_conventions/points_cubic.gif | Bin 0 -> 1782 bytes docs/glyph_conventions/points_segment.gif | Bin 0 -> 1548 bytes docs/glyph_conventions/twlewis1.gif | Bin 0 -> 1762 bytes docs/glyph_conventions/twlewis2.gif | Bin 0 -> 1277 bytes docs/glyph_conventions/up_flow.gif | Bin 0 -> 2648 bytes docs/internals/Image1.gif | Bin 0 -> 3939 bytes docs/internals/Image2.gif | Bin 0 -> 2190 bytes docs/internals/Image3.gif | Bin 0 -> 4248 bytes docs/internals/Image4.gif | Bin 0 -> 3873 bytes docs/internals/freetype_internals.html | 788 ++ include/freetype.h | 2156 +++++ include/ftbbox.h | 73 + include/fterrors.h | 82 + include/ftimage.h | 627 ++ include/ftsystem.h | 95 + include/ttnamedid.h | 624 ++ obj/README | 1 + src/base/ftbase.c | 6 + src/base/ftbbox.c | 447 + src/base/ftcalc.c | 505 ++ src/base/ftcalc.h | 85 + src/base/ftdebug.c | 93 + src/base/ftdebug.h | 191 + src/base/ftdriver.h | 641 ++ src/base/ftextend.c | 199 + src/base/ftextend.h | 166 + src/base/ftinit.c | 169 + src/base/ftlist.c | 300 + src/base/ftlist.h | 228 + src/base/ftobjs.c | 2123 +++++ src/base/ftobjs.h | 710 ++ src/base/ftoutln.c | 286 + src/base/ftoutln.h | 153 + src/base/ftraster.c | 4372 +++++++++ src/base/ftstream.c | 436 + src/base/ftstream.h | 178 + src/base/rules.mk | 136 + src/oldapi/Makefile | 29 + src/oldapi/readme.txt | 18 + src/oldapi/truetype.h | 1709 ++++ src/oldapi/ttapi.c | 2267 +++++ src/sfnt/rules.mk | 172 + src/sfnt/sfconfig.h | 51 + src/sfnt/sfdriver.c | 72 + src/sfnt/sfdriver.h | 83 + src/sfnt/sfnt.c | 15 + src/sfnt/ttcmap.c | 508 ++ src/sfnt/ttcmap.h | 84 + src/sfnt/ttload.c | 1477 +++ src/sfnt/ttload.h | 382 + src/sfnt/ttpost.c | 700 ++ src/sfnt/ttpost.h | 87 + src/sfnt/ttsbit.c | 1437 +++ src/sfnt/ttsbit.h | 104 + src/shared/otlayout/otlayout.h | 372 + src/shared/otlayout/otload.c | 890 ++ src/shared/otlayout/otload.h | 297 + src/shared/readme.txt | 6 + src/shared/rules.mk | 95 + src/shared/sfnt.h | 347 + src/shared/sfnt/rules.mk | 58 + src/shared/sfnt/sfnt.h | 50 + src/shared/sfnt/ttload.c | 1488 +++ src/shared/sfnt/ttload.h | 353 + src/shared/sfnt/ttpost.c | 713 ++ src/shared/sfnt/ttpost.h | 95 + src/shared/sfnt/ttsbit.c | 1443 +++ src/shared/sfnt/ttsbit.h | 104 + src/shared/sfnt/tttypes.h | 1848 ++++ src/shared/t1types.h | 485 + src/shared/tterrors.h | 126 + src/shared/ttnameid.h | 603 ++ src/shared/tttags.h | 60 + src/shared/tttypes.h | 2066 +++++ src/shared/type1/rules.mk | 54 + src/shared/type1/t1encode.c | 330 + src/shared/type1/t1encode.h | 98 + src/shared/type1/t1types.h | 485 + src/truetype/rules.mk | 205 + src/truetype/truetype.c | 50 + src/truetype/ttconfig.h | 66 + src/truetype/ttdriver.c | 783 ++ src/truetype/ttdriver.h | 193 + src/truetype/tterrors.h | 124 + src/truetype/ttgload.c | 1492 ++++ src/truetype/ttgload.h | 109 + src/truetype/ttinterp.c | 7954 +++++++++++++++++ src/truetype/ttinterp.h | 470 + src/truetype/ttnameid.h | 603 ++ src/truetype/ttobjs.c | 888 ++ src/truetype/ttobjs.h | 594 ++ src/truetype/ttpload.c | 260 + src/truetype/ttpload.h | 92 + src/truetype/tttags.h | 60 + src/type1/rules.mk | 167 + src/type1/t1config.h | 45 + src/type1/t1driver.c | 279 + src/type1/t1driver.h | 77 + src/type1/t1encode.c | 332 + src/type1/t1encode.h | 98 + src/type1/t1errors.h | 77 + src/type1/t1gload.c | 1579 ++++ src/type1/t1gload.h | 436 + src/type1/t1hinter.c | 1269 +++ src/type1/t1hinter.h | 380 + src/type1/t1load.c | 1458 +++ src/type1/t1load.h | 72 + src/type1/t1objs.c | 414 + src/type1/t1objs.h | 302 + src/type1/t1parse.c | 665 ++ src/type1/t1parse.h | 296 + src/type1/t1tokens.c | 994 ++ src/type1/t1tokens.h | 352 + src/type1/type1.c | 50 + 210 files changed, 84971 insertions(+) create mode 100644 CHANGES create mode 100644 Makefile create mode 100644 config/ansi/Makefile create mode 100644 config/ansi/ftconfig.h create mode 100644 config/ansi/ftoption.h create mode 100644 config/ansi/ftsys.c create mode 100644 config/ansi/ftsystem.c create mode 100644 config/ansi/memdebug.c create mode 100644 config/detect.mk create mode 100644 config/dos/FTCONFIG.H create mode 100644 config/dos/FTOPTION.H create mode 100644 config/dos/FTSYSTEM.C create mode 100644 config/dos/MAKEFILE.GCC create mode 100644 config/dos/detect.mk create mode 100644 config/dos/ftoption.h create mode 100644 config/dos/ftsys.c create mode 100644 config/freetype.mk create mode 100644 config/os2/Makefile.emx create mode 100644 config/os2/detect.mk create mode 100644 config/os2/ftconfig.h create mode 100644 config/os2/ftoption.h create mode 100644 config/os2/ftsys.c create mode 100644 config/os2/ftsystem.c create mode 100644 config/os2/makefile.devel create mode 100644 config/os2/makefile.gcc create mode 100644 config/unix/Makefile create mode 100644 config/unix/Makefile.devel create mode 100644 config/unix/detect.mk create mode 100644 config/unix/ftconfig.h create mode 100644 config/unix/ftoption.h create mode 100644 config/unix/ftsys.c create mode 100644 config/unix/ftsystem.c create mode 100644 config/win32/Makefile.gcc create mode 100644 config/win32/Makefile.lcc create mode 100644 config/win32/Makefile.vcc create mode 100644 config/win32/detect.mk create mode 100644 config/win32/ftconfig.h create mode 100644 config/win32/ftoption.h create mode 100644 config/win32/ftsystem.c create mode 100644 config/win32/lcclib.bat create mode 100644 demos/Makefile create mode 100644 demos/config/os2/gros2pm.c create mode 100644 demos/config/os2/gros2pm.def create mode 100644 demos/config/os2/gros2pm.h create mode 100644 demos/config/os2/rules.mk create mode 100644 demos/config/x11/grx11.c create mode 100644 demos/config/x11/grx11.h create mode 100644 demos/config/x11/rules.mk create mode 100644 demos/graph/gpm_os2.def create mode 100644 demos/graph/graph.h create mode 100644 demos/graph/grblit.c create mode 100644 demos/graph/grblit.h create mode 100644 demos/graph/grconfig.h create mode 100644 demos/graph/grdevice.c create mode 100644 demos/graph/grdevice.h create mode 100644 demos/graph/grevents.h create mode 100644 demos/graph/grfont.c create mode 100644 demos/graph/grfont.h create mode 100644 demos/graph/grinit.c create mode 100644 demos/graph/grobjs.c create mode 100644 demos/graph/grobjs.h create mode 100644 demos/graph/gros2pm.c create mode 100644 demos/graph/gros2pm.h create mode 100644 demos/graph/grtypes.h create mode 100644 demos/graph/grx11.c create mode 100644 demos/graph/grx11.h create mode 100644 demos/graph/migs.html create mode 100644 demos/graph/rules.mk create mode 100644 demos/graph/xtest.c create mode 100644 demos/obj/README create mode 100644 demos/src/common.c create mode 100644 demos/src/common.h create mode 100644 demos/src/ftlint.c create mode 100644 demos/src/ftsbit.c create mode 100644 demos/src/fttimer.c create mode 100644 demos/src/fttry.c create mode 100644 demos/src/ftview.c create mode 100644 demos/src/t1dump.c create mode 100644 demos/src/ttdebug.c create mode 100644 docs/BUILD create mode 100644 docs/DESIGN create mode 100644 docs/essai create mode 100644 docs/glyph_conventions/bbox1.gif create mode 100644 docs/glyph_conventions/bbox2.gif create mode 100644 docs/glyph_conventions/body_comparison.gif create mode 100644 docs/glyph_conventions/bravo_kerned.gif create mode 100644 docs/glyph_conventions/bravo_unkerned.gif create mode 100644 docs/glyph_conventions/build_diagram.gif create mode 100644 docs/glyph_conventions/clipping.gif create mode 100644 docs/glyph_conventions/down_flow.gif create mode 100644 docs/glyph_conventions/glyph_conventions.html create mode 100644 docs/glyph_conventions/grid_1.gif create mode 100644 docs/glyph_conventions/objects_diagram.gif create mode 100644 docs/glyph_conventions/objects_diagram2.gif create mode 100644 docs/glyph_conventions/points_conic.gif create mode 100644 docs/glyph_conventions/points_conic2.gif create mode 100644 docs/glyph_conventions/points_cubic.gif create mode 100644 docs/glyph_conventions/points_segment.gif create mode 100644 docs/glyph_conventions/twlewis1.gif create mode 100644 docs/glyph_conventions/twlewis2.gif create mode 100644 docs/glyph_conventions/up_flow.gif create mode 100644 docs/internals/Image1.gif create mode 100644 docs/internals/Image2.gif create mode 100644 docs/internals/Image3.gif create mode 100644 docs/internals/Image4.gif create mode 100644 docs/internals/freetype_internals.html create mode 100644 include/freetype.h create mode 100644 include/ftbbox.h create mode 100644 include/fterrors.h create mode 100644 include/ftimage.h create mode 100644 include/ftsystem.h create mode 100644 include/ttnamedid.h create mode 100644 obj/README create mode 100644 src/base/ftbase.c create mode 100644 src/base/ftbbox.c create mode 100644 src/base/ftcalc.c create mode 100644 src/base/ftcalc.h create mode 100644 src/base/ftdebug.c create mode 100644 src/base/ftdebug.h create mode 100644 src/base/ftdriver.h create mode 100644 src/base/ftextend.c create mode 100644 src/base/ftextend.h create mode 100644 src/base/ftinit.c create mode 100644 src/base/ftlist.c create mode 100644 src/base/ftlist.h create mode 100644 src/base/ftobjs.c create mode 100644 src/base/ftobjs.h create mode 100644 src/base/ftoutln.c create mode 100644 src/base/ftoutln.h create mode 100644 src/base/ftraster.c create mode 100644 src/base/ftstream.c create mode 100644 src/base/ftstream.h create mode 100644 src/base/rules.mk create mode 100644 src/oldapi/Makefile create mode 100644 src/oldapi/readme.txt create mode 100644 src/oldapi/truetype.h create mode 100644 src/oldapi/ttapi.c create mode 100644 src/sfnt/rules.mk create mode 100644 src/sfnt/sfconfig.h create mode 100644 src/sfnt/sfdriver.c create mode 100644 src/sfnt/sfdriver.h create mode 100644 src/sfnt/sfnt.c create mode 100644 src/sfnt/ttcmap.c create mode 100644 src/sfnt/ttcmap.h create mode 100644 src/sfnt/ttload.c create mode 100644 src/sfnt/ttload.h create mode 100644 src/sfnt/ttpost.c create mode 100644 src/sfnt/ttpost.h create mode 100644 src/sfnt/ttsbit.c create mode 100644 src/sfnt/ttsbit.h create mode 100644 src/shared/otlayout/otlayout.h create mode 100644 src/shared/otlayout/otload.c create mode 100644 src/shared/otlayout/otload.h create mode 100644 src/shared/readme.txt create mode 100644 src/shared/rules.mk create mode 100644 src/shared/sfnt.h create mode 100644 src/shared/sfnt/rules.mk create mode 100644 src/shared/sfnt/sfnt.h create mode 100644 src/shared/sfnt/ttload.c create mode 100644 src/shared/sfnt/ttload.h create mode 100644 src/shared/sfnt/ttpost.c create mode 100644 src/shared/sfnt/ttpost.h create mode 100644 src/shared/sfnt/ttsbit.c create mode 100644 src/shared/sfnt/ttsbit.h create mode 100644 src/shared/sfnt/tttypes.h create mode 100644 src/shared/t1types.h create mode 100644 src/shared/tterrors.h create mode 100644 src/shared/ttnameid.h create mode 100644 src/shared/tttags.h create mode 100644 src/shared/tttypes.h create mode 100644 src/shared/type1/rules.mk create mode 100644 src/shared/type1/t1encode.c create mode 100644 src/shared/type1/t1encode.h create mode 100644 src/shared/type1/t1types.h create mode 100644 src/truetype/rules.mk create mode 100644 src/truetype/truetype.c create mode 100644 src/truetype/ttconfig.h create mode 100644 src/truetype/ttdriver.c create mode 100644 src/truetype/ttdriver.h create mode 100644 src/truetype/tterrors.h create mode 100644 src/truetype/ttgload.c create mode 100644 src/truetype/ttgload.h create mode 100644 src/truetype/ttinterp.c create mode 100644 src/truetype/ttinterp.h create mode 100644 src/truetype/ttnameid.h create mode 100644 src/truetype/ttobjs.c create mode 100644 src/truetype/ttobjs.h create mode 100644 src/truetype/ttpload.c create mode 100644 src/truetype/ttpload.h create mode 100644 src/truetype/tttags.h create mode 100644 src/type1/rules.mk create mode 100644 src/type1/t1config.h create mode 100644 src/type1/t1driver.c create mode 100644 src/type1/t1driver.h create mode 100644 src/type1/t1encode.c create mode 100644 src/type1/t1encode.h create mode 100644 src/type1/t1errors.h create mode 100644 src/type1/t1gload.c create mode 100644 src/type1/t1gload.h create mode 100644 src/type1/t1hinter.c create mode 100644 src/type1/t1hinter.h create mode 100644 src/type1/t1load.c create mode 100644 src/type1/t1load.h create mode 100644 src/type1/t1objs.c create mode 100644 src/type1/t1objs.h create mode 100644 src/type1/t1parse.c create mode 100644 src/type1/t1parse.h create mode 100644 src/type1/t1tokens.c create mode 100644 src/type1/t1tokens.h create mode 100644 src/type1/type1.c diff --git a/CHANGES b/CHANGES new file mode 100644 index 000000000..cc42e4841 --- /dev/null +++ b/CHANGES @@ -0,0 +1,176 @@ +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: + + +----------------------------------------------------------------------------------------- +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 + + 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/ + 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 is 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 to be able 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". + + +----------------------------------------------------------------------------------------- +Drivers Interface : + (To be written) + +----------------------------------------------------------------------------------------- +Extensions support : + (To be defined) + diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..5932377e8 --- /dev/null +++ b/Makefile @@ -0,0 +1,90 @@ +#****************************************************************************** +#* +#* FreeType build system - top-level Makefile +#* +#* This file is designed for GNU Make, do not use it with another Make tool. +#* It works as follows : +#* +#* - when invoked for the first time, this Makefile will include +#* the rules found in `freetype/config/detect.mk'. They are in charge +#* of detecting the current platform. +#* +#* A summary of the detection will be displayed, and the file `config.mk' +#* will be created in the current directory +#* +#* +#* - when invoked later, this Makefile will include the rules found in +#* `config.mk'. This sub-Makefile will define some system-specific +#* variables (like compiler, compilation flags, object suffix, etc..), +#* then include the rules found in `freetype/config/freetype.mk', +#* used to build the library. +#* +#* See the comments in `config/detect.mk' and `config/freetype.mk' for +#* more details on host platform detection and library builds.. +#* +#****************************************************************************** + +.PHONY: setup + +# +# The variable TOP holds the path to the topmost directory in the FreeType +# engine source hierarchy. If it is not defined, default it to '.' +# +ifndef TOP +TOP := . +endif + +CONFIG_MK := config.mk + +############################################################################# +# +# If no configuration sub-makefile is present, or if "setup" is the target +# to be built, run the auto-detection rules to figure out which configuration +# rules file to use.. +# +# Note that the configuration file is put in the current directory, which is +# not necessarily TOP. +# + +# if `config.mk' is not present, set "check_platform" and "first_time" +# +ifeq ($(wildcard $(CONFIG_MK)),) +check_platform := 1 +first_time := 1 +endif + +# if `setup' is one of the targets requested, set "check_platform" +# +ifneq ($(findstring setup,$(MAKECMDGOALS)),) +check_platform := 1 +endif + + +######################################################################### +# +# include the automatic host platform detection rules when we need to +# check the platform. +# +# +ifdef check_platform + +all: setup + +include $(TOP)/config/detect.mk + +# "setup" must be defined by the host platform detection rules + +else + +######################################################################## +# +# A configuration sub-Makefile is present, simply run it.. +# +# +all: build_freetype + +BUILD_FREETYPE := yes +include $(CONFIG_MK) + +endif #test check_platform + diff --git a/config/ansi/Makefile b/config/ansi/Makefile new file mode 100644 index 000000000..07db19262 --- /dev/null +++ b/config/ansi/Makefile @@ -0,0 +1,178 @@ +#******************************************************************* +#* +#* FreeType 2 Configuration rules for a `normal' ANSI compiler +#* +#* Copyright 1996-1999 by +#* David Turner, Robert Wilhelm, and Werner Lemberg. +#* +#* This file is part of the FreeType project, and may only be used +#* modified and distributed under the terms of the FreeType project +#* license, LICENSE.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 sub-Makefile is to define various build and +#* platform specific variables before including the sub-Makefile +#* containing the FreeType library rules, found in +#* +#* $(TOP)/config/freetype.mk +#* +#* The following variables must be defined before including this +#* file : +#* +#* TOP Pathname to the top of the FreeType sources +#* hierarchy +#* +#* This file should define the following variables before including +#* the FreeType library rules file : +#* +#* BUILD Pathname to the platform-specific files used +#* for the build. Usually `$(TOP)/config/' +#* +#* SEP Directory separator for the current platform. +#* Either / or \ (maybe : on Macs) +#* +#* DELETE The forced remove/delete command to erase one or more +#* files +#* +#* INCLUDE The location of all public header files. e.g. +#* `$(TOP)/include'include' * +#* +#* SRC The directory containing all sources. e.g. +#* '$(TOP)/src' +#* +#* OBJ_DIR The location where compiled object files will be +#* placed, e.g. '$(TOP)/obj' +#* +#* LIB_DIR The location where the resulting library file will be +#* placed, e.g. '$(TOP)/obj' +#* +#* LIBRARY The filename of the resulting library file, without +#* its extension.. e.g. 'libfreetype' or 'freetype' +#* +#* O The object file suffix. Can be '.o', '.obj,' '.lo,' +#* ';coff,' etc. +#* +#* A The library file suffix. Can be '.a' '.so,' '.lib' +#* '.dll,' etc. +#* +#* I The path inclusion flag. Some compilers use a +#* different flag than '-I' to specify an additional +#* include path. Examples are '/i=' or '-J ', etc. +#* +#* D The macro definition flag. I haven't met compilers +#* which don't use the '-D' switch to define a macro, but +#* who knows... +#* +#* T The compilation flag used to identify the target. Some +#* compilers use a different flag than '-o ' to specify +#* the name of the target object file. +#* +#* CFLAGS The set of flags used to compile object files. +#* (usually contains the flag '-c'). +#* +#* +#* +#******************************************************************* + +ifndef TOP +TOP := . +endif + +DELETE := rm -f +SEP := / +BUILD := $(TOP)/config/ansi +PLATFORM := ansi + +# the directory where all object files are placed +# +OBJ_DIR := $(TOP)/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, this can be .o, .tco, .obj, etc.. +# depending on the platform +# +O := o + +# the library file extension, this can be .a, .lib, etc.. +# depending on the platform +# +A := 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", etc... +# +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 + + +# Target flag - beware, there is a space after the 'o' !! +# +# +T := -o + + +# 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 + + +# C flags +# +# These should concern : +# +# - debug output +# - optimization +# - warnings +# - ansi compliance.. +# +ifndef CFLAGS +CFLAGS := -c +endif + +# Now include the main sub-makefile. It contains all the rules used +# to build the library with the previous variables defined +# +include $(TOP)/config/freetype.mk + + +# 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) + diff --git a/config/ansi/ftconfig.h b/config/ansi/ftconfig.h new file mode 100644 index 000000000..43a4c9522 --- /dev/null +++ b/config/ansi/ftconfig.h @@ -0,0 +1,182 @@ +/***************************************************************************/ +/* */ +/* ftconfig.h */ +/* */ +/* ANSI-specific configuration file (specification only). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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. Porters are free to copy this file and */ + /* adapt it to suit their own system. */ + /* */ + /* IMPORTANT NOTE: */ + /* */ + /* Porters, read carefully the comments in `ftsys.h' before trying to */ + /* port this file to your system. It contains many essential */ + /* remarks, and will ease your work greatly. */ + /* */ + /*************************************************************************/ + + +#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/arch/' directory, and edit it to port the engine. */ + /* */ + /*************************************************************************/ + + +/* Define to empty if the keyword does not work. */ +/* #undef const */ + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* We use values to know the sizes of the types. */ +#include + +/* The number of bytes in an `int' type. */ +#if UINT_MAX == 0xFFFFFFFF +#define SIZEOF_INT 4 +#elif UINT_MAX == 0xFFFF +#define SIZEOF_INT 2 +#elif UINT_MAX > 0xFFFFFFFF && UINT_MAX == 0xFFFFFFFFFFFFFFFF +#define 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 SIZEOF_LONG 4 +#elif ULONG_MAX > 0xFFFFFFFF && ULONG_MAX == 0xFFFFFFFFFFFFFFFF +#define SIZEOF_LONG 8 +#else +#error "Unsupported number of bytes in `long' type!" +#endif + +/* Define if you have the memcpy function. */ +#define HAVE_MEMCPY 1 + +/* Define if you have the header file. */ +#define HAVE_FCNTL_H 0 + +/* Define if you have the header file. */ +#define HAVE_UNISTD_H 0 + + +/* Preferred alignment of data */ +#define FT_ALIGNMENT 8 + + + + /*************************************************************************/ + /* */ + /* AUTOMATIC CONFIGURATION MACROS */ + /* */ + /* These macros are computed from the ones defined above. Don't touch */ + /* their definition, unless you know precisely what you're 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_Word16; + +#if SIZEOF_INT == 4 + + typedef signed int FT_Int32; + typedef unsigned int FT_Word32; + +#elif SIZEOF_LONG == 4 + + typedef signed long FT_Int32; + typedef unsigned long FT_Word32; + +#else +#error "no 32bit type found - please check your configuration files" +#endif + +#if SIZEOF_LONG == 8 + + /* LONG64 must be defined when a 64-bit type is available */ +#define LONG64 +#define INT64 long + +#else + + + /*************************************************************************/ + /* */ + /* GCC provides the non-ANSI 'long long' 64-bit type. You can activate */ + /* it by defining the FTCALC_USE_LONG_LONG macro in `ftconfig.h'. Note */ + /* that this will produce many -ansi warnings during library */ + /* compilation. */ + /* */ +#ifdef FTCALC_USE_LONG_LONG + +#define LONG64 +#define INT64 long long + +#endif /* FTCALC_USE_LONG_LONG */ +#endif + + +#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 LOCAL_DEF +#define BASE_FUNC LOCAL_FUNC +#else +#define BASE_DEF extern +#define BASE_FUNC /* nothing */ +#endif + +#ifndef EXPORT_DEF +#define EXPORT_DEF extern +#endif + +#ifndef EXPORT_FUNC +#define EXPORT_FUNC /* nothing */ +#endif + +#endif /* FTCONFIG_H */ + + +/* END */ diff --git a/config/ansi/ftoption.h b/config/ansi/ftoption.h new file mode 100644 index 000000000..852f65fbb --- /dev/null +++ b/config/ansi/ftoption.h @@ -0,0 +1,162 @@ +#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 file contains macros that apply to */ + /* all of FreeType. Driver-specific configurations are placed in each */ + /* driver directory (e.g. `freetype/drivers/ttlib/ttconfig.h'). */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* 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're sure that you'll never use a font driver */ + /* with an alternate glyph format, this will reduce the size of the */ + /* base layer code. */ + /* */ +#define FT_CONFIG_OPTION_ALTERNATE_GLYPH_FORMATS + + /*************************************************************************/ + /* */ + /* GCC provides the non-ANSI `long long' 64-bit type. You can activate */ + /* it by defining the FTCALC_USE_LONG_LONG macro here. Note however */ + /* that we did not experience any improvement in speed with gcc, and */ + /* that the final code seems bigger when linked. */ + /* */ +#undef FTCALC_USE_LONG_LONG + + + /*************************************************************************/ + /* */ + /* When compiling FreeType as a DLL, some systems/compilers need a */ + /* special keyword in front of each function definition instead of */ + /* `extern'. */ + /* */ + /* The macros EXPORT_DEF and EXPORT_FUNC are thus used to define */ + /* exported library function interfaces and exported library functions */ + /* implementations respectively. */ + /* */ + /* If not defined here, they automatically default to `extern' and void */ + /* later in this header file. */ + /* */ +#undef EXPORT_DEF +#undef 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. */ + /* */ +#undef FT_DEBUG_LEVEL_ERROR +#undef FT_DEBUG_LEVEL_TRACE + + + /*************************************************************************/ + /* */ + /* Anti-aliasing support */ + /* */ + /* Undefine this macro only if you want to disable the anti-aliasing */ + /* support in FreeType. This will save you about 5 Kb of code. It */ + /* may be important for some embedded systems. */ + /* */ +#define FT_CONFIG_OPTION_ANTI_ALIAS + + + /*************************************************************************/ + /* */ + /* Endianess performance improvement */ + /* */ + /* FreeType is completely endian-independent, and can thus be compiled */ + /* directly on _any_ machine. However, some components of the library */ + /* provide improved routines for the cases where endianess is known. */ + /* */ + /* It usually results in speed-ups and reduced code size. Note that */ + /* you should not define both of these macros. */ + /* */ + /* */ + /* NOTE: For now, only the scan-line converter (base/ftraster.c) uses */ + /* these macros to speed-up some anti-alias rendering routines. */ + /* */ +#undef FT_CONFIG_OPTION_LITTLE_ENDIAN +#undef FT_CONFIG_OPTION_BIG_ENDIAN + + + /*************************************************************************/ + /* */ + /* Define this configuration macro whenever you want to build a version */ + /* of FreeType that does not include a default `system' component. */ + /* */ + /* Note that this will prevent the compilation of `ftinit', hence the */ + /* function FT_Init_FreeType */ + /* */ +#undef FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM + + + /*************************************************************************/ + /* */ + /* 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 4 Kb */ + /* */ +#define FT_RENDER_POOL_SIZE 32768 + + + /*************************************************************************/ + /* */ + /* FT_MAX_DRIVERS */ + /* */ + /* The maximum number of font drivers that can be registered in a */ + /* single FreeType library object. 8 seems to be a good choice due */ + /* to the relative low actual number of drivers ;-) */ + /* */ +#define FT_MAX_DRIVERS 8 + + + /*************************************************************************/ + /* */ + /* FT_MAX_EXTENSIONS */ + /* */ + /* The maximum number of extensions that can be registered in a */ + /* single font driver. 8 seems to be a good choice for now.. */ + /* */ +#define FT_MAX_EXTENSIONS 8 + + + /*************************************************************************/ + /* */ + /* FT_MAX_GLYPH_FORMATS */ + /* */ + /* The maximum number of glyph image formats that might be registered */ + /* in a given library instance. 8 seems to be a good choice due to */ + /* the relatively low number of current formats ;-) */ + /* */ + +#define FT_MAX_GLYPH_FORMATS 8 + + + +#endif /* FTOPTION_H */ diff --git a/config/ansi/ftsys.c b/config/ansi/ftsys.c new file mode 100644 index 000000000..8042d56c1 --- /dev/null +++ b/config/ansi/ftsys.c @@ -0,0 +1,971 @@ +/***************************************************************************/ +/* */ +/* ftsys.c */ +/* */ +/* ANSI-specific system operations (body). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 implementation of the `ftsys' component uses the standard ANSI C */ + /* library. */ + /* */ + /* IMPORTANT NOTE: */ + /* */ + /* Porters, read carefully the comments in ftsys.h before trying to */ + /* port this file to your system. It contains many essential */ + /* remarks, and will ease your work greatly. */ + /* */ + /*************************************************************************/ + + +#include "ftsys.h" +#include "ftstream.h" +#include "ftdebug.h" + + +#ifdef FT_CONFIG_OPTION_DEBUG_MEMORY +#include "memdebug.c" +#endif + + + /*************************************************************************/ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the PTRACE() and PERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_io + + +#undef CUR_SYSTEM /* just in case */ + + + /*************************************************************************/ + /* */ + /* To ease porting, we use the macro SYS_STREAM to name the */ + /* system-specific stream type. For example, it is a `FILE*' with the */ + /* ANSI libc, it will be a file descriptor, i.e. an integer, when using */ + /* the Unix system API, etc. */ + /* */ +#define SYS_STREAM FILE* + + + /*************************************************************************/ + /* */ + /* This implementation of ftsys uses the ANSI C library. Memory */ + /* management is performed through malloc/free, i/o access through */ + /* fopen/fread/fseek, and no synchronisation primitive is implemented */ + /* (they contain dummy code) */ + /* */ + /*************************************************************************/ + + +#include +#include + + + /*************************************************************************/ + /* */ + /* I/O ACCESS AND MANAGEMENT */ + /* */ + /* We only define the `ANSI' resource class in this class. It is */ + /* disk-based and provides a MRU cache in order to only keep the file */ + /* descriptors of the 10 most recently used resource files. */ + /* */ + /* It simply contains two lists. One contains the `cached' resources */ + /* with a valid FILE* pointer, the second contains all other `flushed' */ + /* resource objects. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* FT_AnsiFileRec */ + /* */ + /* */ + /* The FT_AnsiFile class derives from FT_ResourceRec. */ + /* */ + /* */ + /* root :: The root resource class fields. */ + /* */ + /* pathname :: This is a copy of the ANSI file pathname used to open */ + /* streams for the resource. A different implementation */ + /* is free to use Unicode chars, or file i-node numbers, */ + /* etc. */ + /* */ + /* file_size :: The size in bytes of the resource. This field should */ + /* be set to -1 until the resource is first opened. */ + /* */ + typedef struct FT_AnsiFileRec_ + { + FT_ResourceRec root; + char* pathname; /* the font file's pathname */ + FT_Long file_size; /* file size in bytes */ + + } FT_AnsiFileRec, *FT_AnsiFile; + + + /*************************************************************************/ + /* */ + /* We use the macro STREAM_Name() as a convenience to return a given */ + /* ANSI resource's pathname. Its `stream' argument is a FT_Resource */ + /* which is typecasted to the FT_AnsiFile class. */ + /* */ +#define STREAM_Name( stream ) ((FT_AnsiFile)stream->resource)->pathname + + + /*************************************************************************/ + /* */ + /* We use the macro STREAM_File() as a convenience to extract the */ + /* system-specific stream handle from a given FreeType stream object. */ + /* */ +#define STREAM_File( stream ) ((FILE*)stream->stream_id.pointer) + + + /*************************************************************************/ + /* */ + /* */ + /* AnsiFile_Open */ + /* */ + /* */ + /* This function is used to open a system-stream for a given */ + /* resource. */ + /* */ + /* Note that it must update the target FreeType stream object with */ + /* the system-stream handle and the resource's size. */ + /* */ + /* Also, the `stream->base' field must be set to NULL for disk-based */ + /* resources, and to the address in memory of the resource's first */ + /* byte for memory-based ones. */ + /* */ + /* */ + /* resource :: The source resource. */ + /* stream :: The target stream object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* This function simply calls fopen() in the resource's file */ + /* pathname. */ + /* */ + /* The stream object IS NOT CREATED by this function, but by its */ + /* caller. */ + /* */ + static + FT_Error AnsiFile_Open( FT_AnsiFile resource, + FT_Stream stream ) + { + FILE* file; + + /* open the file */ + file = fopen( resource->pathname, "rb" ); + if ( !file ) + { + PERROR(( "AnsiFile_Open: Could not open file `%s'\n", + resource->pathname )); + return FT_Err_Cannot_Open_Stream; + } + + /* compute file size if necessary */ + if ( resource->file_size < 0 ) + { + fseek( file, 0, SEEK_END ); + resource->file_size = ftell( file ); + fseek( file, 0, SEEK_SET ); + } + + stream->resource = (FT_Resource)resource; + stream->stream_id.pointer = file; + stream->size = resource->file_size; + + /* it's a disk-based resource, we don't need to use the `base' and */ + /* `cursor' fields of the stream objects */ + stream->base = NULL; + stream->cursor = NULL; + + PTRACE1(( "AnsiFile_Open: Opened `%s' (%d bytes) successfully\n", + resource->pathname, resource->file_size )); + + return FT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* AnsiFile_Close */ + /* */ + /* */ + /* Closes a given stream. */ + /* */ + /* */ + /* stream :: The target stream object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* This function simply calls fclose() on the stream's ANSI FILE */ + /* object. */ + /* */ + static + FT_Error AnsiFile_Close( FT_Stream stream ) + { + PTRACE1(( "AnsiFile_Close: Closing file `%s'\n", STREAM_Name( stream ) )); + + fclose( STREAM_File( stream ) ); + + stream->resource = NULL; + stream->stream_id.pointer = NULL; + stream->size = 0; + + return FT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* AnsiFile_Seek */ + /* */ + /* */ + /* Seeks a stream to a given position. */ + /* */ + /* */ + /* stream :: The target stream object. */ + /* position :: The offset in bytes from the start of the */ + /* resource/stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* This function simply calls fseek() on the stream. */ + /* */ + /* The `seek' method is never called by the stream manager in case */ + /* of a memory-based resource (i.e., when `stream->base' isn't NULL). */ + /* */ + static + FT_Error AnsiFile_Seek( FT_Stream stream, + FT_Long position ) + { + if ( fseek( STREAM_File( stream ), position, SEEK_SET ) ) + { + PERROR(( "AnsiFile_Seek: FAILED! Pos. %ld of `%s'\n", + position, STREAM_Name( stream ) )); + + return FT_Err_Invalid_Stream_Seek; + } + + PTRACE2(( "AnsiFile_Seek: Pos. %ld of `%s'\n", + position, STREAM_Name( stream ) )); + + return FT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* AnsiFile_Skip */ + /* */ + /* */ + /* Skips a given number of bytes in an ANSI stream. Useful to skip */ + /* pad bytes, for example. */ + /* */ + /* */ + /* stream :: The target stream object. */ + /* count :: The number of bytes to skip in the stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* This function simply calls fseek() on the stream. */ + /* */ + /* The `skip' method is never called by the stream manager in case */ + /* of a memory-based resource (i.e., when `stream->base' isn't NULL). */ + /* */ + static + FT_Error AnsiFile_Skip( FT_Stream stream, + FT_Long count ) + { + if ( fseek( STREAM_File( stream ), count, SEEK_CUR ) ) + { + PERROR(( "AnsiFile_Skip: FAILED! %ld bytes in `%s'\n", + count, STREAM_Name( stream ) )); + + return FT_Err_Invalid_Stream_Seek; + } + + PTRACE2(( "AnsiFile_Skip: %ld bytes in `%s'\n", + count, STREAM_Name( stream ) )); + + return FT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* AnsiFile_Pos */ + /* */ + /* */ + /* Returns the current offset within an ANSI stream's resource. */ + /* */ + /* */ + /* stream :: The target stream object. */ + /* */ + /* */ + /* position :: The current offset. -1 in case of error. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* This function simply calls ftell() on the stream. */ + /* */ + /* The `pos' method is never called by the stream manager in case */ + /* of a memory-based resource (i.e., when `stream->base' isn't NULL). */ + /* */ + static + FT_Error AnsiFile_Pos( FT_Stream stream, + FT_Long* position ) + { + *position = ftell( STREAM_File( stream ) ); + if ( *position == -1 ) + { + PTRACE2(( "AnsiFile_Pos: FAILED! In `%s'\n", STREAM_Name( stream ) )); + return FT_Err_Invalid_Stream_Seek; + } + + PTRACE2(( "AnsiFile_Pos: For `%s'\n", STREAM_Name( stream ) )); + return FT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* AnsiFile_Read */ + /* */ + /* */ + /* Reads a given number of bytes from an ANSI stream into memory. */ + /* */ + /* */ + /* stream :: The target stream object. */ + /* buffer :: The target read buffer where data is copied. */ + /* size :: The number of bytes to read from the stream. */ + /* */ + /* */ + /* read_bytes :: The number of bytes effectively read from the */ + /* stream. Used in case of error */ + /* (i.e. FT_Err_Invalid_Stream_Read) by some parts of */ + /* the library. */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* This function simply calls fread() on the stream. */ + /* */ + /* It MUST return the error FT_Err_Invalid_Stream_Read in case of */ + /* an over-read (i.e., reading more bytes from the stream that what */ + /* is left), as the stream component checks for this specific value. */ + /* */ + /* The `read' method is never called by the stream manager in case */ + /* of a memory-based resource (i.e., when `stream->base' isn't NULL). */ + /* */ + static + FT_Error AnsiFile_Read( FT_Stream stream, + FT_Char* buffer, + FT_Long size, + FT_Long* read_bytes ) + { + *read_bytes = fread( buffer, 1, size, STREAM_File( stream ) ); + if ( *read_bytes != size ) + { + /* Note : we can have an over-read here when called by the */ + /* function FT_Access_Compressed_Frame. This means */ + /* that the following message should be a trace, */ + /* rather than an error for disk-based resources.. */ + /* */ + /* the function must set the value of 'read_bytes' */ + /* even if it returns an error code.. */ + PTRACE2(( "AnsiFile_Read: FAILED! Read %ld bytes from '%s'\n", + size, STREAM_Name( stream ) )); + + return FT_Err_Invalid_Stream_Read; + } + + PTRACE2(( "AnsiFile_Read: Read %ld bytes to buffer 0x%08lx from `%s'\n", + size, (long)buffer, STREAM_Name( stream ) )); + return FT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* The following table is the `virtual method table' for the `ANSI */ + /* resource class', which methods are defined above. Its address is set */ + /* in the `interface' field of all resource objects created by the */ + /* function FT_Create_AnsiFile() (see below). */ + /* */ + static + FTRes_InterfaceRec FT_AnsiFile_Interface = + { + (FTRes_Open_Func) AnsiFile_Open, + (FTRes_Close_Func)AnsiFile_Close, + (FTRes_Seek_Func) AnsiFile_Seek, + (FTRes_Skip_Func) AnsiFile_Skip, + (FTRes_Pos_Func) AnsiFile_Pos, + (FTRes_Read_Func) AnsiFile_Read, + }; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Create_Resource */ + /* */ + /* */ + /* Creates a new resource object. This function is called by the */ + /* FT_New_Resource() function of the base layer. */ + /* */ + /* */ + /* library :: The input library object. */ + /* pathname :: The file's pathname as an ASCII string. */ + /* */ + /* */ + /* aresource :: A handle to new resource object. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + /* */ + /* This functions does not open a stream. It simply copies the */ + /* pathname within a fresh new resource object. */ + /* */ + EXPORT_FUNC + FT_Error FT_Create_Resource( FT_Library library, + const char* pathname, + FT_Resource* aresource ) + { + FT_Int len; + FT_AnsiFile resource; + FT_Error error; + FT_System system; + + + if ( !library ) + return FT_Err_Invalid_Library_Handle; + + system = library->system; + + if ( !pathname ) + goto Fail_Null; + + len = strlen( pathname ); + if ( len == 0 ) + goto Fail_Null; + + resource = NULL; + + if ( ALLOC( resource, sizeof ( *resource ) ) || + ALLOC( resource->pathname, len + 1 ) ) + goto Fail_Memory; + + resource->root.library = library; + resource->root.interface = &FT_AnsiFile_Interface; + resource->root.flags = FT_RESOURCE_TYPE_DISK_BASED; + resource->file_size = -1; + strcpy( resource->pathname, pathname ); + + PTRACE1(( "Create_AnsiFile: Ansi resource created for `%s'\n", + pathname )); + + *aresource = (FT_Resource)resource; + return FT_Err_Ok; + + Fail_Null: + PERROR(( "Create_AnsiFile: Null pathname!\n" )); + return FT_Err_Invalid_Argument; + + Fail_Memory: + if ( resource ) + FREE( resource->pathname ); + FREE( resource ); + PERROR(( "Create_AnsiFile: Not enough memory to create resource!\n" )); + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Destroy_Resource */ + /* */ + /* */ + /* Discards a given resource object explicitly. */ + /* */ + /* */ + /* resource :: The ANSI resource object. */ + /* */ + /* */ + /* This function does not check whether runs or streams are opened */ + /* for the resource (for now, we assume developer intelligence. */ + /* We'll most probably lower our standard later to ease debugging :-) */ + /* */ + EXPORT_FUNC + FT_Error FT_Destroy_Resource( FT_Resource resource ) + { + FT_System system = resource->library->system; + FT_AnsiFile ansi = (FT_AnsiFile)resource; + + if ( !ansi || ansi->root.interface != &FT_AnsiFile_Interface ) + { + PERROR(( + "Destroy_AnsiFile: Trying to destroy an invalid resource!\n" )); + return FT_Err_Invalid_Resource_Handle; + } + + PTRACE1(( "Destroy_AnsiFile: Destroying resource for `%s'\n", + ansi->pathname )); + + FREE( ansi->pathname ); + FREE( ansi ); + + return FT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* MEMORY MANAGEMENT */ + /* */ + /* */ + /* This part copies the old FreeType 1.0 and 1.1 memory management */ + /* scheme that was defined in the file `ttmemory.h'. One can see that */ + /* */ + /* - a set of macros is defined for the memory operations used by the */ + /* engine (MEM_Copy(), MEM_Move(), MEM_Set()). This comes from the */ + /* fact that many compilers are able to inline these operations */ + /* directly within the compiled code, rather than generating a call */ + /* to the C library. However, this obliges us to include the */ + /* `' header file. */ + /* */ + /* If you provide your own memory operations, you can get rid of the */ + /* `#include ' below. */ + /* */ + /* */ + /* - the FT_Alloc() function has several essential properties that MUST */ + /* be retained by each port: */ + /* */ + /* - It returns an error code, NOT the allocated block's base */ + /* address. */ + /* */ + /* - It takes the address of a target pointer, where the block's base */ + /* address will be set. If the size is zero, its value will be */ + /* NULL, and the function returns successfully. */ + /* */ + /* - In case of error, the pointer's value is set to NULL and an */ + /* error code is returned. */ + /* */ + /* - The new allocated block MUST be zero-filled. This is a strong */ + /* convention the rest of the engine relies on. */ + /* */ + /* */ + /* - the FT_Free() function has also its essentials: */ + /* */ + /* - It takes the address of a pointer which value is the block's */ + /* base address. This is UNLIKE a standard `free()' which takes */ + /* the block's base directly. */ + /* */ + /* - It accepts successfully the address of a pointer which value is */ + /* NULL, in which case it simply returns. */ + /* */ + /* - The pointer is always set to NULL by the function. */ + /* */ + /* */ + /* - The MEM_Alloc(), ALLOC(), and ALLOC_ARRAY() macros are used by the */ + /* library and should NOT be modified by porters! */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the PTRACE() and PERROR() 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. */ + /* */ + /* */ + /* system :: A handle to a given `system object' where allocation */ + /* occurs. */ + /* */ + /* 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_System system, + FT_Long size, + void** P ) + { + if ( !P ) + { + PERROR(( "FT_Alloc: Invalid pointer address!\n" )); + return FT_Err_Invalid_Argument; + } + + if ( size > 0 ) + { + *P = malloc( size ); + if ( !*P ) + { + PERROR(( "FT_Alloc: Out of memory (%ld bytes requested)!\n", + size )); + + return FT_Err_Out_Of_Memory; + } + +#ifdef FT_CONFIG_OPTION_DEBUG_MEMORY + DM_Record( (char*)*P, size ); +#endif + + system->total_alloc += size; + + /* ALWAYS ZERO-FILL THE BLOCK! */ + MEM_Set( *P, 0, size ); + } + else + *P = NULL; + + PTRACE2(( "FT_Alloc: Size = %ld, pointer = 0x%08lx, block = 0x%08lx\n", + size, (long)P, (long)*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'. */ + /* */ + /* */ + /* system :: A handle to a given `system object' where allocation */ + /* occurs. */ + /* */ + /* 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_Realloc( FT_System system, + FT_Long size, + void* *P ) + { + void* Q; + + + if ( !P ) + { + PERROR(( "FT_Realloc: Invalid pointer address!\n" )); + return FT_Err_Invalid_Argument; + } + + /* if the original pointer is NULL, call FT_Alloc() */ + if ( !*P ) + return FT_Alloc( system, size, P ); + + /* if the new block if zero-sized, clear the current one */ + if ( size <= 0 ) + return FT_Free( system, P ); + +#ifdef FT_CONFIG_OPTION_DEBUG_MEMORY + DM_Forget( (char*)*P ); +#endif + + Q = (void*)realloc( *P, size ); + if ( !Q ) + { + PERROR(( "FT_Realloc: Reallocation failed!\n" )); + return FT_Err_Out_Of_Memory; + } + +#ifdef FT_CONFIG_OPTION_DEBUG_MEMORY + DM_Record( (char*)Q, size ); +#endif + + *P = Q; + return FT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Free */ + /* */ + /* */ + /* Releases a given block of memory allocated through FT_Alloc(). */ + /* */ + /* */ + /* system :: A handle to a given `system object' where allocation */ + /* occured. */ + /* */ + /* 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 + FT_Error FT_Free( FT_System system, + void* *P ) + { + UNUSED( system ); + + PTRACE2(( "FT_Free: Freeing pointer 0x%08lx (block 0x%08lx)\n", + (long)P, (P ? (long)*P : -1) )); + + if ( !P || !*P ) + return FT_Err_Ok; + + free( *P ); + +#ifdef FT_CONFIG_OPTION_DEBUG_MEMORY + DM_Forget( (char*)*P ); +#endif + + *P = NULL; + + return FT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* SYNCHRONIZATION MANAGEMENT */ + /* */ + /* */ + /* This section deals with mutexes. The library can be compiled to */ + /* two distinct thread support levels (namely single threaded and */ + /* re-entrant modes). */ + /* */ + /* It protects its variables through the MUTEX_Lock() and */ + /* MUTEX_Release() macros which are void in single threaded mode. */ + /* */ + /* It defines a typeless mutex reference type, `FT_Mutex', that you're */ + /* free to redefine for your system's needs. */ + /* */ + /* The default implementation of ftsys.c contains only dummy functions */ + /* which always return successfully. You NEED to specialize them in */ + /* order to port ftsys.c to any multi-threaded environment. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the PTRACE() and PERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_sync + + +#ifdef FT_CONFIG_THREADS + + BASE_FUNC + FT_Error FT_Mutex_Create( FT_System system, + TMutex* mutex ) + { + UNUSED( system ); + + mutex = (void*)-1; + system->num_mutexes++; + + /* Insert your own mutex creation code here */ + + return FT_Err_Ok; + } + + + BASE_FUNC + void FT_Mutex_Delete( FT_System system, + TMutex* mutex ) + { + UNUSED( system ); + + mutex = (void*)0; + system->num_mutexes--; + + /* Insert your own mutex destruction code here */ + } + + + BASE_FUNC + void FT_Mutex_Lock( FT_System system, + TMutex* mutex ) + { + /* NOTE: It is legal to call this function with a NULL argument */ + /* in which case an immediate return is appropriate. */ + + UNUSED( system ); + + if ( !mutex ) + return; + + /* Insert your own mutex locking code here */ + } + + + BASE_FUNC + void FT_Mutex_Release( FT_System system, + TMutex* mutex ) + { + /* NOTE: It is legal to call this function with a NULL argument */ + /* in which case an immediate return is appropriate */ + + UNUSED( system ); + + if ( !mutex ) + return; + + /* Insert your own mutex release code here */ + } + +#endif /* FT_CONFIG_THREADS */ + + + /*************************************************************************/ + /* */ + /* */ + /* FT_New_System */ + /* */ + /* */ + /* This function is used to create and initialize new system objects. */ + /* These are mainly used to let client applications and font servers */ + /* specify their own memory allocators and synchronization */ + /* procedures. */ + /* */ + /* */ + /* system :: A handle to a given `system object'. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + EXPORT_FUNC + FT_Error FT_New_System( FT_System* system ) + { + *system = (FT_System)malloc( sizeof ( **system ) ); + + if ( !*system ) + return FT_Err_Out_Of_Memory; + + /* the ANSI function `free()' is unable to return the number */ + /* of released bytes. Hence, the `current_alloc' field of the */ + /* system object cannot be used. */ + + (*system)->system_flags = FT_SYSTEM_FLAG_TOTAL_ALLOC | + FT_SYSTEM_FLAG_MUTEXES; + (*system)->total_alloc = 0; + (*system)->num_mutexes = 0; + +#ifdef FT_CONFIG_OPTION_DEBUG_MEMORY + DM_Init_Mem(); +#endif + + /* initialize i/o management (nothing) */ + + /* initialize synchronisation (nothing) */ + + /* initialize streams (nothing) */ + + return FT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Done_System */ + /* */ + /* */ + /* Destroys a given FreeType system object. */ + /* */ + /* */ + /* system :: A handle to a given `system object'. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + EXPORT_FUNC + FT_Error FT_Done_System( FT_System system ) + { + /* finalize synchronization (nothing) */ + + /* finalize i/o management (nothing) */ + + /* finalize memory management */ + +#ifdef FT_CONFIG_OPTION_DEBUG_MEMORY + DM_Done_Mem(); +#endif + + free( system ); + + return FT_Err_Ok; + } + + +/* END */ diff --git a/config/ansi/ftsystem.c b/config/ansi/ftsystem.c new file mode 100644 index 000000000..459f668e9 --- /dev/null +++ b/config/ansi/ftsystem.c @@ -0,0 +1,214 @@ +/************************************************************************** + * + * ftsystem.h 1.0 + * + * ANSI-specific FreeType low-level system interface + * + * This file contains the definition of interface used by FreeType + * to access low-level, i.e. memory management, i/o access as well + * as thread synchronisation. + * + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.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 + + /*********************************************************************/ + /* */ + /* MEMORY MANAGEMENT INTERFACE */ + /* */ + +/************************************************************************ + * + * + * FT_Alloc_Func + * + * + * The memory allocator function type + * + * + * system :: pointer to the system object + * size :: requested size in bytes + * + * + * block :: address of newly allocated block + * + * + * Error code. 0 means success. + * + * + * If your allocation routine ALWAYS zeroes the new block, you + * should set the flag FT_SYSTEM_FLAG_ALLOC_ZEROES in your system + * object 'flags' field. + * + * If you have set the flag FT_SYSTEM_FLAG_REPORT_CURRENT_ALLOC in + * your system's "system_flags" field, this function should update + * the "current_alloc" field of the system object. + * + ************************************************************************/ + + static + void* ft_alloc( FT_Memory memory, + long size ) + { + (void)memory; + return malloc(size); + } + + +/************************************************************************ + * + * + * FT_Realloc_Func + * + * + * The memory reallocator function type + * + * + * system :: pointer to the system object + * new_size :: new requested size in bytes + * + * + * block :: address of block in memory + * + * + * Error code. 0 means success. + * + * + * This function is _never_ called when the system flag + * FT_SYSTEM_FLAG_NO_REALLOC is set. Instead, the engine will emulate + * realloc through "alloc" and "free". + * + * Note that this is possible due to the fact that FreeType's + * "FT_Realloc" always requests the _current_ size of the reallocated + * block as a parameter, thus avoiding memory leaks. + * + * If you have set the flag FT_SYSTEM_FLAG_REPORT_CURRENT_ALLOC in + * your system's "system_flags" field, this function should update + * the "current_alloc" field of the system object. + * + ************************************************************************/ + + static + void* ft_realloc( FT_Memory memory, + long cur_size, + long new_size, + void* block ) + { + (void)memory; + (void)cur_size; + + return realloc( block, new_size ); + } + + +/************************************************************************ + * + * + * FT_Free_Func + * + * + * The memory release function type + * + * + * system :: pointer to the system object + * block :: address of block in memory + * + * + * If you have set the flag FT_SYSTEM_FLAG_REPORT_CURRENT_ALLOC in + * your system's "system_flags" field, this function should update + * the "current_alloc" field of the system object. + * + ************************************************************************/ + + static + void ft_free( FT_Memory memory, + void* block ) + { + (void)memory; + free( block ); + } + + /*********************************************************************/ + /* */ + /* RESOURCE MANAGEMENT INTERFACE */ + /* */ + + +#define STREAM_FILE(stream) ((FILE*)stream->descriptor.pointer) + + static + void ft_close_stream( FT_Stream stream ) + { + fclose( STREAM_FILE(stream) ); + } + + static + unsigned long ft_io_stream( FT_Stream stream, + unsigned long offset, + char* buffer, + unsigned long count ) + { + FILE* file; + + file = STREAM_FILE(stream); + + fseek( file, offset, SEEK_SET ); + return (unsigned long)fread( buffer, count, 1, file ); + } + + + extern + int FT_New_Stream( const char* filepathname, + FT_Stream stream ) + { + FILE* file; + + file = fopen( filepathname, "rb" ); + if (!file) + 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->pos = 0; + + stream->read = ft_io_stream; + stream->close = ft_close_stream; + + return 0; + } + + + extern + 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; + } + diff --git a/config/ansi/memdebug.c b/config/ansi/memdebug.c new file mode 100644 index 000000000..fa2796140 --- /dev/null +++ b/config/ansi/memdebug.c @@ -0,0 +1,143 @@ +/***************************************************************************/ +/* */ +/* memdebug.c */ +/* */ +/* Memory debugging functions (body only). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 + + + typedef struct TBlockRec_ + { + char* base; + long size; + + } TBlockRec; + + + static TBlockRec* mem_blocks; + static int num_mem_blocks; + static int max_mem_blocks; + + + void DM_Init_Mem() + { + num_mem_blocks = 0; + max_mem_blocks = 4096; + mem_blocks = (TBlockRec*)malloc( max_mem_blocks * + sizeof ( *mem_blocks ) ); + } + + + void DM_Done_Mem() + { + /* Now print the remaining blocks */ + if ( num_mem_blocks == 0 ) + { + fprintf( stderr, "No memory leaked!\n" ); + } + else + { + int i; + + + fprintf( stderr, "There were %d leaked memory blocks\n\n", + num_mem_blocks ); + + fprintf( stderr, "base size\n" ); + fprintf( stderr, "------------------\n" ); + + for ( i = 0; i < num_mem_blocks; i++ ) + { + fprintf( stderr, "%08lx %04lx\n", + (long)mem_blocks[i].base, mem_blocks[i].size ); + } + } + free( mem_blocks ); + } + + + void DM_Record( char* base, + long size ) + { + TBlockRec* block; + + +#if 0 + /* First, check that the block is not located within one of the */ + /* recorded blocks */ + for ( i = 0; i < num_mem_blocks; i++ ) + { + char *start, *end, *_limit, *_base; + + + _base = mem_blocks[i].base; + _limit = _base + mem_blocks[i].size; + + start = base; + end = base + size - 1; + + if ( ( start >= base && start < limit ) || + ( end >= base && end < limit ) ) + { + fprintf( stderr, "Warning: Recording an invalid block!\n" ); + } + } +#endif + + /* Add block to list */ + if ( num_mem_blocks >= max_mem_blocks ) + { + max_mem_blocks *= 2; + mem_blocks = realloc( mem_blocks, + max_mem_blocks * sizeof ( *mem_blocks ) ); + } + block = mem_blocks + num_mem_blocks; + block->base = base; + block->size = size; + num_mem_blocks++; + } + + + void DM_Forget( char* base ) + { + TBlockRec* block = mem_blocks; + int i; + + + for ( i = 0; i < num_mem_blocks; i++, block++ ) + { + if ( block->base == base ) + { + /* simply move last block to the current position */ + if ( num_mem_blocks > 1 ) + *block = mem_blocks[num_mem_blocks - 1]; + + num_mem_blocks--; + return; + } + +#if 1 + if ( base >= block->base && base < block->base + block->size ) + { + fprintf( stderr, "Invalid block forgotten!\n" ); + } +#endif + } + } + + +/* END */ diff --git a/config/detect.mk b/config/detect.mk new file mode 100644 index 000000000..0dcc7c9a0 --- /dev/null +++ b/config/detect.mk @@ -0,0 +1,127 @@ +#**************************************************************************** +#* * +#* FreeType host platform detection rules * +#* * +#* Copyright 1996-1999 by * +#* David Turner, Robert Wilhelm, and Werner Lemberg. * +#* * +#* This file is part of the FreeType project, and may only be used * +#* modified and distributed under the terms of the FreeType project * +#* license, LICENSE.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 some variables accordingly. Namely : * +#* * +#* PLATFORM The detected platform. This will default to "ansi" if * +#* auto-detection fails. * +#* * +#* BUILD The configuration and system-specific directory. Usually * +#* 'freetype/config/$(PLATFORM)' but can be different when * +#* a specific compiler has been requested on the * +#* command line.. * +#* * +#* CONFIG_RULES The 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 * +#* * +#* 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. +# Note that we delay the valuation of BUILD and RULES +# +PLATFORM := ansi +CONFIG = $(TOP)$(SEP)config +DELETE := $(RM) +COPY := cp +SEP := / + +BUILD = $(CONFIG)$(SEP)$(PLATFORM) +CONFIG_FILE = $(BUILD)/Makefile + + +########################################################################### +# +# Now, include each detection rules file found in a `config/' +# directory.. +# +# + +# 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 back-slash is interpreted as a line +# continuation). While a line like : +# +# SEP := \\ +# +# really define $(SEP) as "\" on Unix, and "\\" on Dos and Windows !! +# +BACKSLASH := $(strip \ ) + +include $(wildcard $(CONFIG)/*/detect.mk) + + +# The following targets are equivalent, with the exception that they use +# slightly different syntaxes for the `echo' command. This is due to +# +# std_setup: is defined for most platforms +# dos_setup: is 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 were detected :" + @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, simple 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 were detected : + @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, simple type 'make' again to build the library + @echo ÿ + @$(COPY) $(CONFIG_RULES) $(CONFIG_MK) > nul + diff --git a/config/dos/FTCONFIG.H b/config/dos/FTCONFIG.H new file mode 100644 index 000000000..43a4c9522 --- /dev/null +++ b/config/dos/FTCONFIG.H @@ -0,0 +1,182 @@ +/***************************************************************************/ +/* */ +/* ftconfig.h */ +/* */ +/* ANSI-specific configuration file (specification only). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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. Porters are free to copy this file and */ + /* adapt it to suit their own system. */ + /* */ + /* IMPORTANT NOTE: */ + /* */ + /* Porters, read carefully the comments in `ftsys.h' before trying to */ + /* port this file to your system. It contains many essential */ + /* remarks, and will ease your work greatly. */ + /* */ + /*************************************************************************/ + + +#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/arch/' directory, and edit it to port the engine. */ + /* */ + /*************************************************************************/ + + +/* Define to empty if the keyword does not work. */ +/* #undef const */ + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* We use values to know the sizes of the types. */ +#include + +/* The number of bytes in an `int' type. */ +#if UINT_MAX == 0xFFFFFFFF +#define SIZEOF_INT 4 +#elif UINT_MAX == 0xFFFF +#define SIZEOF_INT 2 +#elif UINT_MAX > 0xFFFFFFFF && UINT_MAX == 0xFFFFFFFFFFFFFFFF +#define 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 SIZEOF_LONG 4 +#elif ULONG_MAX > 0xFFFFFFFF && ULONG_MAX == 0xFFFFFFFFFFFFFFFF +#define SIZEOF_LONG 8 +#else +#error "Unsupported number of bytes in `long' type!" +#endif + +/* Define if you have the memcpy function. */ +#define HAVE_MEMCPY 1 + +/* Define if you have the header file. */ +#define HAVE_FCNTL_H 0 + +/* Define if you have the header file. */ +#define HAVE_UNISTD_H 0 + + +/* Preferred alignment of data */ +#define FT_ALIGNMENT 8 + + + + /*************************************************************************/ + /* */ + /* AUTOMATIC CONFIGURATION MACROS */ + /* */ + /* These macros are computed from the ones defined above. Don't touch */ + /* their definition, unless you know precisely what you're 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_Word16; + +#if SIZEOF_INT == 4 + + typedef signed int FT_Int32; + typedef unsigned int FT_Word32; + +#elif SIZEOF_LONG == 4 + + typedef signed long FT_Int32; + typedef unsigned long FT_Word32; + +#else +#error "no 32bit type found - please check your configuration files" +#endif + +#if SIZEOF_LONG == 8 + + /* LONG64 must be defined when a 64-bit type is available */ +#define LONG64 +#define INT64 long + +#else + + + /*************************************************************************/ + /* */ + /* GCC provides the non-ANSI 'long long' 64-bit type. You can activate */ + /* it by defining the FTCALC_USE_LONG_LONG macro in `ftconfig.h'. Note */ + /* that this will produce many -ansi warnings during library */ + /* compilation. */ + /* */ +#ifdef FTCALC_USE_LONG_LONG + +#define LONG64 +#define INT64 long long + +#endif /* FTCALC_USE_LONG_LONG */ +#endif + + +#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 LOCAL_DEF +#define BASE_FUNC LOCAL_FUNC +#else +#define BASE_DEF extern +#define BASE_FUNC /* nothing */ +#endif + +#ifndef EXPORT_DEF +#define EXPORT_DEF extern +#endif + +#ifndef EXPORT_FUNC +#define EXPORT_FUNC /* nothing */ +#endif + +#endif /* FTCONFIG_H */ + + +/* END */ diff --git a/config/dos/FTOPTION.H b/config/dos/FTOPTION.H new file mode 100644 index 000000000..caded5014 --- /dev/null +++ b/config/dos/FTOPTION.H @@ -0,0 +1,152 @@ +#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 file contains macros that apply to */ + /* all of FreeType. Driver-specific configurations are placed in each */ + /* driver directory (e.g. `freetype/drivers/ttlib/ttconfig.h'). */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* 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're sure that you'll never use a font driver */ + /* with an alternate glyph format, this will reduce the size of the */ + /* base layer code. */ + /* */ +#define FT_CONFIG_OPTION_ALTERNATE_GLYPH_FORMATS + + /*************************************************************************/ + /* */ + /* GCC provides the non-ANSI `long long' 64-bit type. You can activate */ + /* it by defining the FTCALC_USE_LONG_LONG macro here. Note however */ + /* that we did not experience any improvement in speed with gcc, and */ + /* that the final code seems bigger when linked. */ + /* */ +#undef FTCALC_USE_LONG_LONG + + + /*************************************************************************/ + /* */ + /* When compiling FreeType as a DLL, some systems/compilers need a */ + /* special keyword in front of each function definition instead of */ + /* `extern'. */ + /* */ + /* The macros EXPORT_DEF and EXPORT_FUNC are thus used to define */ + /* exported library function interfaces and exported library functions */ + /* implementations respectively. */ + /* */ + /* If not defined here, they automatically default to `extern' and void */ + /* later in this header file. */ + /* */ +#undef EXPORT_DEF +#undef 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. */ + /* */ +#undef FT_DEBUG_LEVEL_ERROR +#undef FT_DEBUG_LEVEL_TRACE + + + /*************************************************************************/ + /* */ + /* Anti-aliasing support */ + /* */ + /* Undefine this macro only if you want to disable the anti-aliasing */ + /* support in FreeType. This will save you about 5 Kb of code. It */ + /* may be important for some embedded systems. */ + /* */ +#define FT_CONFIG_OPTION_ANTI_ALIAS + + + /*************************************************************************/ + /* */ + /* Endianess performance improvement */ + /* */ + /* FreeType is completely endian-independent, and can thus be compiled */ + /* directly on _any_ machine. However, some components of the library */ + /* provide improved routines for the cases where endianess is known. */ + /* */ + /* It usually results in speed-ups and reduced code size. Note that */ + /* you should not define both of these macros. */ + /* */ + /* */ + /* NOTE: For now, only the scan-line converter (base/ftraster.c) uses */ + /* these macros to speed-up some anti-alias rendering routines. */ + /* */ +#undef FT_CONFIG_OPTION_LITTLE_ENDIAN +#undef FT_CONFIG_OPTION_BIG_ENDIAN + + + /*************************************************************************/ + /* */ + /* Define this configuration macro whenever you want to build a version */ + /* of FreeType that does not include a default `system' component. */ + /* */ + /* Note that this will prevent the compilation of `ftinit', hence the */ + /* function FT_Init_FreeType */ + /* */ +#undef FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM + + + /*************************************************************************/ + /* */ + /* 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 4 Kb */ + /* */ +#define FT_RENDER_POOL_SIZE 32768 + + + /*************************************************************************/ + /* */ + /* FT_MAX_DRIVERS */ + /* */ + /* The maximum number of font drivers that can be registered in a */ + /* single FreeType library object. 8 seems to be a good choice due */ + /* to the relative low actual number of drivers ;-) */ + /* */ +#define FT_MAX_DRIVERS 8 + + + /*************************************************************************/ + /* */ + /* FT_MAX_GLYPH_FORMATS */ + /* */ + /* The maximum number of glyph image formats that might be registered */ + /* in a given library instance. 8 seems to be a good choice due to */ + /* the relatively low number of current formats ;-) */ + /* */ + +#define FT_MAX_GLYPH_FORMATS 8 + + + +#endif /* FTOPTION_H */ diff --git a/config/dos/FTSYSTEM.C b/config/dos/FTSYSTEM.C new file mode 100644 index 000000000..459f668e9 --- /dev/null +++ b/config/dos/FTSYSTEM.C @@ -0,0 +1,214 @@ +/************************************************************************** + * + * ftsystem.h 1.0 + * + * ANSI-specific FreeType low-level system interface + * + * This file contains the definition of interface used by FreeType + * to access low-level, i.e. memory management, i/o access as well + * as thread synchronisation. + * + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.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 + + /*********************************************************************/ + /* */ + /* MEMORY MANAGEMENT INTERFACE */ + /* */ + +/************************************************************************ + * + * + * FT_Alloc_Func + * + * + * The memory allocator function type + * + * + * system :: pointer to the system object + * size :: requested size in bytes + * + * + * block :: address of newly allocated block + * + * + * Error code. 0 means success. + * + * + * If your allocation routine ALWAYS zeroes the new block, you + * should set the flag FT_SYSTEM_FLAG_ALLOC_ZEROES in your system + * object 'flags' field. + * + * If you have set the flag FT_SYSTEM_FLAG_REPORT_CURRENT_ALLOC in + * your system's "system_flags" field, this function should update + * the "current_alloc" field of the system object. + * + ************************************************************************/ + + static + void* ft_alloc( FT_Memory memory, + long size ) + { + (void)memory; + return malloc(size); + } + + +/************************************************************************ + * + * + * FT_Realloc_Func + * + * + * The memory reallocator function type + * + * + * system :: pointer to the system object + * new_size :: new requested size in bytes + * + * + * block :: address of block in memory + * + * + * Error code. 0 means success. + * + * + * This function is _never_ called when the system flag + * FT_SYSTEM_FLAG_NO_REALLOC is set. Instead, the engine will emulate + * realloc through "alloc" and "free". + * + * Note that this is possible due to the fact that FreeType's + * "FT_Realloc" always requests the _current_ size of the reallocated + * block as a parameter, thus avoiding memory leaks. + * + * If you have set the flag FT_SYSTEM_FLAG_REPORT_CURRENT_ALLOC in + * your system's "system_flags" field, this function should update + * the "current_alloc" field of the system object. + * + ************************************************************************/ + + static + void* ft_realloc( FT_Memory memory, + long cur_size, + long new_size, + void* block ) + { + (void)memory; + (void)cur_size; + + return realloc( block, new_size ); + } + + +/************************************************************************ + * + * + * FT_Free_Func + * + * + * The memory release function type + * + * + * system :: pointer to the system object + * block :: address of block in memory + * + * + * If you have set the flag FT_SYSTEM_FLAG_REPORT_CURRENT_ALLOC in + * your system's "system_flags" field, this function should update + * the "current_alloc" field of the system object. + * + ************************************************************************/ + + static + void ft_free( FT_Memory memory, + void* block ) + { + (void)memory; + free( block ); + } + + /*********************************************************************/ + /* */ + /* RESOURCE MANAGEMENT INTERFACE */ + /* */ + + +#define STREAM_FILE(stream) ((FILE*)stream->descriptor.pointer) + + static + void ft_close_stream( FT_Stream stream ) + { + fclose( STREAM_FILE(stream) ); + } + + static + unsigned long ft_io_stream( FT_Stream stream, + unsigned long offset, + char* buffer, + unsigned long count ) + { + FILE* file; + + file = STREAM_FILE(stream); + + fseek( file, offset, SEEK_SET ); + return (unsigned long)fread( buffer, count, 1, file ); + } + + + extern + int FT_New_Stream( const char* filepathname, + FT_Stream stream ) + { + FILE* file; + + file = fopen( filepathname, "rb" ); + if (!file) + 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->pos = 0; + + stream->read = ft_io_stream; + stream->close = ft_close_stream; + + return 0; + } + + + extern + 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; + } + diff --git a/config/dos/MAKEFILE.GCC b/config/dos/MAKEFILE.GCC new file mode 100644 index 000000000..a7642cbe2 --- /dev/null +++ b/config/dos/MAKEFILE.GCC @@ -0,0 +1,172 @@ +#******************************************************************* +#* +#* FreeType 2 Configuration rules for Unix + gcc +#* +#* Copyright 1996-1999 by +#* David Turner, Robert Wilhelm, and Werner Lemberg. +#* +#* This file is part of the FreeType project, and may only be used +#* modified and distributed under the terms of the FreeType project +#* license, LICENSE.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 sub-Makefile is to define various build and +#* platform specific variables before including the sub-Makefile +#* containing the FreeType library rules, found in +#* +#* $(TOP)/config/freetype.mk +#* +#* The following variables must be defined before including this +#* file : +#* +#* TOP Pathname to the top of the FreeType sources +#* hierarchy +#* +#* This file should define the following variables before including +#* the FreeType library rules file : +#* +#* BUILD Pathname to the platform-specific files used +#* for the build. Usually `$(TOP)/config/' +#* +#* SEP Directory separator for the current platform. +#* Either / or \ (maybe : on Macs) +#* +#* DELETE The forced remove/delete command to erase one or more +#* files +#* +#* INCLUDE The location of all public header files. e.g. +#* `$(TOP)/include'include' * +#* +#* SRC The directory containing all sources. e.g. +#* '$(TOP)/src' +#* +#* OBJ_DIR The location where compiled object files will be +#* placed, e.g. '$(TOP)/obj' +#* +#* LIB_DIR The location where the resulting library file will be +#* placed, e.g. '$(TOP)/obj' +#* +#* LIBRARY The filename of the resulting library file, without +#* its extension.. e.g. 'libfreetype' or 'freetype' +#* +#* O The object file suffix. Can be '.o', '.obj,' '.lo,' +#* ';coff,' etc. +#* +#* A The library file suffix. Can be '.a' '.so,' '.lib' +#* '.dll,' etc. +#* +#* I The path inclusion flag. Some compilers use a +#* different flag than '-I' to specify an additional +#* include path. Examples are '/i=' or '-J ', etc. +#* +#* D The macro definition flag. I haven't met compilers +#* which don't use the '-D' switch to define a macro, but +#* who knows... +#* +#* T The compilation flag used to identify the target. Some +#* compilers use a different flag than '-o ' to specify +#* the name of the target object file. +#* +#* CFLAGS The set of flags used to compile object files. +#* (usually contains the flag '-c'). +#* +#* +#* +#******************************************************************* + +ifndef TOP +TOP := . +endif + +DELETE := rm -f +SEP := / +BUILD := $(TOP)/config/dos +PLATFORM := dos + +# the directory where all object files are placed +# +OBJ_DIR := $(TOP)/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, this can be .o, .tco, .obj, etc.. +# depending on the platform +# +O := o + +# the library file extension, this can be .a, .lib, etc.. +# depending on the platform +# +A := 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", etc... +# +I := -I + + +# 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 + + +# C flag used to define a macro before the compilation of a given +# source object. Usually is '-D' like in "-DDEBUG" +# +D := -D + + +# Target flag - beware, there is a space after the 'o' !! +# +# +T := -o + +# C flags +# +# These should concern : +# +# - debug output +# - optimization +# - warnings +# - ansi compliance.. +# +ifndef CFLAGS +CFLAGS := -c -g -O6 -Wall +endif + +ifdef BUILD_FREETYPE + +include $(TOP)/config/freetype.mk + + +# 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) $@ + $(AR) -r $@ $(OBJECTS_LIST) + +endif diff --git a/config/dos/detect.mk b/config/dos/detect.mk new file mode 100644 index 000000000..9fe4400b9 --- /dev/null +++ b/config/dos/detect.mk @@ -0,0 +1,87 @@ +# +# This file is used to detect a DOS host platform. +# +# This configuration file to be used depends on the value of the CC +# environment variable. +# +# + +# 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're 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 +# there. +# +# 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 gcc, i.e. DJGPP by default. Aren't we biased ;-) +# +# +CONFIG_FILE := Makefile.gcc +SEP := / +ifndef CC +CC := gcc +endif + + +ifneq ($(findstring turboc,$(MAKECMDGOALS)),) # Turbo C +CONFIG_FILE := Makefile.tcc +SEP := $(BACKSLASH) +CC := tcc +.PHONY: turboc +endif + +ifneq ($(findstring watcom,$(MAKECMDGOALS)),) # Watcom C/C++ +CONFIG_FILE := Makefile.wat +SEP := $(BACKSLASH) +CC := wcc386 +.PHONY: watcom +endif + +ifneq ($(findstring borlandc16,$(MAKECMDGOALS)),) # Borland C/C++ 16 bits +CONFIG_FILE := Makefile.bcc +SEP := $(BACKSLASH) +CC := bcc +.PHONY: borlandc16 +endif + +ifneq ($(findstring borlandc,$(MAKECMDGOALS)),) # Borland C/C++ 32 bits +CONFIG_FILE := Makefile.bcc +SEP := $(BACKSLASH) +CC := bcc32 +.PHONY: borlandc +endif + +CONFIG_RULES := $(TOP)\config\dos\$(CONFIG_FILE) + +# use the Dos version of the "setup dump" +# +setup: dos_setup + +endif # test Dos +endif # test COMSPEC +endif # test PLATFORM + diff --git a/config/dos/ftoption.h b/config/dos/ftoption.h new file mode 100644 index 000000000..852f65fbb --- /dev/null +++ b/config/dos/ftoption.h @@ -0,0 +1,162 @@ +#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 file contains macros that apply to */ + /* all of FreeType. Driver-specific configurations are placed in each */ + /* driver directory (e.g. `freetype/drivers/ttlib/ttconfig.h'). */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* 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're sure that you'll never use a font driver */ + /* with an alternate glyph format, this will reduce the size of the */ + /* base layer code. */ + /* */ +#define FT_CONFIG_OPTION_ALTERNATE_GLYPH_FORMATS + + /*************************************************************************/ + /* */ + /* GCC provides the non-ANSI `long long' 64-bit type. You can activate */ + /* it by defining the FTCALC_USE_LONG_LONG macro here. Note however */ + /* that we did not experience any improvement in speed with gcc, and */ + /* that the final code seems bigger when linked. */ + /* */ +#undef FTCALC_USE_LONG_LONG + + + /*************************************************************************/ + /* */ + /* When compiling FreeType as a DLL, some systems/compilers need a */ + /* special keyword in front of each function definition instead of */ + /* `extern'. */ + /* */ + /* The macros EXPORT_DEF and EXPORT_FUNC are thus used to define */ + /* exported library function interfaces and exported library functions */ + /* implementations respectively. */ + /* */ + /* If not defined here, they automatically default to `extern' and void */ + /* later in this header file. */ + /* */ +#undef EXPORT_DEF +#undef 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. */ + /* */ +#undef FT_DEBUG_LEVEL_ERROR +#undef FT_DEBUG_LEVEL_TRACE + + + /*************************************************************************/ + /* */ + /* Anti-aliasing support */ + /* */ + /* Undefine this macro only if you want to disable the anti-aliasing */ + /* support in FreeType. This will save you about 5 Kb of code. It */ + /* may be important for some embedded systems. */ + /* */ +#define FT_CONFIG_OPTION_ANTI_ALIAS + + + /*************************************************************************/ + /* */ + /* Endianess performance improvement */ + /* */ + /* FreeType is completely endian-independent, and can thus be compiled */ + /* directly on _any_ machine. However, some components of the library */ + /* provide improved routines for the cases where endianess is known. */ + /* */ + /* It usually results in speed-ups and reduced code size. Note that */ + /* you should not define both of these macros. */ + /* */ + /* */ + /* NOTE: For now, only the scan-line converter (base/ftraster.c) uses */ + /* these macros to speed-up some anti-alias rendering routines. */ + /* */ +#undef FT_CONFIG_OPTION_LITTLE_ENDIAN +#undef FT_CONFIG_OPTION_BIG_ENDIAN + + + /*************************************************************************/ + /* */ + /* Define this configuration macro whenever you want to build a version */ + /* of FreeType that does not include a default `system' component. */ + /* */ + /* Note that this will prevent the compilation of `ftinit', hence the */ + /* function FT_Init_FreeType */ + /* */ +#undef FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM + + + /*************************************************************************/ + /* */ + /* 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 4 Kb */ + /* */ +#define FT_RENDER_POOL_SIZE 32768 + + + /*************************************************************************/ + /* */ + /* FT_MAX_DRIVERS */ + /* */ + /* The maximum number of font drivers that can be registered in a */ + /* single FreeType library object. 8 seems to be a good choice due */ + /* to the relative low actual number of drivers ;-) */ + /* */ +#define FT_MAX_DRIVERS 8 + + + /*************************************************************************/ + /* */ + /* FT_MAX_EXTENSIONS */ + /* */ + /* The maximum number of extensions that can be registered in a */ + /* single font driver. 8 seems to be a good choice for now.. */ + /* */ +#define FT_MAX_EXTENSIONS 8 + + + /*************************************************************************/ + /* */ + /* FT_MAX_GLYPH_FORMATS */ + /* */ + /* The maximum number of glyph image formats that might be registered */ + /* in a given library instance. 8 seems to be a good choice due to */ + /* the relatively low number of current formats ;-) */ + /* */ + +#define FT_MAX_GLYPH_FORMATS 8 + + + +#endif /* FTOPTION_H */ diff --git a/config/dos/ftsys.c b/config/dos/ftsys.c new file mode 100644 index 000000000..e276dfcd8 --- /dev/null +++ b/config/dos/ftsys.c @@ -0,0 +1,866 @@ +/******************************************************************* + * + * ftsys.c + * + * ANSI-specific system operations. + * + * Copyright 1996-1998 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.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 implementation of the 'ftsys' component uses the standard + * ANSI C library. + * + * IMPORTANT NOTE : + * + * Porters, read carefully the comments in ftsys.h before trying + * to port this file to your system. It contains many essential + * remarks, and will ease your work greatly.. + * + ******************************************************************/ + +#include "ftsys.h" +#include "ftstream.h" +#include "ftdebug.h" + + +/* The macro FT_COMPONENT is used in trace mode. It is an implicit */ +/* parameter of the PTRACE and PERROR macros, used to print/log */ +/* messages during execution.. */ +/* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_io + + +#undef CUR_SYSTEM /* just in case */ + + +/* To ease porting, we use the macro SYS_STREAM to name the system-specific */ +/* stream type. For example, it is a "FILE*" with the ANSI libc, it will be */ +/* a file descriptor, i.e. an integer, when using the Unix system api, etc. */ + +#define SYS_STREAM FILE* + + + /* This implementation of ftsys uses the ANSI C library. Memory */ + /* management is performed through malloc/free, i/o access through */ + /* fopen/fread/fseek, and no synchronisation primitive is implemented */ + /* (they contain dummy code) */ + + + +/**************************************************************************/ +/* */ +/* I/O ACCESS AND MANAGEMENT */ +/* */ +/* We only define the "ANSI" resource class in this class. It is */ +/* disk-based, and provides a MRU cache, in order to only keep the file */ +/* descriptors of the 10 most recently used resource files. */ +/* */ +/* it simply contains two lists. One contains the "cached" resources */ +/* with a valid FILE* pointer, the second contains all other "flushed" */ +/* resource objects. */ +/* */ + +/* The FT_ANSI_File class derives from FT_ResourceRec - description : */ +/* */ +/* FT_AnsiFileRec */ +/* */ +/* */ +/* */ +/* root :: */ +/* the root resource class fields. */ +/* */ +/* pathname :: */ +/* this is a copy of the ANSI file pathname used to open streams */ +/* for the resource. A different implementation is free to use */ +/* unicode chars, or file i-node numbers, etc.. */ +/* */ +/* file_size :: */ +/* the size in bytes of the resource. This field should be set to */ +/* -1 until the resource is first opened.. */ +/* */ + +#include + + typedef struct FT_AnsiFileRec_ + { + FT_ResourceRec root; + char* pathname; /* the font file's pathname */ + FT_Long file_size; /* file size in bytes */ + + } FT_AnsiFileRec, *FT_AnsiFile; + + +/* We use the macro STREAM_Name as a convenience to return a given */ +/* ANSI resource's pathname. Its "stream" argument is a FT_Resource */ +/* which is typecasted to the FT_AnsiFile class */ +#define STREAM_Name(stream) ((FT_AnsiFile)stream->resource)->pathname + +/* We use the macro STREAM_File as a convenience to extract the */ +/* system-specific stream handle from a given FreeType stream object */ +#define STREAM_File(stream) ((FILE*)stream->stream_id.pointer) + + + +/***************************************************************************/ +/* */ +/* AnsiFile_Open */ +/* */ +/* */ +/* This function is used to open a system-stream for a given resource. */ +/* */ +/* Note that it must update the target FreeType stream object with the */ +/* system-stream handle and the resource's size. */ +/* */ +/* Also, the 'stream->base' field must be set to NULL for disk-based */ +/* resource, and to the address in memory of the resource's first byte */ +/* for a memory-based one. */ +/* */ +/* */ +/* resource :: the source resource */ +/* stream :: the target stream object */ +/* */ +/* */ +/* Error code */ +/* */ +/* */ +/* This function simply calls fopen in the resource's file pathname */ +/* */ +/* The stream object IS NOT CREATED by this function, but by its caller. */ +/* */ +/***************************************************************************/ + + static + FT_Error AnsiFile_Open( FT_AnsiFile resource, + FT_Stream stream ) + { + FILE* file; + + /* open the file */ + file = fopen( resource->pathname, "rb" ); + if (!file) + { + PERROR(( "AnsiFile_Open: could not open file '%s'\n", + resource->pathname )); + return FT_Err_Cannot_Open_Stream; + } + + /* compute file size if necessary */ + if ( resource->file_size < 0 ) + { + fseek( file, 0, SEEK_END ); + resource->file_size = ftell(file); + fseek( file, 0, SEEK_SET ); + } + + stream->resource = (FT_Resource)resource; + stream->stream_id.pointer = file; + stream->size = resource->file_size; + + /* it's a disk-based resource, we don't need to use the "base" and */ + /* "cursor" fields of the stream objects */ + stream->base = NULL; + stream->cursor = NULL; + + PTRACE1(( "AnsiFile_Open: opened '%s' (%d bytes) succesfully\n", + resource->pathname, resource->file_size )); + + return FT_Err_Ok; + } + + +/***************************************************************************/ +/* */ +/* AnsiFile_Close */ +/* */ +/* Closes a given stream */ +/* */ +/* */ +/* stream :: the target stream object */ +/* */ +/* */ +/* Error code */ +/* */ +/* */ +/* This function simply calls fclose on the stream's ANSI FILE object */ +/* */ +/***************************************************************************/ + + static + FT_Error AnsiFile_Close( FT_Stream stream ) + { + PTRACE1(( "Closing file '%s'\n", STREAM_Name(stream) )); + + fclose( STREAM_File(stream) ); + + stream->resource = NULL; + stream->stream_id.pointer = NULL; + stream->size = 0; + + return FT_Err_Ok; + } + + +/***************************************************************************/ +/* */ +/* AnsiFile_Seek */ +/* */ +/* Seek a stream to a given position */ +/* */ +/* */ +/* stream :: the target stream object */ +/* position :: offset in bytes from start of resource/stream */ +/* */ +/* */ +/* Error code */ +/* */ +/* */ +/* This function simply calls fseek on the stream. */ +/* */ +/* The "seek" method is never called by the stream manager in the case */ +/* of a memory-based resource (i.e. when 'stream->base' isn't NULL). */ +/* */ +/***************************************************************************/ + + static + FT_Error AnsiFile_Seek( FT_Stream stream, + FT_Long position ) + { + if ( fseek( STREAM_File(stream), position, SEEK_SET ) ) + { + PERROR(( "AnsiFile_Seek : FAILED !! pos. %ld of '%s'\n", + position, STREAM_Name(stream) )); + + return FT_Err_Invalid_Stream_Seek; + } + + PTRACE2(( "AnsiFile_Seek : pos. %ld of '%s'\n", + position, STREAM_Name(stream) )); + + return FT_Err_Ok; + } + + +/***************************************************************************/ +/* */ +/* AnsiFile_Skip */ +/* */ +/* Skip a given number of bytes in an ANSI stream. */ +/* Useful to skip pad bytes, for example. */ +/* */ +/* */ +/* stream :: the target stream object */ +/* count :: number of bytes to skip in the stream */ +/* */ +/* */ +/* Error code */ +/* */ +/* */ +/* This function simply calls fseek on the stream. */ +/* */ +/* The "skip" method is never called by the stream manager in the case */ +/* of a memory-based resource (i.e. when 'stream->base' isn't NULL). */ +/* */ +/***************************************************************************/ + + static + FT_Error AnsiFile_Skip( FT_Stream stream, + FT_Long count ) + { + if ( fseek( STREAM_File(stream), count, SEEK_CUR ) ) + { + PERROR(( "AnsiFile_Skip : FAILED !! %ld bytes in '%s'\n", + count, STREAM_Name(stream) )); + + return FT_Err_Invalid_Stream_Seek; + } + + PTRACE2(( "AnsiFile_Skip : %ld bytes in '%s'\n",count, + STREAM_Name(stream) )); + + return FT_Err_Ok; + } + +/***************************************************************************/ +/* */ +/* AnsiFile_Pos */ +/* */ +/* Returns the current offset within an ANSI stream's */ +/* resource. */ +/* */ +/* */ +/* stream :: the target stream object */ +/* */ +/* */ +/* position :: current offset. -1 in case of error */ +/* */ +/* */ +/* Error code. */ +/* */ +/* */ +/* This function simply calls ftell on the stream. */ +/* */ +/* The "pos" method is never called by the stream manager in the case */ +/* of a memory-based resource (i.e. when 'stream->base' isn't NULL). */ +/* */ +/***************************************************************************/ + + static + FT_Error AnsiFile_Pos( FT_Stream stream, + FT_Long* position ) + { + *position = ftell( STREAM_File(stream) ); + if ( *position == -1 ) + { + PTRACE2(( "AnsiFile_Pos : FAILED !! in '%s'\n", STREAM_Name(stream) )); + return FT_Err_Invalid_Stream_Seek; + } + + PTRACE2(( "AnsiFile_Pos : for '%s'\n", STREAM_Name(stream) )); + return FT_Err_Ok; + } + +/***************************************************************************/ +/* */ +/* AnsiFile_Read */ +/* */ +/* Read a given number of bytes from an ANSI stream into */ +/* memory. */ +/* */ +/* */ +/* stream :: the target stream object */ +/* buffer :: the target read buffer where data is copied */ +/* size :: number of bytes to read from the stream */ +/* */ +/* */ +/* read_bytes :: the number of bytes effectively read from the stream */ +/* used in case of error (i.e. FT_Err_Invalid_Stream_Read) */ +/* by some parts of the library.. */ +/* */ +/* Error code */ +/* */ +/* */ +/* This function simply calls fread on the stream. */ +/* */ +/* It MUST return the error FT_Err_Invalid_Stream_Read in case of */ +/* an over-read (i.e. reading more bytes from the stream that what */ +/* is left int), as the stream component checks for this specific */ +/* value.. */ +/* */ +/* The "read" method is never called by the stream manager in the case */ +/* of a memory-based resource (i.e. when 'stream->base' isn't NULL). */ +/* */ +/***************************************************************************/ + + static + FT_Error AnsiFile_Read( FT_Stream stream, + FT_Char* buffer, + FT_Long size, + FT_Long* read_bytes ) + { + *read_bytes = fread( buffer, 1, size, STREAM_File(stream) ); + if ( *read_bytes != size ) + { + /* Note : we can have an over-read here when called by the */ + /* function FT_Access_Compressed_Frame. This means */ + /* that the following message should be a trace, */ + /* rather than an error for disk-based resources.. */ + /* */ + /* the function must set the value of 'read_bytes' */ + /* even if it returns an error code.. */ + PTRACE2(( "AnsiFile_Read : FAILED !! read %ld bytes from '%s'\n", + size, STREAM_Name(stream) )); + + return FT_Err_Invalid_Stream_Read; + } + + PTRACE2(( "AnsiFile_Read : read %ld bytes to buffer 0x%08lx from '%s'\n", + size, (long)buffer, STREAM_Name(stream) )); + return FT_Err_Ok; + } + +/* The following table is the "virtual method table" for the 'ANSI */ +/* resource class', which methods are defined above. Its address is */ +/* set in the 'interface' field of all resource objects created by */ +/* the function FT_Create_AnsiFile (see below) */ + + static + FTRes_InterfaceRec FT_AnsiFile_Interface = + { + (FTRes_Open_Func) AnsiFile_Open, + (FTRes_Close_Func) AnsiFile_Close, + (FTRes_Seek_Func) AnsiFile_Seek, + (FTRes_Skip_Func) AnsiFile_Skip, + (FTRes_Pos_Func) AnsiFile_Pos, + (FTRes_Read_Func) AnsiFile_Read, + }; + + +/***************************************************************************/ +/* */ +/* FT_Create_Resource */ +/* */ +/* Creates a new resource object, of class "AnsiFile". */ +/* This function is never called directly by the font */ +/* drivers. Only by the higher-level part of FreeType */ +/* (called the HLib), or client applications */ +/* */ +/* */ +/* pathname :: the file's pathname, in ASCII */ +/* */ +/* */ +/* Handle/pointer to the new resource object. NULL in case of error */ +/* */ +/* */ +/* This functions does not open a stream. It simply copies the */ +/* pathname within a fresh new resource object. */ +/* */ +/***************************************************************************/ + + EXPORT_FUNC + FT_Error FT_Create_Resource( FT_Library library, + const char* pathname, + FT_Resource* aresource ) + { + FT_Int len; + FT_AnsiFile resource; + FT_Error error; + FT_System system = library->system; + + if ( !pathname ) + goto Fail_Null; + + len = strlen(pathname); + if (len == 0) + goto Fail_Null; + + resource = NULL; + + if ( ALLOC( resource, sizeof(*resource) ) || + ALLOC( resource->pathname, len+1 ) ) + goto Fail_Memory; + + resource->root.library = library; + resource->root.interface = &FT_AnsiFile_Interface; + resource->root.flags = FT_RESOURCE_TYPE_DISK_BASED; + resource->file_size = -1; + strcpy( resource->pathname, pathname ); + + PTRACE1(( "Create_AnsiFile : Ansi resource created for '%s'\n", + pathname )); + + *aresource = (FT_Resource)resource; + return FT_Err_Ok; + + Fail_Null: + PERROR(( "Create_AnsiFile : null pathname !!\n" )); + return FT_Err_Invalid_Argument; + + Fail_Memory: + if (resource) + FREE( resource->pathname ); + FREE( resource ); + PERROR(( "Create_AnsiFile : not enough memory to create resource !\n" )); + return error; + } + + +/***************************************************************************/ +/* */ +/* FT_Destroy_Resource */ +/* */ +/* Destroys an ANSI resource object. */ +/* This function is never called directly by the font */ +/* drivers. Only by the higher-level part of FreeType */ +/* (called the HLib), or client applications */ +/* */ +/* */ +/* resource :: the Ansi resource object */ +/* */ +/* */ +/* This functions does not check that runs or streams are opened for */ +/* the resource (for now, we assume developer intelligence. We'll most */ +/* probably lower our standard later to ease debugging ;-) */ +/* */ +/***************************************************************************/ + + EXPORT_FUNC + FT_Error FT_Destroy_Resource( FT_Resource resource ) + { + FT_System system = resource->library->system; + FT_AnsiFile ansi = (FT_AnsiFile)resource; + + if ( !ansi || ansi->root.interface != &FT_AnsiFile_Interface ) + { + PERROR(( + "Destroy_AnsiFile : Trying to destroy an invalid resource !!\n" )); + return FT_Err_Invalid_Resource_Handle; + } + + PTRACE1(( "Destroy_AnsiFile : destroying resource for '%s'\n", + ansi->pathname )); + + FREE( ansi->pathname ); + FREE( ansi ); + + return FT_Err_Ok; + } + + + +/**************************************************************************/ +/* */ +/* MEMORY MANAGEMENT */ +/* */ +/* */ +/* This part copies the old FreeType 1.0 and 1.1 memory management */ +/* scheme that was defined in the file "ttmemory.h". One can see that */ +/* */ +/* - a set of macros is defined for the memory operations used */ +/* by the engine ( MEM_Copy, MEM_Move, MEM_Set ). This comes from */ +/* the fact that many compilers are able to inline these ops directly */ +/* within the compiled code, rather than generating a call to the */ +/* C library. However, this obliges us to include the */ +/* header file. */ +/* */ +/* If you provide your own memory operations routine, you can get */ +/* rid of the #include below. */ +/* */ +/* */ +/* - the FT_Alloc function has several essential properties that */ +/* MUST be retained by each port : */ +/* */ +/* - it returns an error code, NOT the allocated block's base */ +/* address */ +/* */ +/* - it takes the address of a target pointer, where the block's */ +/* base address will be set. if the size is zero, its value */ +/* will be NULL and the function returns successfully */ +/* */ +/* - in case of error, the pointer's value is set to NULL and */ +/* an error code is returned.. */ +/* */ +/* - the new allocated block MUST be zero-filled. This is a strong */ +/* convetion the rest of the engine relies on */ +/* */ +/* */ +/* */ +/* - the FT_Free function has also its essentials : */ +/* */ +/* - it takes the address of a pointer which value is the block's */ +/* base address. This is UNLIKE a standard "free" which takes the */ +/* the block's base directly. */ +/* */ +/* - it accepts succesfully the address of a pointer which value */ +/* is NULL, in which case it simply returns. */ +/* */ +/* - the pointer is always set to NULL by the function */ +/* */ +/* */ +/* - the MEM_Alloc, ALLOC and ALLOC_ARRAY macros are used by the */ +/* library, and should NOT be modified by porters !! */ +/* */ + +/* The macro FT_COMPONENT is used in trace mode. It is an implicit */ +/* parameter of the PTRACE and PERROR macros, used to print/log */ +/* messages during execution.. */ +/* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_memory + + +#include + +/**************************************************************************/ +/* */ +/* FT_Alloc */ +/* */ +/* */ +/* Allocates a new bloc of memory. The returned area is always */ +/* zero-filled, this is a strong convention in many FreeType parts */ +/* */ +/* */ +/* system :: handle to a given 'system object' where allocation */ +/* occurs.. */ +/* */ +/* size :: size in bytes of the block to allocate */ +/* */ +/* */ +/* P :: pointer to the fresh new block. It should be set */ +/* to NULL if 'size' is 0, of in case of error.. */ +/* */ +/* */ +/* FreeType error code. 0 means success. */ +/* */ +/**************************************************************************/ + + BASE_FUNC + FT_Error FT_Alloc( FT_System system, + long size, + void* *P ) + { + + if (!P) + { + PERROR(( "FT_Alloc : invalid pointer address !!\n" )); + return FT_Err_Invalid_Argument; + } + + if ( size > 0 ) + { + *P = malloc( size ); + if ( !*P ) + { + PERROR(( "FT_Alloc : out of memory (%ld bytes requested) !!\n", + size )); + + return FT_Err_Out_Of_Memory; + } + + system->total_alloc += size; + + /* ALWAYS ZERO-FILL THE BLOCK !!!!! */ + MEM_Set( *P, 0, size ); + } + else + *P = NULL; + + PTRACE2(( "FT_Alloc : size = %ld, pointer = 0x%08lx, block = 0x%08lx\n", + size, (long)P, (long)*P )); + + return FT_Err_Ok; + } + + +/**************************************************************************/ +/* */ +/* FT_Realloc */ +/* */ +/* */ +/* Reallocates a block of memory pointed to by '*P' to 'Size' */ +/* bytes from the hea^, possibly changing '*P'. */ +/* */ +/* */ +/* system :: handle to a given 'system object' where allocation */ +/* occurs.. */ +/* */ +/* size :: size in bytes of the block to allocate */ +/* */ +/* */ +/* P :: pointer to the fresh new block. It should be set */ +/* to NULL if 'size' is 0, of in case of error.. */ +/* */ +/* */ +/* FreeType error code. 0 means success. */ +/* */ + + BASE_FUNC + int FT_Realloc( FT_System system, + long size, + void* *P ) + { + void* Q; + + if (!P) + { + PERROR(( "FT_Realloc : invalid pointer address !!\n" )); + return FT_Err_Invalid_Argument; + } + + /* if the original pointer is NULL, call FT_Alloc */ + if (!*P) + return FT_Alloc( system, size, P ); + + /* if the new block if zero-sized, clear the current one */ + if (size <= 0) + return FT_Free( system, P ); + + Q = (void*)realloc( *P, size ); + if (!Q) + { + PERROR(( "FT_Realloc : reallocation failed\n" )); + return FT_Err_Out_Of_Memory; + } + + *P = Q; + return FT_Err_Ok; + } + + +/**************************************************************************/ +/* */ +/* FT_Free */ +/* */ +/* */ +/* Releases a given block of memory allocated through FT_Alloc */ +/* */ +/* */ +/* system :: handle to a given 'system object' where allocation */ +/* occured.. */ +/* */ +/* 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 successfuly. This */ +/* is a strong convention within all of FreeType and its drivers.. */ +/* */ + + BASE_FUNC + FT_Error FT_Free( FT_System system, + void* *P ) + { + (void)system; /* unused parameter. Gets rid of warnings */ + + PTRACE2(( "FT_Free : freeing pointer 0x%08lx (block 0x%08lx)\n", + (long)P, (P ? (long)*P : -1) )); + + if ( !P || !*P ) + return FT_Err_Ok; + + free( *P ); + *P = NULL; + + return FT_Err_Ok; + } + +/**************************************************************************/ +/* */ +/* SYNCHRONIZATION MANAGEMENT */ +/* */ +/* */ +/* This section deals with mutexes. The library can be compiled to */ +/* three distinct thread-support levels ( namely single-threaded, */ +/* thread-safe and re-entrant modes ). */ +/* */ +/* It protects its variables through the MUTEX_Lock and MUTEX_Release */ +/* macros which are void in single-threaded mode. */ +/* */ +/* */ +/* It defines a type-less mutex reference type, "TMutex", that you're */ +/* free to redefine for your system's needs.. */ +/* */ +/* The default implementation of ftsys.c contains only dummy functions */ +/* which always return succesfully. you NEED to specialize them in */ +/* order to port ftsys.c in any multi-threaded environment... */ +/* */ + +/* The macro FT_COMPONENT is used in trace mode. It is an implicit */ +/* parameter of the PTRACE and PERROR macros, used to print/log */ +/* messages during execution.. */ +/* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_sync + +#ifdef FT_CONFIG_THREADS + + + BASE_FUNC + FT_Error FT_Mutex_Create ( FT_System system, + TMutex* mutex ) + { + (void)system; /* unused parameter. Gets rid of warnings */ + + mutex = (void*)-1; + system->num_mutexes++; + return FT_Err_Ok; + /* Replace this line with your own mutex creation code */ + } + + + BASE_FUNC + void FT_Mutex_Delete ( FT_System system, + TMutex* mutex ) + { + (void)system; /* unused parameter. Gets rid of warnings */ + + mutex = (void*)0; + system->num_mutexes--; + /* Replace this line with your own mutex destruction code */ + } + + BASE_FUNC + void FT_Mutex_Lock ( FT_System system, + TMutex* mutex ) + { + /* NOTE: It is legal to call this function with a NULL argument */ + /* in which case an immediate return is appropriate. */ + (void)system; /* unused parameter. Gets rid of warnings */ + + if ( !mutex ) + return; + + ; /* Insert your own mutex locking code here */ + } + + + void FT_Mutex_Release( FT_System system, + TMutex* mutex ) + { + /* NOTE: It is legal to call this function with a NULL argument */ + /* in which case an immediate return is appropriate */ + (void)system; /* unused parameter. Gets rid of warnings */ + + if ( !mutex ) + return; + ; /* Insert your own mutex release code here */ + } + +#endif /* FT_CONFIG_THREADS */ + + + + + EXPORT_FUNC + FT_Error FT_New_System( FT_System* system ) + { + *system = (FT_System)malloc( sizeof(**system) ); + if ( !*system ) + return FT_Err_Out_Of_Memory; + + /* the ANSI function 'free' is unable to return the number */ + /* of released bytes. Hence, the 'current_alloc' field of the */ + /* system object cannot be used */ + + (*system)->system_flags = FT_SYSTEM_FLAG_TOTAL_ALLOC | + FT_SYSTEM_FLAG_MUTEXES; + (*system)->total_alloc = 0; + (*system)->num_mutexes = 0; + + /* initialise i/o management (nothing) */ + + /* initialise synchronisation (nothing) */ + + /* initialise streams */ + + return FT_Err_Ok; + } + + + + EXPORT_FUNC + FT_Error FT_Done_System( FT_System system ) + { + /* finalise syncrhonisation (nothing) */ + + /* finalise i/o management (nothing) */ + + /* finalise memory management */ + free( system ); + + return FT_Err_Ok; + } + + + + diff --git a/config/freetype.mk b/config/freetype.mk new file mode 100644 index 000000000..4f78e08ab --- /dev/null +++ b/config/freetype.mk @@ -0,0 +1,199 @@ +#**************************************************************************** +#* * +#* FreeType library sub-Makefile * +#* * +#* Copyright 1996-1999 by * +#* David Turner, Robert Wilhelm, and Werner Lemberg. * +#* * +#* This file is part of the FreeType project, and may only be used * +#* modified and distributed under the terms of the FreeType project * +#* license, LICENSE.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 targets `objects', `library' and `multiple' are defined +# at the end of this Makefile when all rules have been included.. +# +.PHONY: build_freetype objects library + +# default target - build objects and library +# +build_freetype: objects library + +# `multi' target - build multiple objects and library +# +multi: objects library + + +# The FreeType sources directory. +# +SRC := $(TOP)$(SEP)src + + +# The directory where the base layer components are placed. +# By default, this is 'freetype/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) + +# The name of the final library file. +# +FT_LIBRARY := $(LIB_DIR)$(SEP)$(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/arch/' directory, as these files +# will override the default sources. +# +INCLUDES := $(BUILD) $(TOP)$(SEP)include $(INCLUDES) + +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 'config/' directories, +# debug/optimization/warning flags + ansi compliance if needed. +# +FT_CFLAGS = $(CFLAGS) $(INCLUDE_FLAGS) +FT_CC = $(CC) $(FT_CFLAGS) +FT_COMPILE = $(FT_CC) + + +# +# Free the lists of driver objects +# +COMPONENTS_LIST := +DRIVERS_LIST := +OBJECTS_LIST := + +# free the list of 'ftinit' variables +# +FTINIT_DRIVER_PATHS := +FTINIT_DRIVER_H := +FTINIT_DRIVER_MACROS := + + +# System-specific component - this must be defined in this Makefile +# for easy updates +# +# BASE_H is defined in src/base/rules.mk and contains the list of all +# base layer header files. +# +FTSYS_SRC = $(BUILD)$(SEP)ftsystem.c +FTSYS_OBJ = $(OBJ_DIR)$(SEP)ftsystem.$O + +OBJECTS_LIST += $(FTSYS_OBJ) + +$(FTSYS_OBJ): $(FTSYS_SRC) $(BASE_H) + $(FT_COMPILE) $T$@ $< + + +# ftdebug component +# +# +# + +FTDEBUG_SRC = $(BASE_)ftdebug.c +FTDEBUG_OBJ = $(OBJ_)ftdebug.$O + +OBJECTS_LIST += $(FTDEBUG_OBJ) + +$(FTDEBUG_OBJ): $(FTDEBUG_SRC) $(BASE_H) + $(FT_COMPILE) $T$@ $< + + + +# Define PUBLIC_H as the list of all public header files located in +# `$(TOP)/include' +# +PUBLIC_H := $(wildcard $(PUBLIC_)*.h) + + +# Include all rule files from FreeType components +# +# +include $(wildcard $(SRC)/*/rules.mk) + +# FTInit file: +# +# The C source 'ftinit.c' contains the FreeType initialisation 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_xxxx lists +# which contain additional include paths and macros used to compile the +# single 'ftapi.c' source. +# +FTINIT_SRC := $(BASE_DIR)$(SEP)ftinit.c +FTINIT_OBJ := $(OBJ_)ftinit.$O + +$(FTINIT_OBJ): $(FTINIT_SRC) $(BASE_H) $(FTINIT_DRIVER_H) + $(FT_COMPILE) $(FTINIT_DRIVER_PATHS:%=$I%) \ + $(FTINIT_DRIVER_MACROS:%=$D%) $T$@ $< + + +# All FreeType library objects +# +# By default, we include the base layer extensions. These could be +# ommitted on builds which do not want them. +# +OBJ_M = $(BASE_OBJ_M) $(BASE_EXT_OBJ) $(DRV_OBJS_M) \ + $(FTSYS_OBJ) $(FTINIT_OBJ) $(FTDEBUG_OBJ) + +OBJ_S = $(BASE_OBJ_S) $(BASE_EXT_OBJ) $(DRV_OBJS_S) \ + $(FTSYS_OBJ) $(FTINIT_OBJ) $(FTDEBUG_OBJ) + +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$@ $< + + +clean_freetype: + -$(DELETE) $(OBJ_S:/=$(SEP)) $(OBJ_M:/=$(SEP)) + + +distclean_freetype: clean_freetype + -$(DELETE) $(FT_LIBRARY:/=$(SEP)) + -$(DELETE) *.orig *~ core *.core + +remove_config_mk: + -$(DELETE) $(CONFIG_MK:/=$(SEP)) + +clean: clean_freetype +distclean: distclean_freetype remove_config_mk + +# END diff --git a/config/os2/Makefile.emx b/config/os2/Makefile.emx new file mode 100644 index 000000000..75394ead8 --- /dev/null +++ b/config/os2/Makefile.emx @@ -0,0 +1,196 @@ +#******************************************************************* +#* +#* FreeType 2 Configuration rules for Unix + gcc +#* +#* Copyright 1996-1999 by +#* David Turner, Robert Wilhelm, and Werner Lemberg. +#* +#* This file is part of the FreeType project, and may only be used +#* modified and distributed under the terms of the FreeType project +#* license, LICENSE.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 sub-Makefile is to define various build and +#* platform specific variables before including the sub-Makefile +#* containing the FreeType library rules, found in +#* +#* $(TOP)/config/freetype.mk +#* +#* The following variables must be defined before including this +#* file : +#* +#* TOP Pathname to the top of the FreeType sources +#* hierarchy +#* +#* This file should define the following variables before including +#* the FreeType library rules file : +#* +#* BUILD Pathname to the platform-specific files used +#* for the build. Usually `$(TOP)/config/' +#* +#* SEP Directory separator for the current platform. +#* Either / or \ (maybe : on Macs) +#* +#* DELETE The forced remove/delete command to erase one or more +#* files +#* +#* INCLUDE The location of all public header files. e.g. +#* `$(TOP)/include'include' * +#* +#* SRC The directory containing all sources. e.g. +#* '$(TOP)/src' +#* +#* OBJ_DIR The location where compiled object files will be +#* placed, e.g. '$(TOP)/obj' +#* +#* LIB_DIR The location where the resulting library file will be +#* placed, e.g. '$(TOP)/obj' +#* +#* LIBRARY The filename of the resulting library file, without +#* its extension.. e.g. 'libfreetype' or 'freetype' +#* +#* O The object file suffix. Can be '.o', '.obj,' '.lo,' +#* ';coff,' etc. +#* +#* A The library file suffix. Can be '.a' '.so,' '.lib' +#* '.dll,' etc. +#* +#* I The path inclusion flag. Some compilers use a +#* different flag than '-I' to specify an additional +#* include path. Examples are '/i=' or '-J ', etc. +#* +#* D The macro definition flag. I haven't met compilers +#* which don't use the '-D' switch to define a macro, but +#* who knows... +#* +#* T The compilation flag used to identify the target. Some +#* compilers use a different flag than '-o ' to specify +#* the name of the target object file. +#* +#* CFLAGS The set of flags used to compile object files. +#* (usually contains the flag '-c'). +#* +#* +#* +#******************************************************************* + +ifndef TOP +TOP := . +endif + +DELETE := del +SEP := / +BUILD := $(TOP)/config/os2 +PLATFORM := os2 +CC := gcc + +# the directory where all object files are placed +# +OBJ_DIR := $(TOP)/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, this can be .o, .tco, .obj, etc.. +# depending on the platform +# +O := o + +# the library file extension, this can be .a, .lib, etc.. +# depending on the platform +# +A := 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", etc... +# +I := -I + + +# 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 + + +# C flag used to define a macro before the compilation of a given +# source object. Usually is '-D' like in "-DDEBUG" +# +D := -D + + +# Target flag - beware, there is a space after the 'o' !! +# +# +T := -o + +# C flags +# +# These should concern : +# +# - debug output +# - optimization +# - warnings +# - ansi compliance.. +# +ifndef CFLAGS +CFLAGS := -c -g -O6 -Wall +endif + + +ifdef BUILD_FREETYPE + +include $(TOP)/config/freetype.mk + + +# 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) + + +# Cleaning rules +# +DIR_OBJ := $(subst $(SEP),\,$(OBJ_DIR)) + +clean_freetype_objects: + -del $(DIR_OBJ)\*.$O + +clean_freetype_lib: + -del $(subst $(SEP),\,$(FT_LIBRARY)) + +clean: clean_freetype_objects + + + +endif + + diff --git a/config/os2/detect.mk b/config/os2/detect.mk new file mode 100644 index 000000000..42dc47b5c --- /dev/null +++ b/config/os2/detect.mk @@ -0,0 +1,47 @@ +# +# This file is used to detect an OS/2 host, and set the build variables +# accordingly.. +# +# which Makefile to use based on the value of the CC environment variable. +# +# OS/2 +# +# + +ifeq ($(PLATFORM),ansi) +ifdef OS2_SHELL + +PLATFORM := os2 +COPY := copy +DELETE := del + +CONFIG_FILE := Makefile.emx # gcc-emx by default +SEP := / + +ifneq ($(findstring visualage,$(MAKECMDGOALS)),) # Visual Age C++ +CONFIG_FILE := Makefile.icc +SEP := $(BACKSLASH) +CC := icc +.PHONY: visualage +endif + +ifneq ($(findstring watcom,$(MAKECMDGOALS)),) # Watcom C/C++ +CONFIG_FILE := Makefile.wat +SEP := $(BACKSLASH) +CC := wcc386 +.PHONY: watcom +endif + +ifneq ($(findstring borlandc,$(MAKECMDGOALS)),) # Borland C++ 32 bits +CONFIG_FILE := Makefile.bcc +SEP := $(BACKSLASH) +CC := bcc32 +.PHONY: borlandc +endif + +CONFIG_RULES := $(TOP)\config\os2\$(CONFIG_FILE) + +setup: dos_setup + +endif #test OS2_SHELL +endif #test PLATFORM diff --git a/config/os2/ftconfig.h b/config/os2/ftconfig.h new file mode 100644 index 000000000..43a4c9522 --- /dev/null +++ b/config/os2/ftconfig.h @@ -0,0 +1,182 @@ +/***************************************************************************/ +/* */ +/* ftconfig.h */ +/* */ +/* ANSI-specific configuration file (specification only). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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. Porters are free to copy this file and */ + /* adapt it to suit their own system. */ + /* */ + /* IMPORTANT NOTE: */ + /* */ + /* Porters, read carefully the comments in `ftsys.h' before trying to */ + /* port this file to your system. It contains many essential */ + /* remarks, and will ease your work greatly. */ + /* */ + /*************************************************************************/ + + +#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/arch/' directory, and edit it to port the engine. */ + /* */ + /*************************************************************************/ + + +/* Define to empty if the keyword does not work. */ +/* #undef const */ + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* We use values to know the sizes of the types. */ +#include + +/* The number of bytes in an `int' type. */ +#if UINT_MAX == 0xFFFFFFFF +#define SIZEOF_INT 4 +#elif UINT_MAX == 0xFFFF +#define SIZEOF_INT 2 +#elif UINT_MAX > 0xFFFFFFFF && UINT_MAX == 0xFFFFFFFFFFFFFFFF +#define 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 SIZEOF_LONG 4 +#elif ULONG_MAX > 0xFFFFFFFF && ULONG_MAX == 0xFFFFFFFFFFFFFFFF +#define SIZEOF_LONG 8 +#else +#error "Unsupported number of bytes in `long' type!" +#endif + +/* Define if you have the memcpy function. */ +#define HAVE_MEMCPY 1 + +/* Define if you have the header file. */ +#define HAVE_FCNTL_H 0 + +/* Define if you have the header file. */ +#define HAVE_UNISTD_H 0 + + +/* Preferred alignment of data */ +#define FT_ALIGNMENT 8 + + + + /*************************************************************************/ + /* */ + /* AUTOMATIC CONFIGURATION MACROS */ + /* */ + /* These macros are computed from the ones defined above. Don't touch */ + /* their definition, unless you know precisely what you're 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_Word16; + +#if SIZEOF_INT == 4 + + typedef signed int FT_Int32; + typedef unsigned int FT_Word32; + +#elif SIZEOF_LONG == 4 + + typedef signed long FT_Int32; + typedef unsigned long FT_Word32; + +#else +#error "no 32bit type found - please check your configuration files" +#endif + +#if SIZEOF_LONG == 8 + + /* LONG64 must be defined when a 64-bit type is available */ +#define LONG64 +#define INT64 long + +#else + + + /*************************************************************************/ + /* */ + /* GCC provides the non-ANSI 'long long' 64-bit type. You can activate */ + /* it by defining the FTCALC_USE_LONG_LONG macro in `ftconfig.h'. Note */ + /* that this will produce many -ansi warnings during library */ + /* compilation. */ + /* */ +#ifdef FTCALC_USE_LONG_LONG + +#define LONG64 +#define INT64 long long + +#endif /* FTCALC_USE_LONG_LONG */ +#endif + + +#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 LOCAL_DEF +#define BASE_FUNC LOCAL_FUNC +#else +#define BASE_DEF extern +#define BASE_FUNC /* nothing */ +#endif + +#ifndef EXPORT_DEF +#define EXPORT_DEF extern +#endif + +#ifndef EXPORT_FUNC +#define EXPORT_FUNC /* nothing */ +#endif + +#endif /* FTCONFIG_H */ + + +/* END */ diff --git a/config/os2/ftoption.h b/config/os2/ftoption.h new file mode 100644 index 000000000..852f65fbb --- /dev/null +++ b/config/os2/ftoption.h @@ -0,0 +1,162 @@ +#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 file contains macros that apply to */ + /* all of FreeType. Driver-specific configurations are placed in each */ + /* driver directory (e.g. `freetype/drivers/ttlib/ttconfig.h'). */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* 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're sure that you'll never use a font driver */ + /* with an alternate glyph format, this will reduce the size of the */ + /* base layer code. */ + /* */ +#define FT_CONFIG_OPTION_ALTERNATE_GLYPH_FORMATS + + /*************************************************************************/ + /* */ + /* GCC provides the non-ANSI `long long' 64-bit type. You can activate */ + /* it by defining the FTCALC_USE_LONG_LONG macro here. Note however */ + /* that we did not experience any improvement in speed with gcc, and */ + /* that the final code seems bigger when linked. */ + /* */ +#undef FTCALC_USE_LONG_LONG + + + /*************************************************************************/ + /* */ + /* When compiling FreeType as a DLL, some systems/compilers need a */ + /* special keyword in front of each function definition instead of */ + /* `extern'. */ + /* */ + /* The macros EXPORT_DEF and EXPORT_FUNC are thus used to define */ + /* exported library function interfaces and exported library functions */ + /* implementations respectively. */ + /* */ + /* If not defined here, they automatically default to `extern' and void */ + /* later in this header file. */ + /* */ +#undef EXPORT_DEF +#undef 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. */ + /* */ +#undef FT_DEBUG_LEVEL_ERROR +#undef FT_DEBUG_LEVEL_TRACE + + + /*************************************************************************/ + /* */ + /* Anti-aliasing support */ + /* */ + /* Undefine this macro only if you want to disable the anti-aliasing */ + /* support in FreeType. This will save you about 5 Kb of code. It */ + /* may be important for some embedded systems. */ + /* */ +#define FT_CONFIG_OPTION_ANTI_ALIAS + + + /*************************************************************************/ + /* */ + /* Endianess performance improvement */ + /* */ + /* FreeType is completely endian-independent, and can thus be compiled */ + /* directly on _any_ machine. However, some components of the library */ + /* provide improved routines for the cases where endianess is known. */ + /* */ + /* It usually results in speed-ups and reduced code size. Note that */ + /* you should not define both of these macros. */ + /* */ + /* */ + /* NOTE: For now, only the scan-line converter (base/ftraster.c) uses */ + /* these macros to speed-up some anti-alias rendering routines. */ + /* */ +#undef FT_CONFIG_OPTION_LITTLE_ENDIAN +#undef FT_CONFIG_OPTION_BIG_ENDIAN + + + /*************************************************************************/ + /* */ + /* Define this configuration macro whenever you want to build a version */ + /* of FreeType that does not include a default `system' component. */ + /* */ + /* Note that this will prevent the compilation of `ftinit', hence the */ + /* function FT_Init_FreeType */ + /* */ +#undef FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM + + + /*************************************************************************/ + /* */ + /* 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 4 Kb */ + /* */ +#define FT_RENDER_POOL_SIZE 32768 + + + /*************************************************************************/ + /* */ + /* FT_MAX_DRIVERS */ + /* */ + /* The maximum number of font drivers that can be registered in a */ + /* single FreeType library object. 8 seems to be a good choice due */ + /* to the relative low actual number of drivers ;-) */ + /* */ +#define FT_MAX_DRIVERS 8 + + + /*************************************************************************/ + /* */ + /* FT_MAX_EXTENSIONS */ + /* */ + /* The maximum number of extensions that can be registered in a */ + /* single font driver. 8 seems to be a good choice for now.. */ + /* */ +#define FT_MAX_EXTENSIONS 8 + + + /*************************************************************************/ + /* */ + /* FT_MAX_GLYPH_FORMATS */ + /* */ + /* The maximum number of glyph image formats that might be registered */ + /* in a given library instance. 8 seems to be a good choice due to */ + /* the relatively low number of current formats ;-) */ + /* */ + +#define FT_MAX_GLYPH_FORMATS 8 + + + +#endif /* FTOPTION_H */ diff --git a/config/os2/ftsys.c b/config/os2/ftsys.c new file mode 100644 index 000000000..df50f1c9b --- /dev/null +++ b/config/os2/ftsys.c @@ -0,0 +1,940 @@ +/***************************************************************************/ +/* */ +/* ftsys.c */ +/* */ +/* OS/2-specific system operations (body). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 implementation of the `ftsys' component uses malloc()/free() for */ + /* memory management, and the OS/2 DosXXXXX() API functionss for file */ + /* access. */ + /* */ + /* IMPORTANT NOTE: */ + /* */ + /* Porters, read carefully the comments in ftsys.h before trying to */ + /* port this file to your system. It contains many essential */ + /* remarks, and will ease your work greatly. */ + /* */ + /*************************************************************************/ + + +#include "ftsys.h" +#include "ftstream.h" +#include "ftdebug.h" + +#include + +#include +#include +#include + +#ifdef HAVE_UNISTD_H +#include +#endif + + + /*************************************************************************/ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the PTRACE() and PERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_io + + +#undef CUR_SYSTEM /* just in case */ + + + /*************************************************************************/ + /* */ + /* To ease porting, we use the macro SYS_STREAM to name the */ + /* system-specific stream type. For example, it is a `FILE*' with the */ + /* ANSI libc, it will be a file descriptor, i.e. an integer, when using */ + /* the Unix system API, etc. */ + /* */ +#define SYS_STREAM HFILE + + + /*************************************************************************/ + /* */ + /* I/O ACCESS AND MANAGEMENT */ + /* */ + /* We only define the `ANSI' resource class in this class. It is */ + /* disk-based and provides a MRU cache in order to only keep the file */ + /* descriptors of the 10 most recently used resource files. */ + /* */ + /* It simply contains two lists. One contains the `cached' resources */ + /* with a valid FILE* pointer, the second contains all other `flushed' */ + /* resource objects. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Os2FileRec */ + /* */ + /* */ + /* The FT_Os2File class derives from FT_ResourceRec. */ + /* */ + /* */ + /* root :: The root resource class fields. */ + /* */ + /* pathname :: This is a copy of the ANSI file pathname used to open */ + /* streams for the resource. A different implementation */ + /* is free to use Unicode chars, or file i-node numbers, */ + /* etc. */ + /* */ + /* file_size :: The size in bytes of the resource. This field should */ + /* be set to -1 until the resource is first opened. */ + /* */ + typedef struct FT_Os2FileRec_ + { + FT_ResourceRec root; + char* pathname; /* the font file's pathname */ + FT_Long file_size; /* file size in bytes */ + + } FT_Os2FileRec, *FT_Os2File; + + + /*************************************************************************/ + /* */ + /* We use the macro STREAM_Name() as a convenience to return a given */ + /* ANSI resource's pathname. Its `stream' argument is a FT_Resource */ + /* which is typecasted to the FT_Os2File class. */ + /* */ +#define STREAM_Name( stream ) ((FT_Os2File)stream->resource)->pathname + + + /*************************************************************************/ + /* */ + /* We use the macro STREAM_File() as a convenience to extract the */ + /* system-specific stream handle from a given FreeType stream object. */ + /* */ +#define STREAM_File(stream) ((HFILE)stream->stream_id.pointer) + + + /*************************************************************************/ + /* */ + /* */ + /* Os2File_Open */ + /* */ + /* */ + /* This function is used to open a system-stream for a given */ + /* resource. */ + /* */ + /* Note that it must update the target FreeType stream object with */ + /* the system-stream handle and the resource's size. */ + /* */ + /* Also, the `stream->base' field must be set to NULL for disk-based */ + /* resources, and to the address in memory of the resource's first */ + /* byte for memory-based ones. */ + /* */ + /* */ + /* resource :: The source resource. */ + /* stream :: The target stream object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The stream object IS NOT CREATED by this function, but by its */ + /* caller. */ + /* */ + static + FT_Error Os2File_Open( FT_Os2File resource, + FT_Stream stream ) + { + HFILE file; + ULONG ulAction; + + + /* open the file */ +#ifdef __EMX__ + if ( DosOpen( (FT_Byte*)resource->pathname, + &file, + &ulAction, 0, 0, OPEN_ACTION_OPEN_IF_EXISTS, + OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY, + NULL ) ) +#else + if ( DosOpen( resource->pathname, + &file, + &ulAction, 0, 0, OPEN_ACTION_OPEN_IF_EXISTS, + OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY, + NULL ) ) +#endif /* __EMX__ */ + { + PERROR(( "Os2File_Open: Could not open file `%s'\n", + resource->pathname )); + return FT_Err_Cannot_Open_Stream; + } + + /* compute file size if necessary */ + if ( resource->file_size < 0 ) + { + DosSetFilePtr( file, 0, FILE_END, (ULONG*)&resource->file_size ); + DosSetFilePtr( file, 0, FILE_BEGIN, &ulAction ); + } + + stream->resource = (FT_Resource)resource; + stream->stream_id.pointer = (void*)file; + stream->size = resource->file_size; + + /* it's a disk-based resource, we don't need to use the "base" and */ + /* "cursor" fields of the stream objects */ + stream->base = NULL; + stream->cursor = NULL; + + PTRACE1(( "Os2File_Open: Opened `%s' (%d bytes) successfully\n", + resource->pathname, resource->file_size )); + + return FT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Os2File_Close */ + /* */ + /* */ + /* Closes a given stream. */ + /* */ + /* */ + /* stream :: The target stream object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error Os2File_Close( FT_Stream stream ) + { + PTRACE1(( "OS2File_Close: Closing file `%s'\n", STREAM_Name( stream ) )); + + DosClose( STREAM_File( stream ) ); + + stream->resource = NULL; + stream->stream_id.pointer = NULL; + stream->size = 0; + + return FT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Os2File_Seek */ + /* */ + /* */ + /* Seeks a stream to a given position. */ + /* */ + /* */ + /* stream :: The target stream object. */ + /* position :: The offset in bytes from the start of the */ + /* resource/stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The `seek' method is never called by the stream manager in case */ + /* of a memory-based resource (i.e., when `stream->base' isn't NULL). */ + /* */ + static + FT_Error Os2File_Seek( FT_Stream stream, + FT_Long position ) + { + ULONG ibActual; + + + if ( DosSetFilePtr( STREAM_File( stream ), position, + FILE_BEGIN, &ibActual ) ) + { + PERROR(( "Os2File_Seek: FAILED! Pos. %ld of `%s'\n", + position, STREAM_Name( stream ) )); + + return FT_Err_Invalid_Stream_Seek; + } + + PTRACE2(( "Os2File_Seek: Pos. %ld of `%s'\n", + position, STREAM_Name( stream ) )); + + return FT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Os2File_Skip */ + /* */ + /* */ + /* Skips a given number of bytes in an OS/2 stream. Useful to skip */ + /* pad bytes, for example. */ + /* */ + /* */ + /* stream :: The target stream object. */ + /* count :: The number of bytes to skip in the stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The `skip' method is never called by the stream manager in case */ + /* of a memory-based resource (i.e., when `stream->base' isn't NULL). */ + /* */ + static + FT_Error Os2File_Skip( FT_Stream stream, + FT_Long count ) + { + ULONG ibActual; + + + DosSetFilePtr( STREAM_File( stream ), 0, FILE_CURRENT, &ibActual ); + return Os2File_Seek( stream, ibActual + count ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* Os2File_Pos */ + /* */ + /* */ + /* Returns the current offset within an OS/2 stream's resource. */ + /* */ + /* */ + /* stream :: The target stream object. */ + /* */ + /* */ + /* position :: The current offset. -1 in case of error. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The `pos' method is never called by the stream manager in case */ + /* of a memory-based resource (i.e., when `stream->base' isn't NULL). */ + /* */ + static + FT_Error Os2File_Pos( FT_Stream stream, + FT_Long* position ) + { + ULONG ibActual; + + + if ( DosSetFilePtr( STREAM_File( stream ), 0, FILE_CURRENT, &ibActual ) ) + { + PTRACE2(( "Os2File_Pos: FAILED! in `%s'\n", STREAM_Name( stream ) )); + return FT_Err_Invalid_Stream_Seek; + } + + *position = ibActual; + + PTRACE2(( "Os2File_Pos: For `%s'\n", STREAM_Name( stream ) )); + return FT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Os2File_Read */ + /* */ + /* */ + /* Reads a given number of bytes from an OS/2 stream into memory. */ + /* */ + /* */ + /* stream :: The target stream object. */ + /* buffer :: The target read buffer where data is copied. */ + /* size :: The number of bytes to read from the stream. */ + /* */ + /* */ + /* read_bytes :: The number of bytes effectively read from the */ + /* stream. Used in case of error */ + /* (i.e. FT_Err_Invalid_Stream_Read) by some parts of */ + /* the library. */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* It MUST return the error FT_Err_Invalid_Stream_Read in case of */ + /* an over-read (i.e., reading more bytes from the stream that what */ + /* is left), as the stream component checks for this specific value. */ + /* */ + /* The `read' method is never called by the stream manager in case */ + /* of a memory-based resource (i.e., when `stream->base' isn't NULL). */ + /* */ + static + FT_Error Os2File_Read( FT_Stream stream, + char* buffer, + FT_Long size, + FT_Long* read_bytes ) + { + ULONG cbActual; + + + DosRead( STREAM_File( stream ), buffer, size, &cbActual ); + + *read_bytes = cbActual; + + if ( cbActual != (ULONG)size ) + { + /* Note : we can have an over-read here when called by the */ + /* function FT_Access_Compressed_Frame. This means */ + /* that the following message should be a trace, */ + /* rather than an error for disk-based resources.. */ + /* */ + /* the function must set the value of 'read_bytes' */ + /* even if it returns an error code.. */ + PTRACE2(( "Os2File_Read: FAILED! Read %ld bytes from '%s'\n", + size, STREAM_Name( stream ) )); + + return FT_Err_Invalid_Stream_Read; + } + + PTRACE2(( "Os2File_Read: Read %ld bytes to buffer 0x%08lx from `%s'\n", + size, (long)buffer, STREAM_Name( stream ) )); + return FT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* The following table is the `virtual method table' for the `OS/2 */ + /* resource class', which methods are defined above. Its address is set */ + /* in the `interface' field of all resource objects created by the */ + /* function FT_Create_Os2File() (see below). */ + /* */ + static + FTRes_InterfaceRec FT_Os2File_Interface = + { + (FTRes_Open_Func) Os2File_Open, + (FTRes_Close_Func) Os2File_Close, + (FTRes_Seek_Func) Os2File_Seek, + (FTRes_Skip_Func) Os2File_Skip, + (FTRes_Pos_Func) Os2File_Pos, + (FTRes_Read_Func) Os2File_Read, + }; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Create_Resource */ + /* */ + /* */ + /* Creates a new resource object. This function is called by the */ + /* FT_New_Resource() function of the base layer. */ + /* */ + /* */ + /* library :: The input library object. */ + /* pathname :: The file's pathname as an ASCII string. */ + /* */ + /* */ + /* aresource :: A handle to new resource object. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + /* */ + /* This functions does not open a stream. It simply copies the */ + /* pathname within a fresh new resource object. */ + /* */ + EXPORT_FUNC + FT_Error FT_Create_Resource( FT_Library library, + const char* pathname, + FT_Resource* aresource ) + { + FT_Int len; + FT_Os2File resource; + FT_Error error; + FT_System system; + + + if ( !library ) + return FT_Err_Invalid_Library_Handle; + + system = library->system; + + if ( !pathname ) + goto Fail_Null; + + len = strlen( pathname ); + if ( len == 0 ) + goto Fail_Null; + + resource = NULL; + + if ( ALLOC( resource, sizeof ( *resource ) ) || + ALLOC( resource->pathname, len + 1 ) ) + goto Fail_Memory; + + resource->root.library = library; + resource->root.interface = &FT_Os2File_Interface; + resource->root.flags = FT_RESOURCE_TYPE_DISK_BASED; + resource->file_size = -1; + strcpy( resource->pathname, pathname ); + + PTRACE1(( "Create_Os2File: OS/2 resource created for '%s'\n", + pathname )); + + *aresource = (FT_Resource)resource; + return FT_Err_Ok; + + Fail_Null: + PERROR(( "Create_Os2File: Null pathname!\n" )); + return FT_Err_Invalid_Argument; + + Fail_Memory: + if ( resource ) + FREE( resource->pathname ); + FREE( resource ); + PERROR(( "Create_Os2File: Not enough memory to create resource!\n" )); + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Destroy_Resource */ + /* */ + /* */ + /* Discards a given resource object explicitly. */ + /* */ + /* */ + /* resource :: The OS/2 resource object. */ + /* */ + /* */ + /* This function does not check whether runs or streams are opened */ + /* for the resource (for now, we assume developer intelligence. */ + /* We'll most probably lower our standard later to ease debugging :-) */ + /* */ + EXPORT_FUNC + FT_Error FT_Destroy_Resource( FT_Resource resource ) + { + FT_System system = resource->library->system; + FT_Os2File ansi = (FT_Os2File)resource; + + if ( !ansi || ansi->root.interface != &FT_Os2File_Interface ) + { + PERROR(( + "Destroy_Os2File: Trying to destroy an invalid resource!\n" )); + return FT_Err_Invalid_Resource_Handle; + } + + PTRACE1(( "Destroy_Os2File: Destroying resource for `%s'\n", + ansi->pathname )); + + FREE( ansi->pathname ); + FREE( ansi ); + + return FT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* MEMORY MANAGEMENT */ + /* */ + /* */ + /* This part copies the old FreeType 1.0 and 1.1 memory management */ + /* scheme that was defined in the file `ttmemory.h'. One can see that */ + /* */ + /* - a set of macros is defined for the memory operations used by the */ + /* engine (MEM_Copy(), MEM_Move(), MEM_Set()). This comes from the */ + /* fact that many compilers are able to inline these operations */ + /* directly within the compiled code, rather than generating a call */ + /* to the C library. However, this obliges us to include the */ + /* `' header file. */ + /* */ + /* If you provide your own memory operations, you can get rid of the */ + /* `#include ' below. */ + /* */ + /* */ + /* - the FT_Alloc() function has several essential properties that MUST */ + /* be retained by each port: */ + /* */ + /* - It returns an error code, NOT the allocated block's base */ + /* address. */ + /* */ + /* - It takes the address of a target pointer, where the block's base */ + /* address will be set. If the size is zero, its value will be */ + /* NULL, and the function returns successfully. */ + /* */ + /* - In case of error, the pointer's value is set to NULL and an */ + /* error code is returned. */ + /* */ + /* - The new allocated block MUST be zero-filled. This is a strong */ + /* convention the rest of the engine relies on. */ + /* */ + /* */ + /* - the FT_Free() function has also its essentials: */ + /* */ + /* - It takes the address of a pointer which value is the block's */ + /* base address. This is UNLIKE a standard `free()' which takes */ + /* the block's base directly. */ + /* */ + /* - It accepts successfully the address of a pointer which value is */ + /* NULL, in which case it simply returns. */ + /* */ + /* - The pointer is always set to NULL by the function. */ + /* */ + /* */ + /* - The MEM_Alloc(), ALLOC(), and ALLOC_ARRAY() macros are used by the */ + /* library and should NOT be modified by porters! */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the PTRACE() and PERROR() 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. */ + /* */ + /* */ + /* system :: A handle to a given `system object' where allocation */ + /* occurs. */ + /* */ + /* 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_System system, + FT_Long size, + void** P ) + { + if ( !P ) + { + PERROR(( "FT_Alloc: Invalid pointer address!\n" )); + return FT_Err_Invalid_Argument; + } + + if ( size > 0 ) + { + *P = malloc( size ); + if ( !*P ) + { + PERROR(( "FT_Alloc: Out of memory (%ld bytes requested)!\n", + size )); + + return FT_Err_Out_Of_Memory; + } + + system->total_alloc += size; + + /* ALWAYS ZERO-FILL THE BLOCK! */ + MEM_Set( *P, 0, size ); + } + else + *P = NULL; + + PTRACE2(( "FT_Alloc: Size = %ld, pointer = 0x%08lx, block = 0x%08lx\n", + size, (long)P, (long)*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'. */ + /* */ + /* */ + /* system :: A handle to a given `system object' where allocation */ + /* occurs. */ + /* */ + /* 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_Realloc( FT_System system, + FT_Long size, + void** P ) + { + void* Q; + + + if ( !P ) + { + PERROR(( "FT_Realloc: Invalid pointer address!\n" )); + return FT_Err_Invalid_Argument; + } + + /* if the original pointer is NULL, call FT_Alloc() */ + if ( !*P ) + return FT_Alloc( system, size, P ); + + /* if the new block if zero-sized, clear the current one */ + if ( size <= 0 ) + return FT_Free( system, P ); + + Q = (void*)realloc( *P, size ); + if ( !Q ) + { + PERROR(( "FT_Realloc: Reallocation failed!\n" )); + return FT_Err_Out_Of_Memory; + } + + *P = Q; + return FT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Free */ + /* */ + /* */ + /* Releases a given block of memory allocated through FT_Alloc(). */ + /* */ + /* */ + /* system :: A handle to a given `system object' where allocation */ + /* occured. */ + /* */ + /* 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 + FT_Error FT_Free( FT_System system, + void* *P ) + { + UNUSED( system ); + + PTRACE2(( "FT_Free: Freeing pointer 0x%08lx (block 0x%08lx)\n", + (long)P, (P ? (long)*P : -1) )); + + if ( !P || !*P ) + return FT_Err_Ok; + + free( *P ); + *P = NULL; + + return FT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* SYNCHRONIZATION MANAGEMENT */ + /* */ + /* */ + /* This section deals with mutexes. The library can be compiled to */ + /* two distinct thread support levels (namely single threaded and */ + /* re-entrant modes). */ + /* */ + /* It protects its variables through the MUTEX_Lock() and */ + /* MUTEX_Release() macros which are void in single threaded mode. */ + /* */ + /* It defines a typeless mutex reference type, `FT_Mutex', that you're */ + /* free to redefine for your system's needs. */ + /* */ + /* The default implementation of ftsys.c contains only dummy functions */ + /* which always return successfully. You NEED to specialize them in */ + /* order to port ftsys.c to any multi-threaded environment. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the PTRACE() and PERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_sync + + +#ifdef FT_CONFIG_THREADS + + BASE_FUNC + FT_Error FT_Mutex_Create( FT_System system, + TMutex* mutex ) + { + UNUSED( system ); + + mutex = (void*)-1; + system->num_mutexes++; + + /* Insert your own mutex creation code here */ + + return FT_Err_Ok; + } + + + BASE_FUNC + void FT_Mutex_Delete( FT_System system, + TMutex* mutex ) + { + UNUSED( system ); + + mutex = (void*)0; + system->num_mutexes--; + + /* Insert your own mutex destruction code here */ + } + + + BASE_FUNC + void FT_Mutex_Lock( FT_System system, + TMutex* mutex ) + { + /* NOTE: It is legal to call this function with a NULL argument */ + /* in which case an immediate return is appropriate. */ + + UNUSED( system ); + + if ( !mutex ) + return; + + /* Insert your own mutex locking code here */ + } + + + BASE_FUNC + void FT_Mutex_Release( FT_System system, + TMutex* mutex ) + { + /* NOTE: It is legal to call this function with a NULL argument */ + /* in which case an immediate return is appropriate */ + + UNUSED( system ); + + if ( !mutex ) + return; + + /* Insert your own mutex release code here */ + } + +#endif /* FT_CONFIG_THREADS */ + + + /*************************************************************************/ + /* */ + /* */ + /* FT_New_System */ + /* */ + /* */ + /* This function is used to create and initialize new system objects. */ + /* These are mainly used to let client applications and font servers */ + /* specify their own memory allocators and synchronization */ + /* procedures. */ + /* */ + /* */ + /* system :: A handle to a given `system object'. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + EXPORT_FUNC + FT_Error FT_New_System( FT_System* system ) + { + *system = (FT_System)malloc( sizeof ( **system ) ); + + if ( !*system ) + return FT_Err_Out_Of_Memory; + + /* initialize memory management */ + + (*system)->system_flags = FT_SYSTEM_FLAG_TOTAL_ALLOC | + FT_SYSTEM_FLAG_MUTEXES; + (*system)->total_alloc = 0; + (*system)->num_mutexes = 0; + + /* initialize i/o management (nothing) */ + + /* initialize synchronisation (nothing) */ + + /* initialize streams (nothing) */ + + return FT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Done_System */ + /* */ + /* */ + /* Destroys a given FreeType system object. */ + /* */ + /* */ + /* system :: A handle to a given `system object'. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + EXPORT_FUNC + FT_Error FT_Done_System( FT_System system ) + { + /* finalize synchronization (nothing) */ + + /* finalize i/o management (nothing) */ + + /* finalize memory management */ + + free( system ); + + return FT_Err_Ok; + } + + +/* END */ diff --git a/config/os2/ftsystem.c b/config/os2/ftsystem.c new file mode 100644 index 000000000..459f668e9 --- /dev/null +++ b/config/os2/ftsystem.c @@ -0,0 +1,214 @@ +/************************************************************************** + * + * ftsystem.h 1.0 + * + * ANSI-specific FreeType low-level system interface + * + * This file contains the definition of interface used by FreeType + * to access low-level, i.e. memory management, i/o access as well + * as thread synchronisation. + * + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.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 + + /*********************************************************************/ + /* */ + /* MEMORY MANAGEMENT INTERFACE */ + /* */ + +/************************************************************************ + * + * + * FT_Alloc_Func + * + * + * The memory allocator function type + * + * + * system :: pointer to the system object + * size :: requested size in bytes + * + * + * block :: address of newly allocated block + * + * + * Error code. 0 means success. + * + * + * If your allocation routine ALWAYS zeroes the new block, you + * should set the flag FT_SYSTEM_FLAG_ALLOC_ZEROES in your system + * object 'flags' field. + * + * If you have set the flag FT_SYSTEM_FLAG_REPORT_CURRENT_ALLOC in + * your system's "system_flags" field, this function should update + * the "current_alloc" field of the system object. + * + ************************************************************************/ + + static + void* ft_alloc( FT_Memory memory, + long size ) + { + (void)memory; + return malloc(size); + } + + +/************************************************************************ + * + * + * FT_Realloc_Func + * + * + * The memory reallocator function type + * + * + * system :: pointer to the system object + * new_size :: new requested size in bytes + * + * + * block :: address of block in memory + * + * + * Error code. 0 means success. + * + * + * This function is _never_ called when the system flag + * FT_SYSTEM_FLAG_NO_REALLOC is set. Instead, the engine will emulate + * realloc through "alloc" and "free". + * + * Note that this is possible due to the fact that FreeType's + * "FT_Realloc" always requests the _current_ size of the reallocated + * block as a parameter, thus avoiding memory leaks. + * + * If you have set the flag FT_SYSTEM_FLAG_REPORT_CURRENT_ALLOC in + * your system's "system_flags" field, this function should update + * the "current_alloc" field of the system object. + * + ************************************************************************/ + + static + void* ft_realloc( FT_Memory memory, + long cur_size, + long new_size, + void* block ) + { + (void)memory; + (void)cur_size; + + return realloc( block, new_size ); + } + + +/************************************************************************ + * + * + * FT_Free_Func + * + * + * The memory release function type + * + * + * system :: pointer to the system object + * block :: address of block in memory + * + * + * If you have set the flag FT_SYSTEM_FLAG_REPORT_CURRENT_ALLOC in + * your system's "system_flags" field, this function should update + * the "current_alloc" field of the system object. + * + ************************************************************************/ + + static + void ft_free( FT_Memory memory, + void* block ) + { + (void)memory; + free( block ); + } + + /*********************************************************************/ + /* */ + /* RESOURCE MANAGEMENT INTERFACE */ + /* */ + + +#define STREAM_FILE(stream) ((FILE*)stream->descriptor.pointer) + + static + void ft_close_stream( FT_Stream stream ) + { + fclose( STREAM_FILE(stream) ); + } + + static + unsigned long ft_io_stream( FT_Stream stream, + unsigned long offset, + char* buffer, + unsigned long count ) + { + FILE* file; + + file = STREAM_FILE(stream); + + fseek( file, offset, SEEK_SET ); + return (unsigned long)fread( buffer, count, 1, file ); + } + + + extern + int FT_New_Stream( const char* filepathname, + FT_Stream stream ) + { + FILE* file; + + file = fopen( filepathname, "rb" ); + if (!file) + 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->pos = 0; + + stream->read = ft_io_stream; + stream->close = ft_close_stream; + + return 0; + } + + + extern + 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; + } + diff --git a/config/os2/makefile.devel b/config/os2/makefile.devel new file mode 100644 index 000000000..f390f7980 --- /dev/null +++ b/config/os2/makefile.devel @@ -0,0 +1,192 @@ +#******************************************************************* +#* +#* FreeType 2 Configuration rules for Unix + gcc +#* +#* Copyright 1996-1999 by +#* David Turner, Robert Wilhelm, and Werner Lemberg. +#* +#* This file is part of the FreeType project, and may only be used +#* modified and distributed under the terms of the FreeType project +#* license, LICENSE.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 sub-Makefile is to define various build and +#* platform specific variables before including the sub-Makefile +#* containing the FreeType library rules, found in +#* +#* $(TOP)/config/freetype.mk +#* +#* The following variables must be defined before including this +#* file : +#* +#* TOP Pathname to the top of the FreeType sources +#* hierarchy +#* +#* This file should define the following variables before including +#* the FreeType library rules file : +#* +#* BUILD Pathname to the platform-specific files used +#* for the build. Usually `$(TOP)/config/' +#* +#* SEP Directory separator for the current platform. +#* Either / or \ (maybe : on Macs) +#* +#* DELETE The forced remove/delete command to erase one or more +#* files +#* +#* INCLUDE The location of all public header files. e.g. +#* `$(TOP)/include'include' * +#* +#* SRC The directory containing all sources. e.g. +#* '$(TOP)/src' +#* +#* OBJ_DIR The location where compiled object files will be +#* placed, e.g. '$(TOP)/obj' +#* +#* LIB_DIR The location where the resulting library file will be +#* placed, e.g. '$(TOP)/obj' +#* +#* LIBRARY The filename of the resulting library file, without +#* its extension.. e.g. 'libfreetype' or 'freetype' +#* +#* O The object file suffix. Can be '.o', '.obj,' '.lo,' +#* ';coff,' etc. +#* +#* A The library file suffix. Can be '.a' '.so,' '.lib' +#* '.dll,' etc. +#* +#* I The path inclusion flag. Some compilers use a +#* different flag than '-I' to specify an additional +#* include path. Examples are '/i=' or '-J ', etc. +#* +#* D The macro definition flag. I haven't met compilers +#* which don't use the '-D' switch to define a macro, but +#* who knows... +#* +#* T The compilation flag used to identify the target. Some +#* compilers use a different flag than '-o ' to specify +#* the name of the target object file. +#* +#* CFLAGS The set of flags used to compile object files. +#* (usually contains the flag '-c'). +#* +#* +#* +#******************************************************************* + +DELETE := del +SEP := / +BUILD := $(TOP)/config/os2 +PLATFORM := os2 +CC := gcc + +# the directory where all object files are placed +# +OBJ_DIR := $(TOP)/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, this can be .o, .tco, .obj, etc.. +# depending on the platform +# +O := o + +# the library file extension, this can be .a, .lib, etc.. +# depending on the platform +# +A := 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", etc... +# +I := -I + + +# 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 + + +# C flag used to define a macro before the compilation of a given +# source object. Usually is '-D' like in "-DDEBUG" +# +D := -D + + +# Target flag - beware, there is a space after the 'o' !! +# +# +T := -o + +# C flags +# +# These should concern : +# +# - debug output +# - optimization +# - warnings +# - ansi compliance.. +# +ifndef CFLAGS +CFLAGS := -c -g -O0 -Wall +endif + + +ifdef BUILD_FREETYPE + +include $(TOP)/config/freetype.mk + + +# 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) + + +# Cleaning rules +# +DIR_OBJ := $(subst $(SEP),\,$(OBJ_DIR)) + +clean_freetype_objects: + -del $(DIR8OBJ)\*.$O + +clean_freetype_lib: + -del $(FT_LIBRARY) + +clean: clean_freetype_objects + + + +endif + + diff --git a/config/os2/makefile.gcc b/config/os2/makefile.gcc new file mode 100644 index 000000000..dfd041cbe --- /dev/null +++ b/config/os2/makefile.gcc @@ -0,0 +1,190 @@ +#******************************************************************* +#* +#* FreeType 2 Configuration rules for Unix + gcc +#* +#* Copyright 1996-1999 by +#* David Turner, Robert Wilhelm, and Werner Lemberg. +#* +#* This file is part of the FreeType project, and may only be used +#* modified and distributed under the terms of the FreeType project +#* license, LICENSE.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 sub-Makefile is to define various build and +#* platform specific variables before including the sub-Makefile +#* containing the FreeType library rules, found in +#* +#* $(TOP)/config/freetype.mk +#* +#* The following variables must be defined before including this +#* file : +#* +#* TOP Pathname to the top of the FreeType sources +#* hierarchy +#* +#* This file should define the following variables before including +#* the FreeType library rules file : +#* +#* BUILD Pathname to the platform-specific files used +#* for the build. Usually `$(TOP)/config/' +#* +#* SEP Directory separator for the current platform. +#* Either / or \ (maybe : on Macs) +#* +#* DELETE The forced remove/delete command to erase one or more +#* files +#* +#* INCLUDE The location of all public header files. e.g. +#* `$(TOP)/include'include' * +#* +#* SRC The directory containing all sources. e.g. +#* '$(TOP)/src' +#* +#* OBJ_DIR The location where compiled object files will be +#* placed, e.g. '$(TOP)/obj' +#* +#* LIB_DIR The location where the resulting library file will be +#* placed, e.g. '$(TOP)/obj' +#* +#* LIBRARY The filename of the resulting library file, without +#* its extension.. e.g. 'libfreetype' or 'freetype' +#* +#* O The object file suffix. Can be '.o', '.obj,' '.lo,' +#* ';coff,' etc. +#* +#* A The library file suffix. Can be '.a' '.so,' '.lib' +#* '.dll,' etc. +#* +#* I The path inclusion flag. Some compilers use a +#* different flag than '-I' to specify an additional +#* include path. Examples are '/i=' or '-J ', etc. +#* +#* D The macro definition flag. I haven't met compilers +#* which don't use the '-D' switch to define a macro, but +#* who knows... +#* +#* T The compilation flag used to identify the target. Some +#* compilers use a different flag than '-o ' to specify +#* the name of the target object file. +#* +#* CFLAGS The set of flags used to compile object files. +#* (usually contains the flag '-c'). +#* +#* +#* +#******************************************************************* + +DELETE := del +SEP := / +BUILD := $(TOP)/config/os2 +PLATFORM := os2 +CC := gcc + +# the directory where all object files are placed +# +OBJ_DIR := $(TOP)/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, this can be .o, .tco, .obj, etc.. +# depending on the platform +# +O := o + +# the library file extension, this can be .a, .lib, etc.. +# depending on the platform +# +A := 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", etc... +# +I := -I + + +# 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 + + +# C flag used to define a macro before the compilation of a given +# source object. Usually is '-D' like in "-DDEBUG" +# +D := -D + + +# Target flag - beware, there is a space after the 'o' !! +# +# +T := -o + +# C flags +# +# These should concern : +# +# - debug output +# - optimization +# - warnings +# - ansi compliance.. +# +ifndef CFLAGS +CFLAGS := -c -g -O0 -Wall +endif + + +ifdef BUILD_FREETYPE + +include $(TOP)/config/freetype.mk + +# A rule used to clean all objects from OBJ_DIR +# +# The OS/2 command shell does not support very long list of arguments +# so we're stuck with wildcards +# + +DIR_OBJ := $(subst $(SEP),\,$(OBJ_DIR)) + +clean_freetype_objects: + -del $(DIR8OBJ)\*.$O + +clean_freetype_lib: + -del $(FT_LIBRARY) + +clean: clean_freetype_objects + +# 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 + diff --git a/config/unix/Makefile b/config/unix/Makefile new file mode 100644 index 000000000..59c08feed --- /dev/null +++ b/config/unix/Makefile @@ -0,0 +1,172 @@ +#******************************************************************* +#* +#* FreeType 2 Configuration rules for Unix + gcc +#* +#* Copyright 1996-1999 by +#* David Turner, Robert Wilhelm, and Werner Lemberg. +#* +#* This file is part of the FreeType project, and may only be used +#* modified and distributed under the terms of the FreeType project +#* license, LICENSE.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 sub-Makefile is to define various build and +#* platform specific variables before including the sub-Makefile +#* containing the FreeType library rules, found in +#* +#* $(TOP)/config/freetype.mk +#* +#* The following variables must be defined before including this +#* file : +#* +#* TOP Pathname to the top of the FreeType sources +#* hierarchy +#* +#* This file should define the following variables before including +#* the FreeType library rules file : +#* +#* BUILD Pathname to the platform-specific files used +#* for the build. Usually `$(TOP)/config/' +#* +#* SEP Directory separator for the current platform. +#* Either / or \ (maybe : on Macs) +#* +#* DELETE The forced remove/delete command to erase one or more +#* files +#* +#* INCLUDE The location of all public header files. e.g. +#* `$(TOP)/include'include' * +#* +#* SRC The directory containing all sources. e.g. +#* '$(TOP)/src' +#* +#* OBJ_DIR The location where compiled object files will be +#* placed, e.g. '$(TOP)/obj' +#* +#* LIB_DIR The location where the resulting library file will be +#* placed, e.g. '$(TOP)/obj' +#* +#* LIBRARY The filename of the resulting library file, without +#* its extension.. e.g. 'libfreetype' or 'freetype' +#* +#* O The object file suffix. Can be '.o', '.obj,' '.lo,' +#* ';coff,' etc. +#* +#* A The library file suffix. Can be '.a' '.so,' '.lib' +#* '.dll,' etc. +#* +#* I The path inclusion flag. Some compilers use a +#* different flag than '-I' to specify an additional +#* include path. Examples are '/i=' or '-J ', etc. +#* +#* D The macro definition flag. I haven't met compilers +#* which don't use the '-D' switch to define a macro, but +#* who knows... +#* +#* T The compilation flag used to identify the target. Some +#* compilers use a different flag than '-o ' to specify +#* the name of the target object file. +#* +#* CFLAGS The set of flags used to compile object files. +#* (usually contains the flag '-c'). +#* +#* +#* +#******************************************************************* + +ifndef TOP +TOP := . +endif + +DELETE := rm -f +SEP := / +BUILD := $(TOP)/config/unix +PLATFORM := unix + +# the directory where all object files are placed +# +OBJ_DIR := $(TOP)/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, this can be .o, .tco, .obj, etc.. +# depending on the platform +# +O := o + +# the library file extension, this can be .a, .lib, etc.. +# depending on the platform +# +A := 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", etc... +# +I := -I + + +# 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 + + +# C flag used to define a macro before the compilation of a given +# source object. Usually is '-D' like in "-DDEBUG" +# +D := -D + + +# Target flag - beware, there is a space after the 'o' !! +# +# +T := -o + +# C flags +# +# These should concern : +# +# - debug output +# - optimization +# - warnings +# - ansi compliance.. +# +ifndef CFLAGS +CFLAGS := -c -g -O6 -Wall +endif + +ifdef BUILD_FREETYPE + +include $(TOP)/config/freetype.mk + + +# 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) $@ + $(AR) -r $@ $(OBJECTS_LIST) + +endif diff --git a/config/unix/Makefile.devel b/config/unix/Makefile.devel new file mode 100644 index 000000000..8710a7c10 --- /dev/null +++ b/config/unix/Makefile.devel @@ -0,0 +1,172 @@ +#******************************************************************* +#* +#* FreeType 2 Configuration rules for Unix + gcc +#* +#* Copyright 1996-1999 by +#* David Turner, Robert Wilhelm, and Werner Lemberg. +#* +#* This file is part of the FreeType project, and may only be used +#* modified and distributed under the terms of the FreeType project +#* license, LICENSE.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 sub-Makefile is to define various build and +#* platform specific variables before including the sub-Makefile +#* containing the FreeType library rules, found in +#* +#* $(TOP)/config/freetype.mk +#* +#* The following variables must be defined before including this +#* file : +#* +#* TOP Pathname to the top of the FreeType sources +#* hierarchy +#* +#* This file should define the following variables before including +#* the FreeType library rules file : +#* +#* BUILD Pathname to the platform-specific files used +#* for the build. Usually `$(TOP)/config/' +#* +#* SEP Directory separator for the current platform. +#* Either / or \ (maybe : on Macs) +#* +#* DELETE The forced remove/delete command to erase one or more +#* files +#* +#* INCLUDE The location of all public header files. e.g. +#* `$(TOP)/include'include' * +#* +#* SRC The directory containing all sources. e.g. +#* '$(TOP)/src' +#* +#* OBJ_DIR The location where compiled object files will be +#* placed, e.g. '$(TOP)/obj' +#* +#* LIB_DIR The location where the resulting library file will be +#* placed, e.g. '$(TOP)/obj' +#* +#* LIBRARY The filename of the resulting library file, without +#* its extension.. e.g. 'libfreetype' or 'freetype' +#* +#* O The object file suffix. Can be '.o', '.obj,' '.lo,' +#* ';coff,' etc. +#* +#* A The library file suffix. Can be '.a' '.so,' '.lib' +#* '.dll,' etc. +#* +#* I The path inclusion flag. Some compilers use a +#* different flag than '-I' to specify an additional +#* include path. Examples are '/i=' or '-J ', etc. +#* +#* D The macro definition flag. I haven't met compilers +#* which don't use the '-D' switch to define a macro, but +#* who knows... +#* +#* T The compilation flag used to identify the target. Some +#* compilers use a different flag than '-o ' to specify +#* the name of the target object file. +#* +#* CFLAGS The set of flags used to compile object files. +#* (usually contains the flag '-c'). +#* +#* +#* +#******************************************************************* + +ifndef TOP +TOP := . +endif + +DELETE := rm -f +SEP := / +BUILD := $(TOP)/config/unix +PLATFORM := unix + +# the directory where all object files are placed +# +OBJ_DIR := $(TOP)/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, this can be .o, .tco, .obj, etc.. +# depending on the platform +# +O := o + +# the library file extension, this can be .a, .lib, etc.. +# depending on the platform +# +A := 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", etc... +# +I := -I + + +# 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 + + +# C flag used to define a macro before the compilation of a given +# source object. Usually is '-D' like in "-DDEBUG" +# +D := -D + + +# Target flag - beware, there is a space after the 'o' !! +# +# +T := -o + +# C flags +# +# These should concern : +# +# - debug output +# - optimization +# - warnings +# - ansi compliance.. +# +ifndef CFLAGS +CFLAGS := -c -g -O0 -Wall +endif + +ifdef BUILD_FREETYPE + +include $(TOP)/config/freetype.mk + + +# 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) $@ + $(AR) -r $@ $(OBJECTS_LIST) + +endif diff --git a/config/unix/detect.mk b/config/unix/detect.mk new file mode 100644 index 000000000..3d39c64e9 --- /dev/null +++ b/config/unix/detect.mk @@ -0,0 +1,31 @@ +# +# This file is used to detect which Makefile to use based on the +# value of the CC environment variable. +# +# Unix +# +# +# This will _much_ probably change in the future if we're going to use +# Automake/Autoconf.. +# + +ifeq ($(PLATFORM),ansi) +has_inittab := $(strip $(wildcard /etc/inittab)) +ifneq ($(has_inittab),) + +PLATFORM := unix +COPY := cp +DELETE := rm -f + +CONFIG_RULES := $(BUILD)$(SEP)Makefile + +setup: std_setup + +endif # test Unix +endif # test PLATFORM + + + + + + diff --git a/config/unix/ftconfig.h b/config/unix/ftconfig.h new file mode 100644 index 000000000..de7f6f283 --- /dev/null +++ b/config/unix/ftconfig.h @@ -0,0 +1,172 @@ +/******************************************************************* + * + * ftconfig.h + * + * Unix-specific configuration file + * + * Copyright 1996-1998 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.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. Porters are free to copy this file + * and adapt it to suit their own system.. + * + * IMPORTANT NOTE : + * + * Porters, read carefully the comments in ftsys.h before trying + * to port this file to your system. It contains many essential + * remarks, and will ease your work greatly.. + * + ******************************************************************/ + +#ifndef FTCONFIG_H +#define FTCONFIG_H + +/*************************************************************************/ +/* */ +/* PLATFORM-SPECIFIC CONFIGURATION MACROS */ +/* */ +/* These macros can be toggled to suit a specific system. The current */ +/* ones are defaults used to compile FreeType in a 32-bits ANSI C */ +/* environment. Copy this file to your own "freetype/arch/" */ +/* directory, and edit it to port the engine.. */ +/* */ +/*************************************************************************/ + +/* Define to empty if the keyword does not work. */ +/* #undef const */ + +/* Define if you have a working `mmap' system call. */ +#define HAVE_MMAP + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define if your processor stores words with the most significant + byte first (like Motorola and SPARC, unlike Intel and VAX). */ +/* #undef WORDS_BIGENDIAN */ + +/* Define if the X Window System is missing or not being used. */ +/* #undef X_DISPLAY_MISSING */ + +/* The number of bytes in a int. */ +#define SIZEOF_INT 4 + +/* The number of bytes in a long. */ +#define SIZEOF_LONG 4 + +/* Define if you have the getpagesize function. */ +#define HAVE_GETPAGESIZE 1 + +/* Define if you have the memcpy function. */ +#define HAVE_MEMCPY 1 + +/* Define if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define if you have the header file. */ +#define HAVE_LOCALE_H 1 + +/* Define if you have the header file. */ +#undef HAVE_LIBINTL_H + +/* Define if you have the libintl library. */ +/* #undef HAVE_LIBINTL */ + +/* Preferred alignment of data */ +#define FT_ALIGNMENT 8 + +/* See the definition of the macro FT_CONFIG_OPTION_LITTLE_ENDIAN */ +/* and FT_CONFIG_OPTION_BIG_ENDIAN below, they may need to be set */ +/* according to the platform too.. */ + + +#include + +/*************************************************************************/ +/* */ +/* AUTOMATIC CONFIGURATION MACROS */ +/* */ +/* These macros are computed from the ones defined above. Don't touch */ +/* their definition, unless you know precisely what you're 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_Word16; + +#if SIZEOF_INT == 4 + + typedef signed int FT_Int32; + typedef unsigned int FT_Word32; + +#elif SIZEOF_LONG == 4 + + typedef signed long FT_Int32; + typedef unsigned long FT_Word32; + +#else +#error "no 32bit type found - please check your configuration files" +#endif + +#if SIZEOF_LONG == 8 + +/* LONG64 must be defined when a 64-bit type is available */ +#define LONG64 +#define INT64 long + +#else + +/* GCC provides the non-ANSI 'long long' 64-bit type. You can activate it */ +/* by defining the FTCALC_USE_LONG_LONG macro in 'ftconfig.h'. Note that */ +/* this will produce many -ansi warnings during library compilation. */ +#ifdef FTCALC_USE_LONG_LONG + +#define LONG64 +#define INT64 long long + +#endif /* FTCALC_USE_LONG_LONG */ +#endif + +#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 LOCAL_DEF +#define BASE_FUNC LOCAL_FUNC +#else +#define BASE_DEF extern +#define BASE_FUNC /* nothing */ +#endif + +#ifndef EXPORT_DEF +#define EXPORT_DEF extern +#endif + +#ifndef EXPORT_FUNC +#define EXPORT_FUNC /* nothing */ +#endif + + +#endif /* FTCONFIG_H */ diff --git a/config/unix/ftoption.h b/config/unix/ftoption.h new file mode 100644 index 000000000..852f65fbb --- /dev/null +++ b/config/unix/ftoption.h @@ -0,0 +1,162 @@ +#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 file contains macros that apply to */ + /* all of FreeType. Driver-specific configurations are placed in each */ + /* driver directory (e.g. `freetype/drivers/ttlib/ttconfig.h'). */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* 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're sure that you'll never use a font driver */ + /* with an alternate glyph format, this will reduce the size of the */ + /* base layer code. */ + /* */ +#define FT_CONFIG_OPTION_ALTERNATE_GLYPH_FORMATS + + /*************************************************************************/ + /* */ + /* GCC provides the non-ANSI `long long' 64-bit type. You can activate */ + /* it by defining the FTCALC_USE_LONG_LONG macro here. Note however */ + /* that we did not experience any improvement in speed with gcc, and */ + /* that the final code seems bigger when linked. */ + /* */ +#undef FTCALC_USE_LONG_LONG + + + /*************************************************************************/ + /* */ + /* When compiling FreeType as a DLL, some systems/compilers need a */ + /* special keyword in front of each function definition instead of */ + /* `extern'. */ + /* */ + /* The macros EXPORT_DEF and EXPORT_FUNC are thus used to define */ + /* exported library function interfaces and exported library functions */ + /* implementations respectively. */ + /* */ + /* If not defined here, they automatically default to `extern' and void */ + /* later in this header file. */ + /* */ +#undef EXPORT_DEF +#undef 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. */ + /* */ +#undef FT_DEBUG_LEVEL_ERROR +#undef FT_DEBUG_LEVEL_TRACE + + + /*************************************************************************/ + /* */ + /* Anti-aliasing support */ + /* */ + /* Undefine this macro only if you want to disable the anti-aliasing */ + /* support in FreeType. This will save you about 5 Kb of code. It */ + /* may be important for some embedded systems. */ + /* */ +#define FT_CONFIG_OPTION_ANTI_ALIAS + + + /*************************************************************************/ + /* */ + /* Endianess performance improvement */ + /* */ + /* FreeType is completely endian-independent, and can thus be compiled */ + /* directly on _any_ machine. However, some components of the library */ + /* provide improved routines for the cases where endianess is known. */ + /* */ + /* It usually results in speed-ups and reduced code size. Note that */ + /* you should not define both of these macros. */ + /* */ + /* */ + /* NOTE: For now, only the scan-line converter (base/ftraster.c) uses */ + /* these macros to speed-up some anti-alias rendering routines. */ + /* */ +#undef FT_CONFIG_OPTION_LITTLE_ENDIAN +#undef FT_CONFIG_OPTION_BIG_ENDIAN + + + /*************************************************************************/ + /* */ + /* Define this configuration macro whenever you want to build a version */ + /* of FreeType that does not include a default `system' component. */ + /* */ + /* Note that this will prevent the compilation of `ftinit', hence the */ + /* function FT_Init_FreeType */ + /* */ +#undef FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM + + + /*************************************************************************/ + /* */ + /* 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 4 Kb */ + /* */ +#define FT_RENDER_POOL_SIZE 32768 + + + /*************************************************************************/ + /* */ + /* FT_MAX_DRIVERS */ + /* */ + /* The maximum number of font drivers that can be registered in a */ + /* single FreeType library object. 8 seems to be a good choice due */ + /* to the relative low actual number of drivers ;-) */ + /* */ +#define FT_MAX_DRIVERS 8 + + + /*************************************************************************/ + /* */ + /* FT_MAX_EXTENSIONS */ + /* */ + /* The maximum number of extensions that can be registered in a */ + /* single font driver. 8 seems to be a good choice for now.. */ + /* */ +#define FT_MAX_EXTENSIONS 8 + + + /*************************************************************************/ + /* */ + /* FT_MAX_GLYPH_FORMATS */ + /* */ + /* The maximum number of glyph image formats that might be registered */ + /* in a given library instance. 8 seems to be a good choice due to */ + /* the relatively low number of current formats ;-) */ + /* */ + +#define FT_MAX_GLYPH_FORMATS 8 + + + +#endif /* FTOPTION_H */ diff --git a/config/unix/ftsys.c b/config/unix/ftsys.c new file mode 100644 index 000000000..2198d95ab --- /dev/null +++ b/config/unix/ftsys.c @@ -0,0 +1,871 @@ +/******************************************************************* + * + * ftsys.c + * + * Unix-specific system operations. + * + * Copyright 1996-1998 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.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 implementation of the 'ftsys' component uses memory-mapped + * files, as well as the ANSI malloc/free functions.. + * + * IMPORTANT NOTE : + * + * Porters, read carefully the comments in ftsys.h before trying + * to port this file to your system. It contains many essential + * remarks, and will ease your work greatly.. + * + ******************************************************************/ + +#include "ftsys.h" +#include "ftobjs.h" +#include "ftstream.h" +#include "ftdebug.h" + +/* 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 + + +/* The macro FT_COMPONENT is used in trace mode. It is an implicit */ +/* parameter of the PTRACE and PERROR macros, used to print/log */ +/* messages during execution.. */ +/* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_io + + + + +/* To ease porting, we use the macro SYS_STREAM to name the system-specific */ +/* stream type. For example, it is a "FILE*" with the ANSI libc, it will be */ +/* a file descriptor, i.e. an integer, when using the Unix system api, etc. */ + +/* we identify each memory-mapped file through its address in memory */ +/* hence the following macro definition.. */ + +#define SYS_STREAM void* + + +/**************************************************************************/ +/* */ +/* I/O ACCESS AND MANAGEMENT */ +/* */ +/* We only define the "ANSI" resource class in this class. It is */ +/* disk-based, and provides a MRU cache, in order to only keep the file */ +/* descriptors of the 10 most recently used resource files. */ +/* */ +/* it simply contains two lists. One contains the "cached" resources */ +/* with a valid FILE* pointer, the second contains all other "flushed" */ +/* resource objects. */ +/* */ + +/* The FT_MMapFile class derives from FT_ResourceRec - description : */ +/* */ +/* FT_AnsiFileRec */ +/* */ +/* */ +/* */ +/* root :: */ +/* the root resource class fields. */ +/* */ +/* pathname :: */ +/* the file's pathname. Needed because we open and close font */ +/* resources dynamically in order to limit the number of */ +/* concurrently active mappings (this saves kernel resources). */ +/* */ +/* file_size :: */ +/* the size in bytes of the resource. This field should be set to */ +/* -1 until the resource is first opened.. */ +/* */ + +#include + + typedef struct FT_MMapFileRec_ + { + FT_ResourceRec root; + const char* pathname; + FT_Long file_size; /* file size in bytes */ + + } FT_MMapFileRec, *FT_MMapFile; + + +/* We use the macro STREAM_Name as a convenience to return a given */ +/* ANSI resource's pathname. Its "stream" argument is a FT_Resource */ +/* which is typecasted to the FT_AnsiFile class */ +#define STREAM_Name(stream) ((FT_MMapFile)stream->resource)->pathname + +/* We use the macro STREAM_File as a convenience to extract the */ +/* system-specific stream handle from a given FreeType stream object */ +#define STREAM_File(stream) ((void*)stream->stream_id.pointer) + + + +/***************************************************************************/ +/* */ +/* MMapFile_Open */ +/* */ +/* */ +/* This function is used to open a system-stream for a given resource. */ +/* */ +/* Note that it must update the target FreeType stream object with the */ +/* system-stream handle and the resource's size. */ +/* */ +/* Also, the 'stream->base' field must be set to NULL for disk-based */ +/* resource, and to the address in memory of the resource's first byte */ +/* for a memory-based one. */ +/* */ +/* */ +/* resource :: the source resource */ +/* stream :: the target stream object */ +/* */ +/* */ +/* Error code */ +/* */ +/* */ +/* This function simply opens and maps the resource's file pathname */ +/* */ +/* The stream object IS NOT CREATED by this function, but by its caller. */ +/* */ +/***************************************************************************/ + + static + FT_Error MMapFile_Open( FT_MMapFile resource, + FT_Stream stream ) + { + int file; + struct stat stat_buf; + + /* open the file */ + file = open( resource->pathname, O_RDONLY ); + if (file < 0) + { + PERROR(( "UnixSys.MMapFile_Open : could not open '%s'\n", + resource->pathname )); + return FT_Err_Cannot_Open_Stream; + } + + if (fstat( file, &stat_buf ) < 0) + { + PERROR(( "UnixSys.MMapFile_Open : could not 'fstat' file '%s'\n", + resource->pathname )); + goto Fail_Map; + } + + if ( resource->file_size < 0 ) + resource->file_size = stat_buf.st_size; + + stream->resource = (FT_Resource)resource; + stream->system = resource->root.driver->system; + stream->size = resource->file_size; + stream->stream_id.pointer = mmap( NULL, + resource->file_size, + PROT_READ, + MAP_FILE | MAP_PRIVATE, + file, + 0 ); + + if ( (long)stream->stream_id.pointer == -1 ) + { + PERROR(( "UnixSys.MMapFile_Open : Could not map file '%s'\n", + resource->pathname )); + goto Fail_Map; + } + + close(file); + stream->base = (FT_Byte*)stream->stream_id.pointer; + stream->cursor = stream->base; + + PTRACE1(( "UnixSys.MMapFile_Open: opened '%s' (%d bytes) succesfully\n", + resource->pathname, resource->file_size )); + + return FT_Err_Ok; + + Fail_Map: + close(file); + stream->resource = NULL; + stream->size = 0; + stream->stream_id.pointer = NULL; + stream->base = NULL; + stream->cursor = NULL; + + return FT_Err_Cannot_Open_Stream; + } + + +/***************************************************************************/ +/* */ +/* MMapFile_Close */ +/* */ +/* Closes a given stream */ +/* */ +/* */ +/* stream :: the target stream object */ +/* */ +/* */ +/* Error code */ +/* */ +/* */ +/* This function simply unmaps the resource.. */ +/* */ +/***************************************************************************/ + + static + FT_Error MMapFile_Close( FT_Stream stream ) + { + PTRACE1(( "Closing file '%s'\n", STREAM_Name(stream) )); + + munmap ( (void*)stream->stream_id.pointer, stream->size ); + + stream->resource = NULL; + stream->stream_id.pointer = NULL; + stream->size = 0; + stream->base = NULL; + stream->cursor = NULL; + + return FT_Err_Ok; + } + + +/***************************************************************************/ +/* */ +/* MMapFile_Seek */ +/* */ +/* Seek a stream to a given position */ +/* */ +/* */ +/* stream :: the target stream object */ +/* position :: offset in bytes from start of resource/stream */ +/* */ +/* */ +/* Error code */ +/* */ +/* */ +/* This function should never be called for memory-based resources.. */ +/* */ +/***************************************************************************/ + + static + FT_Error MMapFile_Seek( FT_Stream stream, + FT_Long position ) + { + (void)stream; + (void)position; + return FT_Err_Invalid_Stream_Operation; + } + + +/***************************************************************************/ +/* */ +/* MMapFile_Skip */ +/* */ +/* Skip a given number of bytes in an MMap stream. */ +/* Useful to skip pad bytes, for example. */ +/* */ +/* */ +/* stream :: the target stream object */ +/* count :: number of bytes to skip in the stream */ +/* */ +/* */ +/* Error code */ +/* */ +/* */ +/* This function should never be called for memory-based resources.. */ +/* */ +/***************************************************************************/ + + static + FT_Error MMapFile_Skip( FT_Stream stream, + FT_Long count ) + { + (void)stream; + (void)count; + return FT_Err_Invalid_Stream_Operation; + } + +/***************************************************************************/ +/* */ +/* MMapFile_Pos */ +/* */ +/* Returns the current offset within an MMap stream's */ +/* resource. */ +/* */ +/* */ +/* stream :: the target stream object */ +/* */ +/* */ +/* position :: current offset. -1 in case of error */ +/* */ +/* */ +/* Error code. */ +/* */ +/* */ +/* This function should never be called for memory-based resources.. */ +/* */ +/***************************************************************************/ + + static + FT_Error MMapFile_Pos( FT_Stream stream, + FT_Long* position ) + { + (void)stream; + (void)position; + return FT_Err_Invalid_Stream_Operation; + } + +/***************************************************************************/ +/* */ +/* MMapFile_Read */ +/* */ +/* Read a given number of bytes from an MMap stream into */ +/* memory. */ +/* */ +/* */ +/* stream :: the target stream object */ +/* buffer :: the target read buffer where data is copied */ +/* size :: number of bytes to read from the stream */ +/* */ +/* */ +/* read_bytes :: the number of bytes effectively read from the stream */ +/* used in case of error (i.e. FT_Err_Invalid_Stream_Read) */ +/* by some parts of the library.. */ +/* */ +/* Error code */ +/* */ +/* */ +/* This function should never be called for memory-based resources.. */ +/* */ +/***************************************************************************/ + + static + FT_Error MMapFile_Read( FT_Stream stream, + FT_Byte* buffer, + FT_Long size, + FT_Long* read_bytes ) + { + (void)stream; + (void)buffer; + (void)size; + (void)read_bytes; + return FT_Err_Invalid_Stream_Operation; + } + +/* The following table is the "virtual method table" for the 'MMap */ +/* resource class', which methods are defined above. Its address is */ +/* set in the 'interface' field of all resource objects created by */ +/* the function FT_Create_MMapFile (see below) */ + + static + FTRes_InterfaceRec FT_MMapFile_Interface = + { + (FTRes_Open_Func) MMapFile_Open, + (FTRes_Close_Func) MMapFile_Close, + (FTRes_Seek_Func) MMapFile_Seek, + (FTRes_Skip_Func) MMapFile_Skip, + (FTRes_Pos_Func) MMapFile_Pos, + (FTRes_Read_Func) MMapFile_Read, + }; + + + /************************************************************************/ + /* */ + /* FT_Create_Resource */ + /* */ + /* */ + /* Create a new resource object for a given library. Note that this */ + /* function takes an ASCII 'pathname' as an argument. */ + /* */ + /* */ + /* library :: handle to target library object */ + /* pathanme :: ASCII pathname of the font file */ + /* */ + /* */ + /* resource :: handle to new resource object */ + /* */ + /* */ + /* Error code. 0 means success */ + /* */ + /* */ + /* When porting the library to exotic environments, where an */ + /* ASCII pathname isn't used to name files, developers should */ + /* invoke directly their own resource creation function which */ + /* must be placed in their port of the "ftsys" component. */ + /* */ + /* See the porting guide for more information.. */ + /* */ + EXPORT_FUNC + FT_Error FT_Create_Resource( FT_Library library, + const char* pathname, + FT_Resource* aresource ) + { + FT_Int len; + FT_System system; + FT_MMapFile resource; + FT_Error error; + + *aresource = NULL; + + if (!library) + { + PERROR(( "Unix.New_Resource : null library handle\n" )); + return FT_Err_Invalid_Library_Handle; + } + + system = library->system; + + if ( !pathname ) + goto Fail_Null; + + len = strlen(pathname); + if (len == 0) + goto Fail_Null; + + resource = NULL; + + if ( ALLOC( resource, sizeof(*resource) ) || + ALLOC( resource->pathname, len+1 ) ) + goto Fail_Memory; + + resource->root.library = library; + resource->root.interface = &FT_MMapFile_Interface; + resource->root.flags = FT_RESOURCE_TYPE_MEMORY_BASED; + resource->file_size = -1; + strcpy( (char*)resource->pathname, pathname ); + + PTRACE1(( "Create_MMapFile : MMap resource created for '%s'\n", + pathname )); + + *aresource = (FT_Resource)resource; + return FT_Err_Ok; + + Fail_Null: + PERROR(( "Create_MMapFile : null pathname !!\n" )); + return FT_Err_Invalid_Argument; + + Fail_Memory: + if (resource) + FREE( resource->pathname ); + FREE( resource ); + PERROR(( "Create_MMapFile : error when creating resource !\n" )); + return error; + } + + +/***************************************************************************/ +/* */ +/* FT_Destroy_Resource */ +/* */ +/* Destroys an MMap resource object. */ +/* This function is never called directly by the font */ +/* drivers. Only by the higher-level part of FreeType */ +/* (called the HLib), or client applications */ +/* */ +/* */ +/* resource :: the MMap resource object */ +/* */ +/* */ +/* This functions does not check that runs or streams are opened for */ +/* the resource (for now, we assume developer intelligence. We'll most */ +/* probably lower our standard later to ease debugging ;-) */ +/* */ +/***************************************************************************/ + + EXPORT_FUNC + FT_Error FT_Destroy_Resource( FT_Resource resource ) + { + FT_System system = resource->library->system; + FT_MMapFile res = (FT_MMapFile)resource; + + if ( !res || res->root.interface != &FT_MMapFile_Interface ) + { + PERROR(( + "Destroy_MMapFile : Trying to destroy an invalid resource !!\n" )); + return FT_Err_Invalid_Resource_Handle; + } + + PTRACE1(( "Destroy_MMapFile : destroying resource for '%s'\n", + res->pathname )); + + FREE( res->pathname ); + FREE( res ); + + return FT_Err_Ok; + } + + + +/**************************************************************************/ +/* */ +/* MEMORY MANAGEMENT */ +/* */ +/* */ +/* This part copies the old FreeType 1.0 and 1.1 memory management */ +/* scheme that was defined in the file "ttmemory.h". One can see that */ +/* */ +/* - a set of macros is defined for the memory operations used */ +/* by the engine ( MEM_Copy, MEM_Move, MEM_Set ). This comes from */ +/* the fact that many compilers are able to inline these ops directly */ +/* within the compiled code, rather than generating a call to the */ +/* C library. However, this obliges us to include the */ +/* header file. */ +/* */ +/* If you provide your own memory operations routine, you can get */ +/* rid of the #include below. */ +/* */ +/* */ +/* - the FT_Alloc function has several essential properties that */ +/* MUST be retained by each port : */ +/* */ +/* - it returns an error code, NOT the allocated block's base */ +/* address */ +/* */ +/* - it takes the address of a target pointer, where the block's */ +/* base address will be set. if the size is zero, its value */ +/* will be NULL and the function returns successfully */ +/* */ +/* - in case of error, the pointer's value is set to NULL and */ +/* an error code is returned.. */ +/* */ +/* - the new allocated block MUST be zero-filled. This is a strong */ +/* convetion the rest of the engine relies on */ +/* */ +/* */ +/* */ +/* - the FT_Free function has also its essentials : */ +/* */ +/* - it takes the address of a pointer which value is the block's */ +/* base address. This is UNLIKE a standard "free" which takes the */ +/* the block's base directly. */ +/* */ +/* - it accepts succesfully the address of a pointer which value */ +/* is NULL, in which case it simply returns. */ +/* */ +/* - the pointer is always set to NULL by the function */ +/* */ +/* */ +/* - the MEM_Alloc, ALLOC and ALLOC_ARRAY macros are used by the */ +/* library, and should NOT be modified by porters !! */ +/* */ + +/* The macro FT_COMPONENT is used in trace mode. It is an implicit */ +/* parameter of the PTRACE and PERROR macros, used to print/log */ +/* messages during execution.. */ +/* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_memory + + +#include + +/**************************************************************************/ +/* */ +/* FT_Alloc */ +/* */ +/* */ +/* Allocates a new bloc of memory. The returned area is always */ +/* zero-filled, this is a strong convention in many FreeType parts */ +/* */ +/* */ +/* system :: handle to a given 'system object' where allocation */ +/* occurs.. */ +/* */ +/* size :: size in bytes of the block to allocate */ +/* */ +/* */ +/* P :: pointer to the fresh new block. It should be set */ +/* to NULL if 'size' is 0, of in case of error.. */ +/* */ +/* */ +/* FreeType error code. 0 means success. */ +/* */ +/**************************************************************************/ + + BASE_FUNC + FT_Error FT_Alloc( FT_System system, + long size, + void* *P ) + { + + if (!P) + { + PERROR(( "FT_Alloc : invalid pointer address !!\n" )); + return FT_Err_Invalid_Argument; + } + + if ( size > 0 ) + { + *P = malloc( size ); + if ( !*P ) + { + PERROR(( "FT_Alloc : out of memory (%ld bytes requested) !!\n", + size )); + + return FT_Err_Out_Of_Memory; + } + + system->total_alloc += size; + + /* ALWAYS ZERO-FILL THE BLOCK !!!!! */ + MEM_Set( *P, 0, size ); + } + else + *P = NULL; + + PTRACE2(( "FT_Alloc : size = %ld, pointer = 0x%08lx, block = 0x%08lx\n", + size, (long)P, (long)*P )); + + return FT_Err_Ok; + } + + +/**************************************************************************/ +/* */ +/* FT_Realloc */ +/* */ +/* */ +/* Reallocates a block of memory pointed to by '*P' to 'Size' */ +/* bytes from the hea^, possibly changing '*P'. */ +/* */ +/* */ +/* system :: handle to a given 'system object' where allocation */ +/* occurs.. */ +/* */ +/* size :: size in bytes of the block to allocate */ +/* */ +/* */ +/* P :: pointer to the fresh new block. It should be set */ +/* to NULL if 'size' is 0, of in case of error.. */ +/* */ +/* */ +/* FreeType error code. 0 means success. */ +/* */ + + BASE_FUNC + int FT_Realloc( FT_System system, + long size, + void* *P ) + { + void* Q; + + if (!P) + { + PERROR(( "FT_Realloc : invalid pointer address !!\n" )); + return FT_Err_Invalid_Argument; + } + + /* if the original pointer is NULL, call FT_Alloc */ + if (!*P) + return FT_Alloc( system, size, P ); + + /* if the new block if zero-sized, clear the current one */ + if (size <= 0) + return FT_Free( system, P ); + + Q = (void*)realloc( *P, size ); + if (!Q) + { + PERROR(( "FT_Realloc : reallocation failed\n" )); + return FT_Err_Out_Of_Memory; + } + + *P = Q; + return FT_Err_Ok; + } + + +/**************************************************************************/ +/* */ +/* FT_Free */ +/* */ +/* */ +/* Releases a given block of memory allocated through FT_Alloc */ +/* */ +/* */ +/* system :: handle to a given 'system object' where allocation */ +/* occured.. */ +/* */ +/* 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 successfuly. This */ +/* is a strong convention within all of FreeType and its drivers.. */ +/* */ + + BASE_FUNC + FT_Error FT_Free( FT_System system, + void* *P ) + { + (void)system; /* unused parameter. Gets rid of warnings */ + + PTRACE2(( "FT_Free : freeing pointer 0x%08lx (block 0x%08lx)\n", + (long)P, (P ? (long)*P : -1) )); + + if ( !P || !*P ) + return FT_Err_Ok; + + free( *P ); + *P = NULL; + + return FT_Err_Ok; + } + +/**************************************************************************/ +/* */ +/* SYNCHRONIZATION MANAGEMENT */ +/* */ +/* */ +/* This section deals with mutexes. The library can be compiled to */ +/* three distinct thread-support levels ( namely single-threaded, */ +/* thread-safe and re-entrant modes ). */ +/* */ +/* It protects its variables through the MUTEX_Lock and MUTEX_Release */ +/* macros which are void in single-threaded mode. */ +/* */ +/* */ +/* It defines a type-less mutex reference type, "TMutex", that you're */ +/* free to redefine for your system's needs.. */ +/* */ +/* The default implementation of ftsys.c contains only dummy functions */ +/* which always return succesfully. you NEED to specialize them in */ +/* order to port ftsys.c in any multi-threaded environment... */ +/* */ + +/* The macro FT_COMPONENT is used in trace mode. It is an implicit */ +/* parameter of the PTRACE and PERROR macros, used to print/log */ +/* messages during execution.. */ +/* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_sync + +#ifdef FT_CONFIG_THREADS + + + BASE_FUNC + FT_Error FT_Mutex_Create ( FT_System system, + TMutex* mutex ) + { + (void)system; /* unused parameter. Gets rid of warnings */ + + mutex = (void*)-1; + system->num_mutexes++; + return FT_Err_Ok; + /* Replace this line with your own mutex creation code */ + } + + + BASE_FUNC + void FT_Mutex_Delete ( FT_System system, + TMutex* mutex ) + { + (void)system; /* unused parameter. Gets rid of warnings */ + + mutex = (void*)0; + system->num_mutexes--; + /* Replace this line with your own mutex destruction code */ + } + + BASE_FUNC + void FT_Mutex_Lock ( FT_System system, + TMutex* mutex ) + { + /* NOTE: It is legal to call this function with a NULL argument */ + /* in which case an immediate return is appropriate. */ + (void)system; /* unused parameter. Gets rid of warnings */ + + if ( !mutex ) + return; + + ; /* Insert your own mutex locking code here */ + } + + + void FT_Mutex_Release( FT_System system, + TMutex* mutex ) + { + /* NOTE: It is legal to call this function with a NULL argument */ + /* in which case an immediate return is appropriate */ + (void)system; /* unused parameter. Gets rid of warnings */ + + if ( !mutex ) + return; + ; /* Insert your own mutex release code here */ + } + +#endif /* FT_CONFIG_THREADS */ + + + + + EXPORT_FUNC + FT_Error FT_New_System( FT_System* system ) + { + *system = (FT_System)malloc( sizeof(FT_SystemRec) ); + if ( !*system ) + return FT_Err_Out_Of_Memory; + + /* the ANSI function 'free' is unable to return the number */ + /* of released bytes. Hence, the 'current_alloc' field of the */ + /* system object cannot be used */ + + (*system)->system_flags = FT_SYSTEM_FLAG_TOTAL_ALLOC | + FT_SYSTEM_FLAG_MUTEXES; + (*system)->total_alloc = 0; + (*system)->num_mutexes = 0; + + /* initialise i/o management (nothing) */ + + /* initialise synchronisation (nothing) */ + + /* initialise streams */ + + return FT_Err_Ok; + } + + + + EXPORT_FUNC + FT_Error FT_Done_System( FT_System system ) + { + /* finalise syncrhonisation (nothing) */ + + /* finalise i/o management (nothing) */ + + /* finalise memory management */ + free( system ); + + return FT_Err_Ok; + } + diff --git a/config/unix/ftsystem.c b/config/unix/ftsystem.c new file mode 100644 index 000000000..0f0291074 --- /dev/null +++ b/config/unix/ftsystem.c @@ -0,0 +1,277 @@ +/************************************************************************** + * + * ftsystem.h 1.0 + * + * Unix-specific FreeType low-level system interface + * + * This file contains the definition of interface used by FreeType + * to access low-level, i.e. memory management, i/o access as well + * as thread synchronisation. + * + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.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 + +/* 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_Func + * + * + * The memory allocator function type + * + * + * system :: pointer to the system object + * size :: requested size in bytes + * + * + * block :: address of newly allocated block + * + * + * Error code. 0 means success. + * + * + * If your allocation routine ALWAYS zeroes the new block, you + * should set the flag FT_SYSTEM_FLAG_ALLOC_ZEROES in your system + * object 'flags' field. + * + * If you have set the flag FT_SYSTEM_FLAG_REPORT_CURRENT_ALLOC in + * your system's "system_flags" field, this function should update + * the "current_alloc" field of the system object. + * + ************************************************************************/ + + static + void* ft_alloc( FT_Memory memory, + long size ) + { + (void)memory; + return malloc(size); + } + + +/************************************************************************ + * + * + * FT_Realloc_Func + * + * + * The memory reallocator function type + * + * + * system :: pointer to the system object + * new_size :: new requested size in bytes + * + * + * block :: address of block in memory + * + * + * Error code. 0 means success. + * + * + * This function is _never_ called when the system flag + * FT_SYSTEM_FLAG_NO_REALLOC is set. Instead, the engine will emulate + * realloc through "alloc" and "free". + * + * Note that this is possible due to the fact that FreeType's + * "FT_Realloc" always requests the _current_ size of the reallocated + * block as a parameter, thus avoiding memory leaks. + * + * If you have set the flag FT_SYSTEM_FLAG_REPORT_CURRENT_ALLOC in + * your system's "system_flags" field, this function should update + * the "current_alloc" field of the system object. + * + ************************************************************************/ + + static + void* ft_realloc( FT_Memory memory, + long cur_size, + long new_size, + void* block ) + { + (void)memory; + (void)cur_size; + + return realloc( block, new_size ); + } + + +/************************************************************************ + * + * + * FT_Free_Func + * + * + * The memory release function type + * + * + * system :: pointer to the system object + * block :: address of block in memory + * + * + * If you have set the flag FT_SYSTEM_FLAG_REPORT_CURRENT_ALLOC in + * your system's "system_flags" field, this function should update + * the "current_alloc" field of the system object. + * + ************************************************************************/ + + static + void ft_free( FT_Memory memory, + void* block ) + { + (void)memory; + free( block ); + } + + /*********************************************************************/ + /* */ + /* RESOURCE MANAGEMENT INTERFACE */ + /* */ + +/* We use the macro STREAM_File as a convenience to extract the */ +/* system-specific stream handle from a given FreeType stream object */ +#define STREAM_File(stream) ((void*)stream->descriptor.pointer) + + +#undef FT_COMPONENT +#define FT_COMPONENT trace_io + + static + void ft_close_stream( FT_Stream stream ) + { + munmap ( stream->descriptor.pointer, stream->size ); + + stream->descriptor.pointer = NULL; + stream->size = 0; + stream->base = 0; + } + + + extern + int FT_New_Stream( const char* filepathname, + FT_Stream stream ) + { + int file; + struct stat stat_buf; + + /* open the file */ + file = open( filepathname, O_RDONLY ); + if (file < 0) + { + FT_ERROR(( "FT.Unix.Open:" )); + FT_ERROR(( " could not open '%s'\n", filepathname )); + return FT_Err_Cannot_Open_Stream; + } + + if (fstat( file, &stat_buf ) < 0) + { + FT_ERROR(( "FT.Unix.Open:" )); + 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.Unix.Open:" )); + FT_ERROR(( " Could not map 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.Unix.Open:" )); + FT_TRACE1(( " opened '%s' (%d bytes) succesfully\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; + } + + + extern + 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; + } + diff --git a/config/win32/Makefile.gcc b/config/win32/Makefile.gcc new file mode 100644 index 000000000..b81a5c6f0 --- /dev/null +++ b/config/win32/Makefile.gcc @@ -0,0 +1,179 @@ +#******************************************************************* +#* +#* FreeType 2 Configuration rules for Unix + gcc +#* +#* Copyright 1996-1999 by +#* David Turner, Robert Wilhelm, and Werner Lemberg. +#* +#* This file is part of the FreeType project, and may only be used +#* modified and distributed under the terms of the FreeType project +#* license, LICENSE.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 sub-Makefile is to define various build and +#* platform specific variables before including the sub-Makefile +#* containing the FreeType library rules, found in +#* +#* $(TOP)/config/freetype.mk +#* +#* The following variables must be defined before including this +#* file : +#* +#* TOP Pathname to the top of the FreeType sources +#* hierarchy +#* +#* This file should define the following variables before including +#* the FreeType library rules file : +#* +#* BUILD Pathname to the platform-specific files used +#* for the build. Usually `$(TOP)/config/' +#* +#* SEP Directory separator for the current platform. +#* Either / or \ (maybe : on Macs) +#* +#* DELETE The forced remove/delete command to erase one or more +#* files +#* +#* INCLUDE The location of all public header files. e.g. +#* `$(TOP)/include'include' * +#* +#* SRC The directory containing all sources. e.g. +#* '$(TOP)/src' +#* +#* OBJ_DIR The location where compiled object files will be +#* placed, e.g. '$(TOP)/obj' +#* +#* LIB_DIR The location where the resulting library file will be +#* placed, e.g. '$(TOP)/obj' +#* +#* LIBRARY The filename of the resulting library file, without +#* its extension.. e.g. 'libfreetype' or 'freetype' +#* +#* O The object file suffix. Can be '.o', '.obj,' '.lo,' +#* ';coff,' etc. +#* +#* A The library file suffix. Can be '.a' '.so,' '.lib' +#* '.dll,' etc. +#* +#* I The path inclusion flag. Some compilers use a +#* different flag than '-I' to specify an additional +#* include path. Examples are '/i=' or '-J ', etc. +#* +#* D The macro definition flag. I haven't met compilers +#* which don't use the '-D' switch to define a macro, but +#* who knows... +#* +#* T The compilation flag used to identify the target. Some +#* compilers use a different flag than '-o ' to specify +#* the name of the target object file. +#* +#* CFLAGS The set of flags used to compile object files. +#* (usually contains the flag '-c'). +#* +#* +#* +#******************************************************************* + +ifndef TOP +TOP := . +endif + +DELETE := del +SEP := / +BUILD := $(TOP)/config/win32 +PLATFORM := win32 +CC := gcc + +# the directory where all object files are placed +# +OBJ_DIR := $(TOP)/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, this can be .o, .tco, .obj, etc.. +# depending on the platform +# +O := o + +# the library file extension, this can be .a, .lib, etc.. +# depending on the platform +# +A := 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", etc... +# +I := -I + + +# 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 + + +# C flag used to define a macro before the compilation of a given +# source object. Usually is '-D' like in "-DDEBUG" +# +D := -D + + +# Target flag - beware, there is a space after the 'o' !! +# +# +T := -o + +# C flags +# +# These should concern : +# +# - debug output +# - optimization +# - warnings +# - ansi compliance.. +# +ifndef CFLAGS +CFLAGS := -c -g -O6 -Wall +endif + + +ifdef BUILD_FREETYPE + +include $(TOP)/config/freetype.mk + +# 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 + diff --git a/config/win32/Makefile.lcc b/config/win32/Makefile.lcc new file mode 100644 index 000000000..d2cd03ddc --- /dev/null +++ b/config/win32/Makefile.lcc @@ -0,0 +1,180 @@ +#******************************************************************* +#* +#* FreeType 2 Configuration rules for Unix + gcc +#* +#* Copyright 1996-1999 by +#* David Turner, Robert Wilhelm, and Werner Lemberg. +#* +#* This file is part of the FreeType project, and may only be used +#* modified and distributed under the terms of the FreeType project +#* license, LICENSE.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 sub-Makefile is to define various build and +#* platform specific variables before including the sub-Makefile +#* containing the FreeType library rules, found in +#* +#* $(TOP)/config/freetype.mk +#* +#* The following variables must be defined before including this +#* file : +#* +#* TOP Pathname to the top of the FreeType sources +#* hierarchy +#* +#* This file should define the following variables before including +#* the FreeType library rules file : +#* +#* BUILD Pathname to the platform-specific files used +#* for the build. Usually `$(TOP)/config/' +#* +#* SEP Directory separator for the current platform. +#* Either / or \ (maybe : on Macs) +#* +#* DELETE The forced remove/delete command to erase one or more +#* files +#* +#* INCLUDE The location of all public header files. e.g. +#* `$(TOP)/include'include' * +#* +#* SRC The directory containing all sources. e.g. +#* '$(TOP)/src' +#* +#* OBJ_DIR The location where compiled object files will be +#* placed, e.g. '$(TOP)/obj' +#* +#* LIB_DIR The location where the resulting library file will be +#* placed, e.g. '$(TOP)/obj' +#* +#* LIBRARY The filename of the resulting library file, without +#* its extension.. e.g. 'libfreetype' or 'freetype' +#* +#* O The object file suffix. Can be '.o', '.obj,' '.lo,' +#* ';coff,' etc. +#* +#* A The library file suffix. Can be '.a' '.so,' '.lib' +#* '.dll,' etc. +#* +#* I The path inclusion flag. Some compilers use a +#* different flag than '-I' to specify an additional +#* include path. Examples are '/i=' or '-J ', etc. +#* +#* D The macro definition flag. I haven't met compilers +#* which don't use the '-D' switch to define a macro, but +#* who knows... +#* +#* T The compilation flag used to identify the target. Some +#* compilers use a different flag than '-o ' to specify +#* the name of the target object file. +#* +#* CFLAGS The set of flags used to compile object files. +#* (usually contains the flag '-c'). +#* +#* +#* +#******************************************************************* + +ifndef TOP +TOP := . +endif + +DELETE := del +SEP := / +BUILD := $(TOP)$(SEP)config$(SEP)win32 +PLATFORM := win32 +CC := lcc + +# the directory where all object files are placed +# +OBJ_DIR := $(TOP)$(SEP)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, this can be .o, .tco, .obj, etc.. +# depending on the platform +# +O := obj + +# the library file extension, this can be .a, .lib, etc.. +# depending on the platform +# +A := 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", etc... +# +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 + + +# Target flag - LCC uses "-Fo" instead of "-o ", what a broken compiler +# +# +T := -Fo + +# 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 + + + +# C flags +# +# These should concern : +# +# - debug output +# - optimization +# - warnings +# - ansi compliance.. +# +ifndef CFLAGS +CFLAGS := -c -g2 -O +endif + +ifdef BUILD_FREETYPE + +include $(TOP)/config/freetype.mk + +# 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} +# +# The LCC-Win32 Librarian, called LCCLIB needs all object files in the current +# directory. That _is_ stupid, but we'll have to deal with it.. +# + +DIR_OBJ := $(subst /,\\,$(OBJ_DIR)) + +$(FT_LIBRARY): $(OBJECTS_LIST) + @$(TOP)/config/win32/lcclib.bat + +endif + + diff --git a/config/win32/Makefile.vcc b/config/win32/Makefile.vcc new file mode 100644 index 000000000..eb251c688 --- /dev/null +++ b/config/win32/Makefile.vcc @@ -0,0 +1,174 @@ +#******************************************************************* +#* +#* FreeType 2 Configuration rules for Visual C++ on Win32 +#* +#* Copyright 1996-1999 by +#* David Turner, Robert Wilhelm, and Werner Lemberg. +#* +#* This file is part of the FreeType project, and may only be used +#* modified and distributed under the terms of the FreeType project +#* license, LICENSE.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 sub-Makefile is to define various build and +#* platform specific variables before including the sub-Makefile +#* containing the FreeType library rules, found in +#* +#* $(TOP)/config/freetype.mk +#* +#* The following variables must be defined before including this +#* file : +#* +#* TOP Pathname to the top of the FreeType sources +#* hierarchy +#* +#* This file should define the following variables before including +#* the FreeType library rules file : +#* +#* BUILD Pathname to the platform-specific files used +#* for the build. Usually `$(TOP)/config/' +#* +#* SEP Directory separator for the current platform. +#* Either / or \ (maybe : on Macs) +#* +#* DELETE The forced remove/delete command to erase one or more +#* files +#* +#* INCLUDE The location of all public header files. e.g. +#* `$(TOP)/include'include' * +#* +#* SRC The directory containing all sources. e.g. +#* '$(TOP)/src' +#* +#* OBJ_DIR The location where compiled object files will be +#* placed, e.g. '$(TOP)/obj' +#* +#* LIB_DIR The location where the resulting library file will be +#* placed, e.g. '$(TOP)/obj' +#* +#* LIBRARY The filename of the resulting library file, without +#* its extension.. e.g. 'libfreetype' or 'freetype' +#* +#* O The object file suffix. Can be '.o', '.obj,' '.lo,' +#* ';coff,' etc. +#* +#* A The library file suffix. Can be '.a' '.so,' '.lib' +#* '.dll,' etc. +#* +#* I The path inclusion flag. Some compilers use a +#* different flag than '-I' to specify an additional +#* include path. Examples are '/i=' or '-J ', etc. +#* +#* D The macro definition flag. I haven't met compilers +#* which don't use the '-D' switch to define a macro, but +#* who knows... +#* +#* T The compilation flag used to identify the target. Some +#* compilers use a different flag than '-o ' to specify +#* the name of the target object file. +#* +#* CFLAGS The set of flags used to compile object files. +#* (usually contains the flag '-c'). +#* +#* +#* +#******************************************************************* + +DELETE := del +SEP := / +BUILD := $(TOP)$(SEP)config$(SEP)win32 +PLATFORM := win32 +CC := cl + +# the directory where all object files are placed +# +OBJ_DIR := $(TOP)$(SEP)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, this can be .o, .tco, .obj, etc.. +# depending on the platform +# +O := obj + +# the library file extension, this can be .a, .lib, etc.. +# depending on the platform +# +A := 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", etc... +# +I := /I + + +# 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 + + +# C flag used to define a macro before the compilation of a given +# source object. Usually is '-D' like in "-DDEBUG" +# +D := /D + +# Target flag - LCC uses "-Fo" instead of "-o ", what a broken compiler +# +# +T := /Fo + +# C flags +# +# These should concern : +# +# - debug output +# - optimization +# - warnings +# - ansi compliance.. +# +ifndef CFLAGS +CFLAGS := /nologo /c /Ox /G5 /Za /W3 /WX +endif + +ifdef BUILD_FREETYPE + +include $(TOP)/config/freetype.mk + +# 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} +# +# The LCC-Win32 Librarian, called LCCLIB needs all object files in the current +# directory. That _is_ stupid, but we'll have to deal with it.. +# + +DIR_OBJ := $(subst /,\\,$(OBJ_DIR)) + +$(FT_LIBRARY): $(OBJECTS_LIST) + lib /out:$@ $(OBJECTS_LIST) + +endif + + diff --git a/config/win32/detect.mk b/config/win32/detect.mk new file mode 100644 index 000000000..3385ab650 --- /dev/null +++ b/config/win32/detect.mk @@ -0,0 +1,66 @@ +# +# This file is used to detect a Win32 host platform. +# +# This configuration file to be used depends on the value of the CC +# environment variable. +# +# + +# 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're running a win32 platform (or an emulation) +# + +ifeq ($(PLATFORM),ansi) +ifdef COMSPEC + +is_windows := $(findstring Windows,$(strip $(shell ver))) +ifneq ($(is_windows),) + +PLATFORM := win32 +DELETE := del +COPY := copy + +CONFIG_FILE := Makefile.gcc # gcc Makefile by default - aren't we biased ;-) +SEP := / +ifeq ($(CC),cc) +CC := gcc +endif + +ifneq ($(findstring visualc,$(MAKECMDGOALS)),) # Visual C/C++ +CONFIG_FILE := Makefile.vcc +SEP := $(BACKSLASH) +CC := cl +visualc: setup +endif + +ifneq ($(findstring watcom,$(MAKECMDGOALS)),) # Watcom C/C++ +CONFIG_FILE := Makefile.wat +SEP := $(BACKSLASH) +CC := wcc386 +watcom: setup +endif + +ifneq ($(findstring visualage,$(MAKECMDGOALS)),) # Visual Age C++ +CONFIG_FILE := Makefile.icc +SEP := $(BACKSLASH) +CC := icc +visualage: setup +endif + +ifneq ($(findstring lcc,$(MAKECMDGOALS)),) # LCC-Win32 +CONFIG_FILE := Makefile.lcc +SEP := $(BACKSLASH) +CC := lcc +lcc: setup +endif + +CONFIG_RULES := $(TOP)\config\win32\$(CONFIG_FILE) + +setup: dos_setup + +endif #test Windows +endif #test COMSPEC +endif #test PLATFORM + diff --git a/config/win32/ftconfig.h b/config/win32/ftconfig.h new file mode 100644 index 000000000..43a4c9522 --- /dev/null +++ b/config/win32/ftconfig.h @@ -0,0 +1,182 @@ +/***************************************************************************/ +/* */ +/* ftconfig.h */ +/* */ +/* ANSI-specific configuration file (specification only). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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. Porters are free to copy this file and */ + /* adapt it to suit their own system. */ + /* */ + /* IMPORTANT NOTE: */ + /* */ + /* Porters, read carefully the comments in `ftsys.h' before trying to */ + /* port this file to your system. It contains many essential */ + /* remarks, and will ease your work greatly. */ + /* */ + /*************************************************************************/ + + +#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/arch/' directory, and edit it to port the engine. */ + /* */ + /*************************************************************************/ + + +/* Define to empty if the keyword does not work. */ +/* #undef const */ + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* We use values to know the sizes of the types. */ +#include + +/* The number of bytes in an `int' type. */ +#if UINT_MAX == 0xFFFFFFFF +#define SIZEOF_INT 4 +#elif UINT_MAX == 0xFFFF +#define SIZEOF_INT 2 +#elif UINT_MAX > 0xFFFFFFFF && UINT_MAX == 0xFFFFFFFFFFFFFFFF +#define 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 SIZEOF_LONG 4 +#elif ULONG_MAX > 0xFFFFFFFF && ULONG_MAX == 0xFFFFFFFFFFFFFFFF +#define SIZEOF_LONG 8 +#else +#error "Unsupported number of bytes in `long' type!" +#endif + +/* Define if you have the memcpy function. */ +#define HAVE_MEMCPY 1 + +/* Define if you have the header file. */ +#define HAVE_FCNTL_H 0 + +/* Define if you have the header file. */ +#define HAVE_UNISTD_H 0 + + +/* Preferred alignment of data */ +#define FT_ALIGNMENT 8 + + + + /*************************************************************************/ + /* */ + /* AUTOMATIC CONFIGURATION MACROS */ + /* */ + /* These macros are computed from the ones defined above. Don't touch */ + /* their definition, unless you know precisely what you're 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_Word16; + +#if SIZEOF_INT == 4 + + typedef signed int FT_Int32; + typedef unsigned int FT_Word32; + +#elif SIZEOF_LONG == 4 + + typedef signed long FT_Int32; + typedef unsigned long FT_Word32; + +#else +#error "no 32bit type found - please check your configuration files" +#endif + +#if SIZEOF_LONG == 8 + + /* LONG64 must be defined when a 64-bit type is available */ +#define LONG64 +#define INT64 long + +#else + + + /*************************************************************************/ + /* */ + /* GCC provides the non-ANSI 'long long' 64-bit type. You can activate */ + /* it by defining the FTCALC_USE_LONG_LONG macro in `ftconfig.h'. Note */ + /* that this will produce many -ansi warnings during library */ + /* compilation. */ + /* */ +#ifdef FTCALC_USE_LONG_LONG + +#define LONG64 +#define INT64 long long + +#endif /* FTCALC_USE_LONG_LONG */ +#endif + + +#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 LOCAL_DEF +#define BASE_FUNC LOCAL_FUNC +#else +#define BASE_DEF extern +#define BASE_FUNC /* nothing */ +#endif + +#ifndef EXPORT_DEF +#define EXPORT_DEF extern +#endif + +#ifndef EXPORT_FUNC +#define EXPORT_FUNC /* nothing */ +#endif + +#endif /* FTCONFIG_H */ + + +/* END */ diff --git a/config/win32/ftoption.h b/config/win32/ftoption.h new file mode 100644 index 000000000..852f65fbb --- /dev/null +++ b/config/win32/ftoption.h @@ -0,0 +1,162 @@ +#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 file contains macros that apply to */ + /* all of FreeType. Driver-specific configurations are placed in each */ + /* driver directory (e.g. `freetype/drivers/ttlib/ttconfig.h'). */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* 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're sure that you'll never use a font driver */ + /* with an alternate glyph format, this will reduce the size of the */ + /* base layer code. */ + /* */ +#define FT_CONFIG_OPTION_ALTERNATE_GLYPH_FORMATS + + /*************************************************************************/ + /* */ + /* GCC provides the non-ANSI `long long' 64-bit type. You can activate */ + /* it by defining the FTCALC_USE_LONG_LONG macro here. Note however */ + /* that we did not experience any improvement in speed with gcc, and */ + /* that the final code seems bigger when linked. */ + /* */ +#undef FTCALC_USE_LONG_LONG + + + /*************************************************************************/ + /* */ + /* When compiling FreeType as a DLL, some systems/compilers need a */ + /* special keyword in front of each function definition instead of */ + /* `extern'. */ + /* */ + /* The macros EXPORT_DEF and EXPORT_FUNC are thus used to define */ + /* exported library function interfaces and exported library functions */ + /* implementations respectively. */ + /* */ + /* If not defined here, they automatically default to `extern' and void */ + /* later in this header file. */ + /* */ +#undef EXPORT_DEF +#undef 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. */ + /* */ +#undef FT_DEBUG_LEVEL_ERROR +#undef FT_DEBUG_LEVEL_TRACE + + + /*************************************************************************/ + /* */ + /* Anti-aliasing support */ + /* */ + /* Undefine this macro only if you want to disable the anti-aliasing */ + /* support in FreeType. This will save you about 5 Kb of code. It */ + /* may be important for some embedded systems. */ + /* */ +#define FT_CONFIG_OPTION_ANTI_ALIAS + + + /*************************************************************************/ + /* */ + /* Endianess performance improvement */ + /* */ + /* FreeType is completely endian-independent, and can thus be compiled */ + /* directly on _any_ machine. However, some components of the library */ + /* provide improved routines for the cases where endianess is known. */ + /* */ + /* It usually results in speed-ups and reduced code size. Note that */ + /* you should not define both of these macros. */ + /* */ + /* */ + /* NOTE: For now, only the scan-line converter (base/ftraster.c) uses */ + /* these macros to speed-up some anti-alias rendering routines. */ + /* */ +#undef FT_CONFIG_OPTION_LITTLE_ENDIAN +#undef FT_CONFIG_OPTION_BIG_ENDIAN + + + /*************************************************************************/ + /* */ + /* Define this configuration macro whenever you want to build a version */ + /* of FreeType that does not include a default `system' component. */ + /* */ + /* Note that this will prevent the compilation of `ftinit', hence the */ + /* function FT_Init_FreeType */ + /* */ +#undef FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM + + + /*************************************************************************/ + /* */ + /* 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 4 Kb */ + /* */ +#define FT_RENDER_POOL_SIZE 32768 + + + /*************************************************************************/ + /* */ + /* FT_MAX_DRIVERS */ + /* */ + /* The maximum number of font drivers that can be registered in a */ + /* single FreeType library object. 8 seems to be a good choice due */ + /* to the relative low actual number of drivers ;-) */ + /* */ +#define FT_MAX_DRIVERS 8 + + + /*************************************************************************/ + /* */ + /* FT_MAX_EXTENSIONS */ + /* */ + /* The maximum number of extensions that can be registered in a */ + /* single font driver. 8 seems to be a good choice for now.. */ + /* */ +#define FT_MAX_EXTENSIONS 8 + + + /*************************************************************************/ + /* */ + /* FT_MAX_GLYPH_FORMATS */ + /* */ + /* The maximum number of glyph image formats that might be registered */ + /* in a given library instance. 8 seems to be a good choice due to */ + /* the relatively low number of current formats ;-) */ + /* */ + +#define FT_MAX_GLYPH_FORMATS 8 + + + +#endif /* FTOPTION_H */ diff --git a/config/win32/ftsystem.c b/config/win32/ftsystem.c new file mode 100644 index 000000000..459f668e9 --- /dev/null +++ b/config/win32/ftsystem.c @@ -0,0 +1,214 @@ +/************************************************************************** + * + * ftsystem.h 1.0 + * + * ANSI-specific FreeType low-level system interface + * + * This file contains the definition of interface used by FreeType + * to access low-level, i.e. memory management, i/o access as well + * as thread synchronisation. + * + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.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 + + /*********************************************************************/ + /* */ + /* MEMORY MANAGEMENT INTERFACE */ + /* */ + +/************************************************************************ + * + * + * FT_Alloc_Func + * + * + * The memory allocator function type + * + * + * system :: pointer to the system object + * size :: requested size in bytes + * + * + * block :: address of newly allocated block + * + * + * Error code. 0 means success. + * + * + * If your allocation routine ALWAYS zeroes the new block, you + * should set the flag FT_SYSTEM_FLAG_ALLOC_ZEROES in your system + * object 'flags' field. + * + * If you have set the flag FT_SYSTEM_FLAG_REPORT_CURRENT_ALLOC in + * your system's "system_flags" field, this function should update + * the "current_alloc" field of the system object. + * + ************************************************************************/ + + static + void* ft_alloc( FT_Memory memory, + long size ) + { + (void)memory; + return malloc(size); + } + + +/************************************************************************ + * + * + * FT_Realloc_Func + * + * + * The memory reallocator function type + * + * + * system :: pointer to the system object + * new_size :: new requested size in bytes + * + * + * block :: address of block in memory + * + * + * Error code. 0 means success. + * + * + * This function is _never_ called when the system flag + * FT_SYSTEM_FLAG_NO_REALLOC is set. Instead, the engine will emulate + * realloc through "alloc" and "free". + * + * Note that this is possible due to the fact that FreeType's + * "FT_Realloc" always requests the _current_ size of the reallocated + * block as a parameter, thus avoiding memory leaks. + * + * If you have set the flag FT_SYSTEM_FLAG_REPORT_CURRENT_ALLOC in + * your system's "system_flags" field, this function should update + * the "current_alloc" field of the system object. + * + ************************************************************************/ + + static + void* ft_realloc( FT_Memory memory, + long cur_size, + long new_size, + void* block ) + { + (void)memory; + (void)cur_size; + + return realloc( block, new_size ); + } + + +/************************************************************************ + * + * + * FT_Free_Func + * + * + * The memory release function type + * + * + * system :: pointer to the system object + * block :: address of block in memory + * + * + * If you have set the flag FT_SYSTEM_FLAG_REPORT_CURRENT_ALLOC in + * your system's "system_flags" field, this function should update + * the "current_alloc" field of the system object. + * + ************************************************************************/ + + static + void ft_free( FT_Memory memory, + void* block ) + { + (void)memory; + free( block ); + } + + /*********************************************************************/ + /* */ + /* RESOURCE MANAGEMENT INTERFACE */ + /* */ + + +#define STREAM_FILE(stream) ((FILE*)stream->descriptor.pointer) + + static + void ft_close_stream( FT_Stream stream ) + { + fclose( STREAM_FILE(stream) ); + } + + static + unsigned long ft_io_stream( FT_Stream stream, + unsigned long offset, + char* buffer, + unsigned long count ) + { + FILE* file; + + file = STREAM_FILE(stream); + + fseek( file, offset, SEEK_SET ); + return (unsigned long)fread( buffer, count, 1, file ); + } + + + extern + int FT_New_Stream( const char* filepathname, + FT_Stream stream ) + { + FILE* file; + + file = fopen( filepathname, "rb" ); + if (!file) + 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->pos = 0; + + stream->read = ft_io_stream; + stream->close = ft_close_stream; + + return 0; + } + + + extern + 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; + } + diff --git a/config/win32/lcclib.bat b/config/win32/lcclib.bat new file mode 100644 index 000000000..ac8f51b18 --- /dev/null +++ b/config/win32/lcclib.bat @@ -0,0 +1,12 @@ +@cd obj +@LCCLIB /out:freetype.lib *.obj +@echo The library file `obj/freetype.lib' was generated. +@exit 0 + +; the LCC Librarian has many flaws, one of them is that it *requires* that +; all object files be placed in the current directory. Another flaw is that +; it cannot accept a long list of object files. +; +; this file is used to build the library file `obj/freetype.lib' +; + diff --git a/demos/Makefile b/demos/Makefile new file mode 100644 index 000000000..e23d9d17f --- /dev/null +++ b/demos/Makefile @@ -0,0 +1,227 @@ +.PHONY: exes +all: exes + +#################################################################### +# +# TOP is the directory where the main FreeType source is found, +# as well as the 'config.mk' file +# + +ifndef TOP +TOP := .. +endif + +#################################################################### +# +# Check that we have a working `config.mk' in the above directory. +# If not, issue a warning message, then stop there.. +# +ifeq ($(wildcard $(TOP)/config.mk),) +no_config_mk := 1 +endif + +ifdef no_config_mk + +exes: + @echo Please compile the library before the demo programs !! + +else + +#################################################################### +# +# Good, now include the `config.mk' in order to know how to build +# object files from sources, as well as other things (compiler flags) +# +include ../config.mk + +#################################################################### +# +# Detect DOS-like platforms, currently DOS, Win 3.1, Win32 & OS/2 +# +# +ifneq ($(findstring $(PLATFORM),os2 win16 win32 dos),) +DOSLIKE := 1 +endif + + +################################################################### +# +# Clean-up rules. Because the `del' command on DOS-like platforms +# cannot take a long list of arguments, we simply erase the directory +# contents.. +# +.PHONY: clean distclean + +ifdef DOSLIKE +clean_demo: + -del obj\*.$O + -del src\*.bak + +distclean_demo: clean_demo + -del obj\*.* + -del bin\*.exe +else +clean_demo: + -$(DELETE) $(OBJ_)*.$O + -$(DELETE) $(SRC_)*.bak graph$(SEP)*.bak + -$(DELETE) $(SRC_)*~ graph$(SEP)*~ + + +distclean_demo: clean_demo + -$(DELETE) $(BIN_)* +endif + +clean: clean_demo +distclean: distclean_demo + +#################################################################### +# +# Define a few important variables now +# +# +TOP_ := $(TOP)$(SEP) +SRC_ := $(TOP)$(SEP)src$(SEP) + +BIN_ := bin$(SEP) +OBJ_ := obj$(SEP) + +GRAPH_DIR := graph + +SRC_DIR := src +SRC_DIR_ := $(SRC_DIR)$(SEP) + + +FT_INCLUDES := $(BUILD) $(TOP_)include $(SRC_)base +TT_INCLUDES := $(SRC_)shared $(SRC_)truetype +T1_INCLUDES := $(SRC_)shared $(SRC_)type1 + +CFLAGS = -c -O0 -g $(INCLUDES:%=$I%) -Wall -W -ansi +CC := $(CC) +LINK := $(CC) +FTLIB := $(LIB_DIR)$(SEP)$(LIBRARY).$A + + +#################################################################### +# +# Compute the executable suffix to use, and put it in `E'. +# It is ".exe" on DOS-ish platforms, and nothing otherwise +# +ifdef DOSLIKE +E := .exe +else +E := +endif + +################################################################### +# +# The list of demonstration programs to build. +# +EXES := ftlint t1dump ftview fttimer + +ifneq ($(findstring $(PLATFORM),os2 unix),) +EXES += ttdebug +endif + +################################################################### +# +# Include the rules needed to compile the graphics sub-system. +# This will also select which graphics driver to compile to the +# sub-system.. +# +include $(GRAPH_DIR)/rules.mk + +exes: $(EXES:%=$(BIN_)%$E) + + +INCLUDES := $(FT_INCLUDES) + +#################################################################### +# +# Rules for compiling object files for text-only demos +# + +COMMON_OBJ := $(OBJ_)common.o +$(COMMON_OBJ): $(SRC_DIR_)common.c + $(CC) $(CFLAGS) $T$@ $< + +$(OBJ_)%.$O: $(SRC_DIR_)%.c $(FTLIB) + $(CC) $(CFLAGS) $T$@ $< + +$(OBJ_)ftlint.$O: $(SRC_DIR_)ftlint.c + $(CC) $(CFLAGS) $T$@ $< + +$(OBJ_)fttry.$O: $(SRC_DIR_)fttry.c + $(CC) $(CFLAGS) $T$@ $< + + +$(OBJ_)ftview.$O: $(SRC_DIR_)ftview.c $(GRAPH_LIB) + $(CC) $(CFLAGS) $(GRAPH_INCLUDES:%=$I%) $T$@ $< + +$(OBJ_)fttimer.$O: $(SRC_DIR_)fttimer.c $(GRAPH_LIB) + $(CC) $(CFLAGS) $(GRAPH_INCLUDES:%=$I%) $T$@ $< + +#$(OBJ_)ftsbit.$O: $(SRC_DIR)/ftsbit.c $(GRAPH_LIB) +# $(CC) $(CFLAGS) $T$@ $< + + +#################################################################### +# +# Special rule to compile the `t1dump' program as it includes +# the Type1 source path +# +$(OBJ_)t1dump.$O: $(SRC_DIR)/t1dump.c + $(CC) $(CFLAGS) $(T1_INCLUDES:%=$I%) $T$@ $< + + +#################################################################### +# +# Special rule to compile the `ttdebug' program as it includes +# the TrueType source path and needs extra flags for correct keyboard +# handling on Unix +# + +# POSIX TERMIOS: Do not define if you use OLD U*ix like 4.2BSD. +# +# detect a Unix system +ifeq ($(PLATFORM),unix) +EXTRAFLAGS = $DUNIX $DHAVE_POSIX_TERMIOS +endif + +$(OBJ_)ttdebug.$O: $(SRC_DIR)/ttdebug.c + $(CC) $(CFLAGS) $(TT_INCLUDES:%=$I%) $T$@ $< $(EXTRAFLAGS) + + +#################################################################### +# +# Rules used to link the executables. Note that they could be +# over-ridden by system-specific things.. +# + +$(BIN_)ftlint$E: $(OBJ_)ftlint.$O $(FTLIB) + $(LINK) $(LFLAGS) $T$@ $< $(FTLIB) $(EFENCE) + + +$(BIN_)fttry$E: $(OBJ_)fttry.$O $(FTLIB) + $(LINK) $(LFLAGS) $T$@ $< $(FTLIB) $(EFENCE) + + +$(BIN_)ftsbit$E: $(OBJ_)ftsbit.$O $(FTLIB) + $(LINK) $(LFLAGS) $T$@ $< $(FTLIB) $(EFENCE) + + +$(BIN_)t1dump$E: $(OBJ_)t1dump.$O $(FTLIB) + $(LINK) $(LFLAGS) $T$@ $< $(FTLIB) $(EFENCE) + +$(BIN_)ttdebug$E: $(OBJ_)ttdebug.$O $(FTLIB) + $(LINK) $(LFLAGS) $T$@ $< $(FTLIB) $(EFENCE) + + +$(BIN_)ftview$E: $(OBJ_)ftview.$O $(FTLIB) $(GRAPH_LIB) $(COMMON_OBJ) + $(LINK) $(LFLAGS) $T$@ $< $(FTLIB) $(GRAPH_LINK) $(COMMON_OBJ) $(EFENCE) + +$(BIN_)fttimer$E: $(OBJ_)fttimer.$O $(FTLIB) $(GRAPH_LIB) $(COMMON_OBJ) + $(LINK) $(LFLAGS) $T$@ $< $(FTLIB) $(GRAPH_LINK) $(EFENCE) + +endif + + diff --git a/demos/config/os2/gros2pm.c b/demos/config/os2/gros2pm.c new file mode 100644 index 000000000..976f58d32 --- /dev/null +++ b/demos/config/os2/gros2pm.c @@ -0,0 +1,887 @@ +#include "gros2pm.h" +#include "grdevice.h" + +#define INCL_DOS +#define INCL_WIN +#define INCL_GPI +#define INCL_SUB + +#include +#include +#include +#include + + + static void Panic( const char* message ) + { + fprintf( stderr, "%s", message ); + exit(1); + } + + typedef struct Translator + { + ULONG os2key; + grKey grkey; + + } Translator; + + + static + Translator key_translators[] = + { + { VK_BACKSPACE, grKeyBackSpace }, + { VK_TAB, grKeyTab }, + { VK_ENTER, grKeyReturn }, + { VK_ESC, grKeyEsc }, + { VK_HOME, grKeyHome }, + { VK_LEFT, grKeyLeft }, + { VK_UP, grKeyUp }, + { VK_RIGHT, grKeyRight }, + { VK_DOWN, grKeyDown }, + { VK_PAGEUP, grKeyPageUp }, + { VK_PAGEDOWN, grKeyPageDown }, + { VK_END, grKeyEnd }, + { VK_F1, grKeyF1 }, + { VK_F2, grKeyF2 }, + { VK_F3, grKeyF3 }, + { VK_F4, grKeyF4 }, + { VK_F5, grKeyF5 }, + { VK_F6, grKeyF6 }, + { VK_F7, grKeyF7 }, + { VK_F8, grKeyF8 }, + { VK_F9, grKeyF9 }, + { VK_F10, grKeyF10 }, + { VK_F11, grKeyF11 }, + { VK_F12, grKeyF12 } + }; + + +#define MAX_PIXEL_MODES 32 + + static int num_pixel_modes = 0; + static grPixelMode pixel_modes[ MAX_PIXEL_MODES ]; + static int pixel_depth[ MAX_PIXEL_MODES ]; + + static HAB gr_anchor; /* device anchor block */ + + typedef POINTL PMBlitPoints[4]; + + + typedef struct grPMSurface_ + { + grSurface root; + grBitmap image; + + HAB anchor; /* handle to anchor block for surface's window */ + HWND frame_window; /* handle to window's frame */ + HWND client_window; /* handle to window's client */ + HWND title_window; /* handle to window's title bar */ + + HPS image_ps; /* memory presentation space used to hold */ + /* the surface's content under PM */ + HDC image_dc; /* memory device context for the image */ + + HEV event_lock; /* semaphore used in listen_surface */ + HMTX image_lock; /* a mutex used to synchronise access */ + /* to the memory presentation space */ + /* used to hold the surface */ + + TID message_thread; /* thread used to process this surface's */ + /* messages.. */ + + PBITMAPINFO2 bitmap_header;/* os/2 bitmap descriptor */ + HBITMAP os2_bitmap; /* Handle to OS/2 bitmap contained in image */ + BOOL ready; /* ??? */ + + long shades[256]; /* indices of gray levels in pixel_mode_gray */ + + POINTL surface_blit[4]; /* surface blitting table */ + POINTL magnify_blit[4]; /* magnifier blitting table */ + int magnification; /* level of magnification */ + POINTL magnify_center; + SIZEL magnify_size; + + grEvent event; + + PMBlitPoints blit_points; + + } grPMSurface; + + + + static + void enable_os2_iostreams( void ) + { + PTIB thread_block; + PPIB process_block; + + /* XXX : This is a very nasty hack, it fools OS/2 and let the program */ + /* call PM functions, even though stdin/stdout/stderr are still */ + /* directed to the standard i/o streams.. */ + /* The program must be compiled with WINDOWCOMPAT */ + /* */ + /* Credits go to Michal for finding this !! */ + /* */ + DosGetInfoBlocks( &thread_block, &process_block ); + process_block->pib_ultype = 3; + } + + + + static + int init_device( void ) + { + enable_os2_iostreams(); + + /* create an anchor block. This will allow this thread (i.e. the */ + /* main one) to call Gpi functions.. */ + gr_anchor = WinInitialize(0); + if (!gr_anchor) + { + /* could not initialise Presentation Manager */ + return -1; + } + + return 0; + } + + + + static + void done_device( void ) + { + /* Indicates that we do not use the Presentation Manager, this */ + /* will also release all associated resources.. */ + WinTerminate( gr_anchor ); + } + + + + /* close a given window */ + static + void done_surface( grPMSurface* surface ) + { + if ( surface->frame_window ) + WinDestroyWindow( surface->frame_window ); + + WinReleasePS( surface->image_ps ); + + grDoneBitmap( &surface->image ); + grDoneBitmap( &surface->root.bitmap ); + } + + + + + + static + void add_pixel_mode( grPixelMode pixel_mode, + int depth ) + { + if ( num_pixel_modes >= MAX_PIXEL_MODES ) + Panic( "X11.Too many pixel modes\n" ); + + pixel_modes[ num_pixel_modes ] = pixel_mode; + pixel_depth[ num_pixel_modes ] = depth; + + num_pixel_modes++; + } + + +#define LOCK(x) DosRequestMutexSem( x, SEM_INDEFINITE_WAIT ); +#define UNLOCK(x) DosReleaseMutexSem( x ) + + + static + const int pixel_mode_bit_count[] = + { + 0, + 1, /* mono */ + 4, /* pal4 */ + 8, /* pal8 */ + 8, /* grays */ + 15, /* rgb15 */ + 16, /* rgb16 */ + 24, /* rgb24 */ + 32 /* rgb32 */ + }; + + + /************************************************************************ + * + * Technical note : how the OS/2 Presntation Manager driver works + * + * PM is, in my opinion, a bloated and over-engineered graphics + * sub-system, even though it has lots of nice features. Here are + * a few tidbits about it : + * + * + * - under PM, a "bitmap" is a device-specific object whose bits are + * not directly accessible to the client application. This means + * that we must use a scheme like the following to display our + * surfaces : + * + * - hold, for each surface, its own bitmap buffer where the + * rest of MiGS writes directly. + * + * - create a PM bitmap object with the same dimensions (and + * possibly format). + * + * - copy the content of each updated rectangle into the + * PM bitmap with the function 'GpiSetBitmapBits'. + * + * - finally, "blit" the PM bitmap to the screen calling + * 'GpiBlitBlt' + * + * - but there is more : you cannot directly blit a PM bitmap to the + * screen with PM. The 'GpiBlitBlt' only works with presentation + * spaces. This means that we also need to create, for each surface : + * + * - a memory presentation space, used to hold the PM bitmap + * - a "memory device context" for the presentation space + * + * The blit is then performed from the memory presentation space + * to the screen's presentation space.. + * + * + * - because each surface creates its own event-handling thread, + * we must protect the surface's presentation space from concurrent + * accesses (i.e. calls to 'GpiSetBitmapBits' when drawing to the + * surface, and calls to 'GpiBlitBlt' when drawing it on the screen + * are performed in two different threads). + * + * we use a simple mutex to do this. + * + * + * - we also use a semaphore to perform a rendez-vous between the + * main and event-handling threads (needed in "listen_event"). + * + ************************************************************************/ + + static + void RunPMWindow( grPMSurface* surface ); + + + + + static + void convert_gray_to_pal8( grPMSurface* surface, + int x, + int y, + int w, + int h ) + { + grBitmap* target = &surface->image; + grBitmap* source = &surface->root.bitmap; + byte* write = (byte*)target->buffer + y*target->pitch + x; + byte* read = (byte*)source->buffer + y*source->pitch + x; + long* palette = surface->shades; + + while (h > 0) + { + byte* _write = write; + byte* _read = read; + byte* limit = _write + w; + + for ( ; _write < limit; _write++, _read++ ) + *_write = (byte) palette[ *_read ]; + + write += target->pitch; + read += source->pitch; + h--; + } + } + + + static + void convert_gray_to_16( grPMSurface* surface, + int x, + int y, + int w, + int h ) + { + grBitmap* target = &surface->image; + grBitmap* source = &surface->root.bitmap; + byte* write = (byte*)target->buffer + y*target->pitch + 2*x; + byte* read = (byte*)source->buffer + y*source->pitch + x; + long* palette = surface->shades; + + while (h > 0) + { + byte* _write = write; + byte* _read = read; + byte* limit = _write + 2*w; + + for ( ; _write < limit; _write += 2, _read++ ) + *(short*)_write = (short)palette[ *_read ]; + + write += target->pitch; + read += source->pitch; + h--; + } + } + + + static + void convert_gray_to_24( grPMSurface* surface, + int x, + int y, + int w, + int h ) + { + grBitmap* target = &surface->image; + grBitmap* source = &surface->root.bitmap; + byte* write = (byte*)target->buffer + y*target->pitch + 3*x; + byte* read = (byte*)source->buffer + y*source->pitch + x; + + while (h > 0) + { + byte* _write = write; + byte* _read = read; + byte* limit = _write + 3*w; + + for ( ; _write < limit; _write += 3, _read++ ) + { + byte color = *_read; + + _write[0] = + _write[1] = + _write[2] = color; + } + + write += target->pitch; + read += source->pitch; + h--; + } + } + + + static + void convert_gray_to_32( grPMSurface* surface, + int x, + int y, + int w, + int h ) + { + grBitmap* target = &surface->image; + grBitmap* source = &surface->root.bitmap; + byte* write = (byte*)target->buffer + y*target->pitch + 4*x; + byte* read = (byte*)source->buffer + y*source->pitch + x; + + while (h > 0) + { + byte* _write = write; + byte* _read = read; + byte* limit = _write + 4*w; + + for ( ; _write < limit; _write += 4, _read++ ) + { + byte color = *_read; + + _write[0] = + _write[1] = + _write[2] = + _write[3] = color; + } + + write += target->pitch; + read += source->pitch; + h--; + } + } + + + static + void convert_rectangle( grPMSurface* surface, + int x, + int y, + int w, + int h ) + { + int z; + + /* first of all, clip to the surface's area */ + if ( x >= surface->image.width || + x+w <= 0 || + y >= surface->image.rows || + y+h <= 0 ) + return; + + if ( x < 0 ) + { + w += x; + x = 0; + } + + z = (x + w) - surface->image.width; + if (z > 0) + w -= z; + + z = (y + h) - surface->image.rows; + if (z > 0) + h -= z; + + /* convert the rectangle to the target depth for gray surfaces */ + if (surface->root.bitmap.mode == gr_pixel_mode_gray) + { + switch (surface->image.mode) + { + case gr_pixel_mode_pal8 : + convert_gray_to_pal8( surface, x, y, w, h ); + break; + + case gr_pixel_mode_rgb555: + case gr_pixel_mode_rgb565: + convert_gray_to_16 ( surface, x, y, w, h ); + break; + + case gr_pixel_mode_rgb24: + convert_gray_to_24 ( surface, x, y, w, h ); + break; + + case gr_pixel_mode_rgb32: + convert_gray_to_32 ( surface, x, y, w, h ); + break; + + default: + ; + } + } + } + + + static + void refresh_rectangle( grPMSurface* surface, + int x, + int y, + int w, + int h ) + { + convert_rectangle( surface, x, y, w, h ); + + WinInvalidateRect( surface->client_window, NULL, FALSE ); + WinUpdateWindow( surface->frame_window ); + } + + + static + void set_title( grPMSurface* surface, + const char* title ) + { + WinSetWindowText( surface->title_window, (PSZ)title ); + } + + + + static + void listen_event( grPMSurface* surface, + int event_mask, + grEvent* grevent ) + { + ULONG ulRequestCount; + + (void) event_mask; /* ignored for now */ + + /* the listen_event function blocks until there is an event to process */ + DosWaitEventSem( surface->event_lock, SEM_INDEFINITE_WAIT ); + DosQueryEventSem( surface->event_lock, &ulRequestCount ); + *grevent = surface->event; + DosResetEventSem( surface->event_lock, &ulRequestCount ); + + return; + } + + + static + grPMSurface* init_surface( grPMSurface* surface, + grBitmap* bitmap ) + { + PBITMAPINFO2 bit; + SIZEL sizl = { 0, 0 }; + LONG palette[256]; + + /* create the bitmap - under OS/2, we support all modes as PM */ + /* handles all conversions automatically.. */ + if ( grNewBitmap( bitmap->mode, + bitmap->grays, + bitmap->width, + bitmap->rows, + bitmap ) ) + return 0; + + surface->root.bitmap = *bitmap; + + /* create the image and event lock */ + DosCreateEventSem( NULL, &surface->event_lock, 0, TRUE ); + DosCreateMutexSem( NULL, &surface->image_lock, 0, FALSE ); + + /* create the image's presentation space */ + surface->image_dc = DevOpenDC( gr_anchor, + OD_MEMORY, (PSZ)"*", 0L, 0L, 0L ); + + surface->image_ps = GpiCreatePS( gr_anchor, + surface->image_dc, + &sizl, + PU_PELS | GPIT_MICRO | + GPIA_ASSOC | GPIF_DEFAULT ); + + GpiSetBackMix( surface->image_ps, BM_OVERPAINT ); + + /* create the image's PM bitmap */ + bit = (PBITMAPINFO2)grAlloc( sizeof(BITMAPINFO2) + 256*sizeof(RGB2) ); + surface->bitmap_header = bit; + + bit->cbFix = sizeof( BITMAPINFOHEADER2 ); + bit->cx = surface->root.bitmap.width; + bit->cy = surface->root.bitmap.rows; + bit->cPlanes = 1; + + bit->argbColor[0].bBlue = 0; + bit->argbColor[0].bGreen = 0; + bit->argbColor[0].bRed = 0; + + bit->argbColor[1].bBlue = 255; + bit->argbColor[1].bGreen = 255; + bit->argbColor[1].bRed = 255; + + bit->cBitCount = pixel_mode_bit_count[ surface->root.bitmap.mode ]; + + surface->os2_bitmap = GpiCreateBitmap( surface->image_ps, + (PBITMAPINFOHEADER2)bit, + 0L, NULL, NULL ); + + GpiSetBitmap( surface->image_ps, surface->os2_bitmap ); + + bit->cbFix = sizeof( BITMAPINFOHEADER2 ); + GpiQueryBitmapInfoHeader( surface->os2_bitmap, + (PBITMAPINFOHEADER2)bit ); + + /* for gr_pixel_mode_gray, create a gray-levels logical palette */ + if ( bitmap->mode == gr_pixel_mode_gray ) + { + int x, count; + + count = bitmap->grays; + for ( x = 0; x < count; x++ ) + palette[x] = (((count-x)*255)/count) * 0x010101; + + /* create logical color table */ + GpiCreateLogColorTable( surface->image_ps, + (ULONG) LCOL_PURECOLOR, + (LONG) LCOLF_CONSECRGB, + (LONG) 0L, + (LONG) count, + (PLONG) palette ); + + /* now, copy the color indexes to surface->shades */ + for ( x = 0; x < count; x++ ) + surface->shades[x] = GpiQueryColorIndex( surface->image_ps, + 0, palette[x] ); + } + + /* set up the blit points array */ + surface->blit_points[1].x = surface->root.bitmap.width; + surface->blit_points[1].y = surface->root.bitmap.rows; + surface->blit_points[3] = surface->blit_points[1]; + + /* Finally, create the event handling thread for the surface's window */ + DosCreateThread( &surface->message_thread, + (PFNTHREAD) RunPMWindow, + (ULONG) surface, + 0UL, + 32920 ); + + surface->root.done = (grDoneSurfaceFunc) done_surface; + surface->root.refresh_rect = (grRefreshRectFunc) refresh_rectangle; + surface->root.set_title = (grSetTitleFunc) set_title; + surface->root.listen_event = (grListenEventFunc) listen_event; + + convert_rectangle( surface, 0, 0, bitmap->width, bitmap->rows ); + return surface; + } + + + + MRESULT EXPENTRY Message_Process( HWND handle, + ULONG mess, + MPARAM parm1, + MPARAM parm2 ); + + + static + void RunPMWindow( grPMSurface* surface ) + { + unsigned char class_name[] = "DisplayClass"; + ULONG class_flags; + + static HMQ queue; + QMSG message; + + /* create an anchor to allow this thread to use PM */ + surface->anchor = WinInitialize(0); + if (!surface->anchor) + { + printf( "Error doing WinInitialize()\n" ); + return; + } + + /* create a message queue */ + queue = WinCreateMsgQueue( surface->anchor, 0 ); + if (!queue) + { + printf( "Error doing >inCreateMsgQueue()\n" ); + return; + } + + /* register the window class */ + if ( !WinRegisterClass( surface->anchor, + (PSZ) class_name, + (PFNWP) Message_Process, + CS_SIZEREDRAW, + 0 ) ) + { + printf( "Error doing WinRegisterClass()\n" ); + return; + } + + /* create the PM window */ + class_flags = FCF_TITLEBAR | FCF_MINBUTTON | FCF_DLGBORDER | + FCF_TASKLIST | FCF_SYSMENU; + + surface->frame_window = WinCreateStdWindow( + HWND_DESKTOP, + WS_VISIBLE, + &class_flags, + (PSZ) class_name, + (PSZ) "FreeType PM Graphics", + WS_VISIBLE, + 0, 0, + &surface->client_window ); + if (!surface->frame_window) + { + printf( "Error doing WinCreateStdWindow()\n" ); + return; + } + + /* find the title window handle */ + surface->title_window = WinWindowFromID( surface->frame_window, + FID_TITLEBAR ); + + /* set Window size and position */ + WinSetWindowPos( surface->frame_window, + 0L, + (SHORT) 60, + (SHORT) WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN ) - + surface->root.bitmap.rows + 100, + + (SHORT) WinQuerySysValue( HWND_DESKTOP, SV_CYDLGFRAME )*2 + + surface->root.bitmap.width, + + (SHORT) WinQuerySysValue( HWND_DESKTOP, SV_CYTITLEBAR ) + + WinQuerySysValue( HWND_DESKTOP, SV_CYDLGFRAME )*2 + + surface->root.bitmap.rows, + + SWP_SIZE | SWP_MOVE ); + + /* save the handle to the current surface within the window words */ + WinSetWindowPtr( surface->frame_window,QWL_USER, surface ); + + /* run the message queue till the end */ + while ( WinGetMsg( surface->anchor, &message, (HWND)NULL, 0, 0 ) ) + WinDispatchMsg( surface->anchor, &message ); + + /* clean-up */ + WinDestroyWindow( surface->frame_window ); + surface->frame_window = 0; + + WinDestroyMsgQueue( queue ); + WinTerminate( surface->anchor ); + + /* await death... */ + while ( 1 ) + DosSleep( 100 ); + } + + + + + /* Message processing for our PM Window class */ + MRESULT EXPENTRY Message_Process( HWND handle, + ULONG mess, + MPARAM parm1, + MPARAM parm2 ) + { + static HDC screen_dc; + static HPS screen_ps; + static BOOL minimized; + + SIZEL sizl; + SWP swp; + + grPMSurface* surface; + + /* get the handle to the window's surface */ + surface = (grPMSurface*)WinQueryWindowPtr( handle, QWL_USER ); + + switch( mess ) + { + case WM_DESTROY: + /* warn the main thread to quit if it didn't know */ + surface->event.type = gr_event_key; + surface->event.key = grKeyEsc; + DosPostEventSem( surface->event_lock ); + break; + + case WM_CREATE: + /* set original magnification */ + minimized = FALSE; + + /* create Device Context and Presentation Space for screen. */ + screen_dc = WinOpenWindowDC( handle ); + screen_ps = GpiCreatePS( surface->anchor, + screen_dc, + &sizl, + PU_PELS | GPIT_MICRO | + GPIA_ASSOC | GPIF_DEFAULT ); + + /* take the input focus */ + WinFocusChange( HWND_DESKTOP, handle, 0L ); + break; + + case WM_MINMAXFRAME: + /* to update minimized if changed */ + swp = *((PSWP) parm1); + if ( swp.fl & SWP_MINIMIZE ) + minimized = TRUE; + if ( swp.fl & SWP_RESTORE ) + minimized = FALSE; + return WinDefWindowProc( handle, mess, parm1, parm2 ); + break; + + case WM_ERASEBACKGROUND: + case WM_PAINT: + /* copy the memory image of the screen out to the real screen */ + DosRequestMutexSem( surface->image_lock, SEM_INDEFINITE_WAIT ); + WinBeginPaint( handle, screen_ps, NULL ); + + /* main image and magnified picture */ + GpiBitBlt( screen_ps, + surface->image_ps, + 4L, + surface->blit_points, + ROP_SRCCOPY, BBO_AND ); + + WinEndPaint( screen_ps ); + DosReleaseMutexSem( surface->image_lock ); + break; + + case WM_CHAR: + if ( CHARMSG( &mess )->fs & KC_KEYUP ) + break; + + /* look for a specific vkey */ + { + int count = sizeof( key_translators )/sizeof( key_translators[0] ); + Translator* trans = key_translators; + Translator* limit = trans + count; + + for ( ; trans < limit; trans++ ) + if ( CHARMSG(&mess)->vkey == trans->os2key ) + { + surface->event.key = trans->grkey; + goto Do_Key_Event; + } + } + + /* otherwise, simply record the character code */ + if ( (CHARMSG( &mess )->fs & KC_CHAR) == 0 ) + break; + + surface->event.key = CHARMSG(&mess)->chr; + + Do_Key_Event: + surface->event.type = gr_event_key; + DosPostEventSem( surface->event_lock ); + break; + + default: + return WinDefWindowProc( handle, mess, parm1, parm2 ); + } + + return (MRESULT) FALSE; + } + + + + + + + +#if 0 + static + grKey KeySymTogrKey( key ) + { + grKey k; + int count = sizeof(key_translators)/sizeof(key_translators[0]); + Translator* trans = key_translators; + Translator* limit = trans + count; + + k = grKeyNone; + + while ( trans < limit ) + { + if ( trans->xkey == key ) + { + k = trans->grkey; + break; + } + trans++; + } + + return k; + } + + + + static + void listen_event( grPMSurface* surface, + int event_mask, + grEvent* grevent ) + { + grKey grkey; + + /* XXXX : For now, ignore the event mask, and only exit when */ + /* a key is pressed.. */ + (void)event_mask; + + + /* Now, translate the keypress to a grKey */ + /* If this wasn't part of the simple translated keys, simply get the charcode */ + /* from the character buffer */ + grkey = grKEY(key_buffer[key_cursor++]); + + Set_Key: + grevent->type = gr_key_down; + grevent->key = grkey; + } + +#endif + + + + grDevice gr_os2pm_device = + { + sizeof( grPMSurface ), + "os2pm", + + init_device, + done_device, + + (grDeviceInitSurfaceFunc) init_surface, + + 0, + 0 + + }; + + diff --git a/demos/config/os2/gros2pm.def b/demos/config/os2/gros2pm.def new file mode 100644 index 000000000..4a77c632c --- /dev/null +++ b/demos/config/os2/gros2pm.def @@ -0,0 +1,5 @@ +NAME WINDOWCOMPAT + +DESCRIPTION 'FreeType Graphics' +HEAPSIZE 8192 +STACKSIZE 40888 diff --git a/demos/config/os2/gros2pm.h b/demos/config/os2/gros2pm.h new file mode 100644 index 000000000..229358025 --- /dev/null +++ b/demos/config/os2/gros2pm.h @@ -0,0 +1,23 @@ +#ifndef GROS2PM_H +#define GROS2PM_H + +#include "grobjs.h" + + extern + grDevice gr_os2pm_device; + +#ifdef GR_INIT_BUILD + static + grDeviceChain gr_os2pm_device_chain = + { + "os2pm", + &gr_os2pm_device, + GR_INIT_DEVICE_CHAIN + }; + +#undef GR_INIT_DEVICE_CHAIN +#define GR_INIT_DEVICE_CHAIN &gr_os2pm_device_chain + +#endif /* GR_INIT_BUILD */ + +#endif /* GROS2PM_H */ diff --git a/demos/config/os2/rules.mk b/demos/config/os2/rules.mk new file mode 100644 index 000000000..537034d2d --- /dev/null +++ b/demos/config/os2/rules.mk @@ -0,0 +1,32 @@ +#************************************************************************** +#* +#* OS/2 specific rules file, used to compile the OS/2 graphics driver +#* to the graphics subsystem +#* +#************************************************************************** + +ifeq ($(PLATFORM),os2) + +GR_OS2 := config$(SEP)os2 +GR_OS2_ := $(GR_OS2)$(SEP) + +# the GRAPH_LINK is expanded each time an executable is linked with the +# graphics library. +# +GRAPH_LINK += $(GR_OS2_)gros2pm.def + +# Add the OS/2 driver object file to the graphics library "graph.a" +# +GRAPH_OBJS += $(OBJ_)gros2pm.$O + +DEVICES += OS2_PM +DEVICE_INCLUDES += $(GR_OS2) + +# the rule used to compile the graphics driver +# +$(OBJ_)gros2pm.$O: $(GR_OS2_)gros2pm.c $(GR_OS2_)gros2pm.h + $(CC) $(CFLAGS) $(GRAPH_INCLUDES:%=$I%) $I$(GR_OS2) $T$@ $< + +endif + + diff --git a/demos/config/x11/grx11.c b/demos/config/x11/grx11.c new file mode 100644 index 000000000..99d853868 --- /dev/null +++ b/demos/config/x11/grx11.c @@ -0,0 +1,936 @@ +#include "grx11.h" + + +#ifdef TEST +#include "grfont.h" +#endif + +#include +#include +#include +#include +#include +#include +#include + + static void Panic( const char* message ) + { + fprintf( stderr, "%s", message ); + exit(1); + } + + typedef struct Translator + { + KeySym xkey; + grKey grkey; + + } Translator; + + static + Translator key_translators[] = + { + { XK_BackSpace, grKeyBackSpace }, + { XK_Tab, grKeyTab }, + { XK_Return, grKeyReturn }, + { XK_Escape, grKeyEsc }, + { XK_Home, grKeyHome }, + { XK_Left, grKeyLeft }, + { XK_Up, grKeyUp }, + { XK_Right, grKeyRight }, + { XK_Down, grKeyDown }, + { XK_Page_Up, grKeyPageUp }, + { XK_Page_Down, grKeyPageDown }, + { XK_End, grKeyEnd }, + { XK_Begin, grKeyHome }, + { XK_F1, grKeyF1 }, + { XK_F2, grKeyF2 }, + { XK_F3, grKeyF3 }, + { XK_F4, grKeyF4 }, + { XK_F5, grKeyF5 }, + { XK_F6, grKeyF6 }, + { XK_F7, grKeyF7 }, + { XK_F8, grKeyF8 }, + { XK_F9, grKeyF9 }, + { XK_F10, grKeyF10 }, + { XK_F11, grKeyF11 }, + { XK_F12, grKeyF12 } + }; + + +#ifdef TEST + +#define grAlloc malloc + +#endif + + + static Display* display; + static char* displayname = ""; + + static Cursor idle; + static Cursor busy; + +#define MAX_PIXEL_MODES 32 + + typedef XPixmapFormatValues XDepth; + + static int num_pixel_modes = 0; + static grPixelMode pixel_modes[ MAX_PIXEL_MODES ]; + static XDepth pixel_depth[ MAX_PIXEL_MODES ]; + + typedef struct grXSurface_ + { + grSurface root; + grBitmap image; + + Window win; + Visual* visual; + Colormap colormap; + int depth; + Bool gray; + + GC gc; + + XColor color[256]; /* gray levels palette for 8-bit modes */ + XImage* ximage; + + int win_org_x; + int win_org_y; + int win_width; + int win_height; + + int image_width; + int image_height; + + } grXSurface; + + + + + /* close a given window */ + static + void done_surface( grXSurface* surface ) + { + XUnmapWindow( display, surface->win ); + } + + + + /* close the device, i.e. the display connection */ + static + void done_device( void ) + { + XCloseDisplay( display ); + } + + + + static + void add_pixel_mode( grPixelMode pixel_mode, + XDepth* depth ) + { + if ( num_pixel_modes >= MAX_PIXEL_MODES ) + Panic( "X11.Too many pixel modes\n" ); + + pixel_modes[ num_pixel_modes ] = pixel_mode; + pixel_depth[ num_pixel_modes ] = *depth; + + num_pixel_modes++; + } + + + + static + int init_device( void ) + { + XDepth dummy; + + XrmInitialize(); + + display = XOpenDisplay( displayname ); + if (!display) + { + return -1; + /* Panic( "Gr:error: cannot open X11 display\n" ); */ + } + + idle = XCreateFontCursor( display, XC_left_ptr ); + busy = XCreateFontCursor( display, XC_watch ); + + num_pixel_modes = 0; + + /* always enable the 8-bit gray levels pixel mode */ + /* even if its display is emulated through a constrained palette */ + /* or another color mode */ + dummy.depth = 8; + dummy.bits_per_pixel = 8; + dummy.scanline_pad = 8; + add_pixel_mode( gr_pixel_mode_gray, &dummy ); + + { + int count; + XDepth* format; + XDepth* formats; + XVisualInfo template; + + formats = XListPixmapFormats( display, &count ); + format = formats; + +#ifdef TEST + printf( "available pixmap formats\n" ); + printf( "depth pixbits scanpad\n" ); +#endif + + while ( count-- > 0 ) + { +#ifdef TEST + printf( " %3d %3d %3d\n", + format->depth, + format->bits_per_pixel, + format->scanline_pad ); +#endif + + if ( format->depth == 1 ) + /* usually, this should be the first format */ + add_pixel_mode( gr_pixel_mode_mono, format ); + + else if ( format->depth == 8 ) + add_pixel_mode( gr_pixel_mode_pal8, format ); + + /* note, the 32-bit modes return a depth of 24, and 32 bits per pixel */ + else if ( format->depth == 24 ) + { + if ( format->bits_per_pixel == 24 ) + add_pixel_mode( gr_pixel_mode_rgb24, format ); + + else if ( format->bits_per_pixel == 32 ) + add_pixel_mode( gr_pixel_mode_rgb32, format ); + } + + else if ( format->depth == 16 ) + { + int count2; + XVisualInfo* visuals; + XVisualInfo* visual; + + template.depth = format->depth; + visuals = XGetVisualInfo( display, + VisualDepthMask, + &template, + &count2 ); + visual = visuals; + + while ( count2-- > 0 ) + { +#ifdef TEST + const char* string = "unknown"; + + switch (visual->class) + { + case TrueColor: string = "TrueColor"; break; + case DirectColor: string = "DirectColor"; break; + case PseudoColor: string = "PseudoColor"; break; + case StaticGray : string = "StaticGray"; break; + case StaticColor: string = "StaticColor"; break; + case GrayScale: string = "GrayScale"; break; + } + + printf( "> RGB %02x:%02x:%02x, colors %3d, bits %2d %s\n", + visual->red_mask, + visual->green_mask, + visual->blue_mask, + visual->colormap_size, + visual->bits_per_rgb, + string ); +#endif + if ( visual->red_mask == 0xf800 && + visual->green_mask == 0x07e0 && + visual->blue_mask == 0x001f ) + add_pixel_mode( gr_pixel_mode_rgb565, format ); + + else if ( visual->red_mask == 0x7c00 && + visual->green_mask == 0x03e0 && + visual->blue_mask == 0x001f ) + add_pixel_mode( gr_pixel_mode_rgb555, format ); + + /* other 16-bit modes are ignored */ + visual++; + } + + XFree( visuals ); + } + + format++; + } + + XFree( formats ); + } + + gr_x11_device.num_pixel_modes = num_pixel_modes; + gr_x11_device.pixel_modes = pixel_modes; + + return 0; + } + + + + + + + + + + + + + static + void convert_gray_to_pal8( grXSurface* surface, + int x, + int y, + int w, + int h ) + { + grBitmap* target = &surface->image; + grBitmap* source = &surface->root.bitmap; + byte* write = (byte*)target->buffer + y*target->pitch + x; + byte* read = (byte*)source->buffer + y*source->pitch + x; + XColor* palette = surface->color; + + while (h > 0) + { + byte* _write = write; + byte* _read = read; + byte* limit = _write + w; + + for ( ; _write < limit; _write++, _read++ ) + *_write = (byte) palette[ *_read ].pixel; + + write += target->pitch; + read += source->pitch; + h--; + } + } + + + static + void convert_gray_to_16( grXSurface* surface, + int x, + int y, + int w, + int h ) + { + grBitmap* target = &surface->image; + grBitmap* source = &surface->root.bitmap; + byte* write = (byte*)target->buffer + y*target->pitch + 2*x; + byte* read = (byte*)source->buffer + y*source->pitch + x; + XColor* palette = surface->color; + + while (h > 0) + { + byte* _write = write; + byte* _read = read; + byte* limit = _write + 2*w; + + for ( ; _write < limit; _write += 2, _read++ ) + *(short*)_write = (short)palette[ *_read ].pixel; + + write += target->pitch; + read += source->pitch; + h--; + } + } + + + static + void convert_gray_to_24( grXSurface* surface, + int x, + int y, + int w, + int h ) + { + grBitmap* target = &surface->image; + grBitmap* source = &surface->root.bitmap; + byte* write = (byte*)target->buffer + y*target->pitch + 3*x; + byte* read = (byte*)source->buffer + y*source->pitch + x; + + while (h > 0) + { + byte* _write = write; + byte* _read = read; + byte* limit = _write + 3*w; + + for ( ; _write < limit; _write += 3, _read++ ) + { + byte color = *_read; + + _write[0] = + _write[1] = + _write[2] = color; + } + + write += target->pitch; + read += source->pitch; + h--; + } + } + + + static + void convert_gray_to_32( grXSurface* surface, + int x, + int y, + int w, + int h ) + { + grBitmap* target = &surface->image; + grBitmap* source = &surface->root.bitmap; + byte* write = (byte*)target->buffer + y*target->pitch + 4*x; + byte* read = (byte*)source->buffer + y*source->pitch + x; + + while (h > 0) + { + byte* _write = write; + byte* _read = read; + byte* limit = _write + 4*w; + + for ( ; _write < limit; _write += 4, _read++ ) + { + byte color = *_read; + + _write[0] = + _write[1] = + _write[2] = + _write[3] = color; + } + + write += target->pitch; + read += source->pitch; + h--; + } + } + + + static + void convert_rectangle( grXSurface* surface, + int x, + int y, + int w, + int h ) + { + int z; + + /* first of all, clip to the surface's area */ + if ( x >= surface->image.width || + x+w <= 0 || + y >= surface->image.rows || + y+h <= 0 ) + return; + + if ( x < 0 ) + { + w += x; + x = 0; + } + + z = (x + w) - surface->image.width; + if (z > 0) + w -= z; + + z = (y + h) - surface->image.rows; + if (z > 0) + h -= z; + + /* convert the rectangle to the target depth for gray surfaces */ + if (surface->gray) + { + switch (surface->depth) + { + case 8 : convert_gray_to_pal8( surface, x, y, w, h ); break; + case 16: convert_gray_to_16 ( surface, x, y, w, h ); break; + case 24: convert_gray_to_24 ( surface, x, y, w, h ); break; + case 32: convert_gray_to_32 ( surface, x, y, w, h ); break; + } + } + } + + + static + void refresh_rectangle( grXSurface* surface, + int x, + int y, + int w, + int h ) + { + if (surface->gray) + convert_rectangle( surface, x, y, w, h ); + + XPutImage( display, + surface->win, + surface->gc, + surface->ximage, + x, y, x, y, w, h ); + } + + + static + void set_title( grXSurface* surface, + const char* title ) + { + XStoreName( display, surface->win, title ); + } + + + + static + grKey KeySymTogrKey( KeySym key ) + { + grKey k; + int count = sizeof(key_translators)/sizeof(key_translators[0]); + Translator* trans = key_translators; + Translator* limit = trans + count; + + k = grKeyNone; + + while ( trans < limit ) + { + if ( trans->xkey == key ) + { + k = trans->grkey; + break; + } + trans++; + } + + return k; + } + + + + static + void listen_event( grXSurface* surface, + int event_mask, + grEvent* grevent ) + { + static char key_buffer[10]; + static int key_cursor = 0; + static int key_number = 0; + static XEvent x_event; + KeySym key; + + int bool_exit; + grKey grkey; + + XComposeStatus compose; + + /* XXXX : For now, ignore the event mask, and only exit when */ + /* a key is pressed.. */ + (void)event_mask; + + bool_exit = key_cursor < key_number; + + XDefineCursor( display, surface->win, idle ); + + while ( !bool_exit ) + { + XNextEvent( display, &x_event ); + + switch ( x_event.type ) + { + case KeyPress: + key_number = XLookupString( &x_event.xkey, + key_buffer, + sizeof ( key_buffer ), + &key, + &compose ); + key_cursor = 0; + + if ( key_number == 0 || + key > 512 ) + { + /* this may be a special key like F1, F2, etc.. */ + grkey = KeySymTogrKey(key); + if (grkey != grKeyNone) + goto Set_Key; + } + else + bool_exit = 1; + break; + + case MappingNotify: + XRefreshKeyboardMapping( &x_event.xmapping ); + break; + + case Expose: + refresh_rectangle( surface, + x_event.xexpose.x, + x_event.xexpose.y, + x_event.xexpose.width, + x_event.xexpose.height ); + break; + + /* You should add more cases to handle mouse events, etc. */ + } + } + + XDefineCursor( display, surface->win, busy ); + XFlush ( display ); + + /* Now, translate the keypress to a grKey */ + /* If this wasn't part of the simple translated keys, simply get the charcode */ + /* from the character buffer */ + grkey = grKEY(key_buffer[key_cursor++]); + + Set_Key: + grevent->type = gr_key_down; + grevent->key = grkey; + } + + + + + grXSurface* init_surface( grXSurface* surface, + grBitmap* bitmap ) + { + int screen; + grBitmap* image; + char grays; + XDepth* format; + int image_depth; + + screen = DefaultScreen( display ); + + surface->colormap = DefaultColormap( display, screen ); + surface->depth = DefaultDepth( display, screen ); + surface->visual = DefaultVisual( display, screen ); + + image = &surface->image; + + /* force the surface image depth to 1 if necessary */ + /* as this should be supported by all windows */ + image_depth = surface->depth; + if (bitmap->mode == gr_pixel_mode_mono) + image_depth = 1; + + grays = ( bitmap->mode == gr_pixel_mode_gray && + bitmap->grays >= 2 ); + + surface->gray = grays; + + /* copy dimensions */ + image->width = bitmap->width; + image->rows = bitmap->rows; + image->mode = bitmap->mode; + image->pitch = 0; + image->grays = 0; + image->buffer = 0; + + /* find the supported format corresponding to the request */ + format = 0; + + if (grays) + { + /* choose the default depth in case of grays rendering */ + int i; + for ( i = 0; i < num_pixel_modes; i++ ) + if ( image_depth == pixel_depth[i].depth ) + { + format = pixel_depth + i; + break; + } + } + else + { + /* otherwise, select the format depending on the pixel mode */ + int i; + + format = 0; + for ( i = 0; i < num_pixel_modes; i++ ) + if ( pixel_modes[i] == bitmap->mode ) + { + format = pixel_depth + i; + break; + } + } + + if (!format) + { + grError = gr_err_bad_argument; + return 0; + } + + + /* correct surface.depth. This is required because in the case */ + /* of 32-bits pixels, the value of "format.depth" is 24 under X11 */ + if ( format->depth == 24 && + format->bits_per_pixel == 32 ) + image_depth = 32; + + /* allocate surface image */ + { + int bits, over; + + bits = image->width * format->bits_per_pixel; + over = bits % format->scanline_pad; + + if (over) + bits += format->scanline_pad - over; + + if (!grays) + { + image->width = bits; + bitmap->width = bits; + } + image->pitch = bits >> 3; + } + + image->buffer = grAlloc( image->pitch * image->rows ); + if (!image->buffer) return 0; + + /* now, allocate a gray pal8 pixmap, only when we asked */ + /* for an 8-bit pixmap */ + if ( grays ) + { + /* pad pitch to 32 bits */ + bitmap->pitch = (bitmap->width + 3) & -4; + bitmap->buffer = grAlloc( bitmap->pitch * bitmap->rows ); + if (!bitmap->buffer) + Panic( "grX11: could not allocate surface bitmap!\n" ); + } + else /* otherwise */ + { + *bitmap = *image; + } + + surface->root.bitmap = *bitmap; + + /* Now create the surface X11 image */ + surface->ximage = XCreateImage( display, + surface->visual, + format->depth, + format->depth == 1 ? XYBitmap : ZPixmap, + 0, + (char*)image->buffer, + image->width, + image->rows, + 8, + 0 ); + if ( !surface->ximage ) + Panic( "grX11: cannot create surface X11 image\n" ); + + + /* allocate gray levels in the case of gray surface */ + if ( grays ) + { + XColor* color = surface->color; + int i; + + for ( i = 0; i < bitmap->grays; i++, color++ ) + { + color->red = + color->green = + color->blue = 65535 - ( i * 65535 ) / bitmap->grays; + + if ( !XAllocColor( display, surface->colormap, color ) ) + Panic( "ERROR: cannot allocate Color\n" ); + } + } + else if ( image_depth == 1 ) + { + surface->ximage->byte_order = MSBFirst; + surface->ximage->bitmap_bit_order = MSBFirst; + } + + { + XTextProperty xtp; + XSizeHints xsh; + XSetWindowAttributes xswa; + + xswa.border_pixel = BlackPixel( display, screen ); + xswa.background_pixel = WhitePixel( display, screen ); + xswa.cursor = busy; + + xswa.event_mask = KeyPressMask | ExposureMask; + + surface->win = XCreateWindow( display, + RootWindow( display, screen ), + 0, + 0, + image->width, + image->rows, + 10, + surface->depth, + InputOutput, + surface->visual, + CWBackPixel | CWBorderPixel | + CWEventMask | CWCursor, + &xswa ); + + XMapWindow( display, surface->win ); + + surface->gc = XCreateGC( display, RootWindow( display, screen ), 0L, NULL ); + XSetForeground( display, surface->gc, xswa.border_pixel ); + XSetBackground( display, surface->gc, xswa.background_pixel ); + + + /* make window manager happy :-) */ + xtp.value = (unsigned char*)"FreeType"; + xtp.encoding = 31; + xtp.format = 8; + xtp.nitems = strlen( (char*)xtp.value ); + + xsh.x = 0; + xsh.y = 0; + + xsh.width = image->width; + xsh.height = image->rows; + xsh.flags = (PPosition | PSize); + xsh.flags = 0; + + XSetWMProperties( display, surface->win, &xtp, &xtp, NULL, 0, &xsh, NULL, NULL ); + } + + surface->root.done = (grDoneSurfaceFunc) done_surface; + surface->root.refresh_rect = (grRefreshRectFunc) refresh_rectangle; + surface->root.set_title = (grSetTitleFunc) set_title; + surface->root.listen_event = (grListenEventFunc) listen_event; + + convert_rectangle( surface, 0, 0, bitmap->width, bitmap->rows ); + return surface; + } + + + + + grDevice gr_x11_device = + { + sizeof( grXSurface ), + "x11", + + init_device, + done_device, + + (grDeviceInitSurfaceFunc) init_surface, + + 0, + 0 + + }; + +#ifdef TEST + +typedef struct grKeyName +{ + grKey key; + const char* name; + +} grKeyName; + + +static +const grKeyName key_names[] = +{ + { grKeyF1, "F1" }, + { grKeyF2, "F2" }, + { grKeyF3, "F3" }, + { grKeyF4, "F4" }, + { grKeyF5, "F5" }, + { grKeyF6, "F6" }, + { grKeyF7, "F7" }, + { grKeyF8, "F8" }, + { grKeyF9, "F9" }, + { grKeyF10, "F10" }, + { grKeyF11, "F11" }, + { grKeyF12, "F12" }, + { grKeyEsc, "Esc" }, + { grKeyHome, "Home" }, + { grKeyEnd, "End" }, + + { grKeyPageUp, "Page_Up" }, + { grKeyPageDown, "Page_Down" }, + { grKeyLeft, "Left" }, + { grKeyRight, "Right" }, + { grKeyUp, "Up" }, + { grKeyDown, "Down" }, + { grKeyBackSpace, "BackSpace" }, + { grKeyReturn, "Return" } +}; + +int main( void ) +{ + grSurface* surface; + int n; + + grInit(); + surface = grNewScreenSurface( 0, gr_pixel_mode_gray, 320, 400, 128 ); + if (!surface) + Panic("Could not create window\n" ); + else + { + grColor color; + grEvent event; + const char* string; + int x; + + grSetSurfaceRefresh( surface, 1 ); + grSetTitle(surface,"X11 driver demonstration" ); + + for ( x = -10; x < 10; x++ ) + { + for ( n = 0; n < 128; n++ ) + { + color.value = (n*3) & 127; + grWriteCellChar( surface, + x + ((n % 60) << 3), + 80 + (x+10)*8*3 + ((n/60) << 3), n, color ); + } + + } + color.value = 64; + grWriteCellString( surface, 0, 0, "just an example", color ); + + do + { + listen_event((grXSurface*)surface, 0, &event); + + /* return if ESC was pressed */ + if ( event.key == grKeyEsc ) + return 0; + + /* otherwise, display key string */ + color.value = (color.value + 8) & 127; + { + int count = sizeof(key_names)/sizeof(key_names[0]); + grKeyName* name = key_names; + grKeyName* limit = name + count; + const char* kname = 0; + char kname_temp[16]; + + while (name < limit) + { + if ( name->key == event.key ) + { + kname = name->name; + break; + } + name++; + } + + if (!kname) + { + sprintf( kname_temp, "char '%c'", (char)event.key ); + kname = kname_temp; + } + + grWriteCellString( surface, 30, 30, kname, color ); + grRefreshSurface(surface); + paint_rectangle( surface, 0, 0, surface->bitmap.width, surface->bitmap.rows ); + } + } while (1); + } + + return 0; + + +} +#endif /* TEST */ + diff --git a/demos/config/x11/grx11.h b/demos/config/x11/grx11.h new file mode 100644 index 000000000..cd77112c0 --- /dev/null +++ b/demos/config/x11/grx11.h @@ -0,0 +1,24 @@ +#ifndef GRX11_H +#define GRX11_H + +#include "grobjs.h" +#include "grdevice.h" + + extern + grDevice gr_x11_device; + +#ifdef GR_INIT_BUILD + static + grDeviceChain gr_x11_device_chain = + { + "x11", + &gr_x11_device, + GR_INIT_DEVICE_CHAIN + }; + +#undef GR_INIT_DEVICE_CHAIN +#define GR_INIT_DEVICE_CHAIN &gr_x11_device_chain + +#endif /* GR_INIT_BUILD */ + +#endif /* GRX11_H */ diff --git a/demos/config/x11/rules.mk b/demos/config/x11/rules.mk new file mode 100644 index 000000000..ee616e9f6 --- /dev/null +++ b/demos/config/x11/rules.mk @@ -0,0 +1,69 @@ +#************************************************************************** +#* +#* X11-specific rules files, used to compile the X11 graphics driver +#* when supported by the current platform +#* +#************************************************************************** + +######################################################################### +# +# Try to detect an X11 setup. +# +# We simply try to detect a `X11R6/bin', `X11R5/bin' or `X11/bin' in +# the current path. +# +ifneq ($(findstring X11R6$(SEP)bin,$(PATH)),) +xversion := X11R6 +endif + +ifneq ($(findstring X11R5$(SEP)bin,$(PATH)),) +xversion := X11R5 +endif + +ifneq ($(findstring X11$(SEP)bin,$(PATH)),) +xversion := X11 +endif + +ifdef xversion +X11_PATH := $(subst ;, ,$(PATH)) $(subst :, ,$(PATH)) +X11_PATH := $(filter %$(xversion)$(SEP)bin,$(X11_PATH)) +X11_PATH := $(X11_PATH:%$(SEP)bin=%) +endif + +########################################################################## +# +# Update some variables to compile the X11 graphics module. Note that +# X11 is available on Unix, or on OS/2. However, it only compiles with +# gcc on the latter platform, which is why it is safe to use the flags +# `-L' and `-l' +# +ifneq ($(X11_PATH),) + +X11_INCLUDE := $(X11_PATH)$(SEP)include +X11_LIB := $(X11_PATH)$(SEP)lib + +# the GRAPH_LINK variable is expanded each time an executable is linked against +# the graphics library.. +# +GRAPH_LINK += -L$(X11_LIB) -lX11 + +# add the X11 driver object file to the graphics library +# +GRAPH_OBJS += $(OBJ_)grx11.$O + +GR_X11 := config$(SEP)x11 +GR_X11_ := $(GR_X11)$(SEP) + +DEVICES += X11 +DEVICE_INCLUDES += $(GR_X11) + +# the rule used to compile the X11 driver +# +$(OBJ_)grx11.$O: $(GR_X11_)grx11.c $(GR_X11_)grx11.h + $(CC) $(CFLAGS) $(GRAPH_INCLUDES:%=$I%) $I$(GR_X11) \ + $(X11_INCLUDE:%=$I%) $T$@ $< +endif + + + + diff --git a/demos/graph/gpm_os2.def b/demos/graph/gpm_os2.def new file mode 100644 index 000000000..4a77c632c --- /dev/null +++ b/demos/graph/gpm_os2.def @@ -0,0 +1,5 @@ +NAME WINDOWCOMPAT + +DESCRIPTION 'FreeType Graphics' +HEAPSIZE 8192 +STACKSIZE 40888 diff --git a/demos/graph/graph.h b/demos/graph/graph.h new file mode 100644 index 000000000..e5f3b32e8 --- /dev/null +++ b/demos/graph/graph.h @@ -0,0 +1,632 @@ +/*************************************************************************** + * + * graph.h + * + * Graphics Subsystem interface + * + * Copyright 1999 - The FreeType Development Team - www.freetype.org + * + * + * + * + ***************************************************************************/ + +#ifndef GRAPH_H +#define GRAPH_H + +#include "grevents.h" + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /******** ********/ + /******** GENERAL DEFINITIONS AND BLITTING ROUTINES ********/ + /******** ********/ + /******** ********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /* define the global error variable */ + extern int grError; + + /* initialisation */ + extern int grInit( void ); + + /* finalisation */ + extern void grDone( void ); + + + /* pixel mode constants */ + typedef enum grPixelMode + { + gr_pixel_mode_none = 0, + gr_pixel_mode_mono, /* monochrome bitmaps */ + gr_pixel_mode_pal4, /* 4-bit paletted - 16 colors */ + gr_pixel_mode_pal8, /* 8-bit paletted - 256 colors */ + gr_pixel_mode_gray, /* 8-bit gray levels */ + gr_pixel_mode_rgb555, /* 15-bits mode - 32768 colors */ + gr_pixel_mode_rgb565, /* 16-bits mode - 65536 colors */ + gr_pixel_mode_rgb24, /* 24-bits mode - 16 million colors */ + gr_pixel_mode_rgb32, /* 32-bits mode - 16 million colors */ + + gr_pixel_mode_max /* don't remove */ + + } grPixelMode; + + + /* forward declaration of the surface class */ + typedef struct grSurface_ grSurface; + + + /********************************************************************* + * + * + * grBitmap + * + * + * a simple bitmap descriptor + * + * + * rows :: height in pixels + * width :: width in pixels + * pitch :: + or - the number of bytes per row + * mode :: pixel mode of bitmap buffer + * grays :: number of grays in palette for PAL8 mode. 0 otherwise + * buffer :: pointer to pixel buffer + * + * + * the 'pitch' is positive for downward flows, and negative otherwise + * Its absolute value is always the number of bytes taken by each + * bitmap row. + * + * All drawing operations will be performed within the first + * "width" pixels of each row (clipping is always performed). + * + ********************************************************************/ + + typedef struct grBitmap_ + { + int rows; + int width; + int pitch; + grPixelMode mode; + int grays; + char* buffer; + + } grBitmap; + + + + typedef long grPos; + typedef char grBool; + + typedef struct grVector_ + { + grPos x; + grPos y; + + } grVector; + + + typedef union grColor_ + { + long value; + unsigned char chroma[4]; + + } grColor; + + + + /********************************************************************** + * + * + * grNewBitmap + * + * + * creates a new bitmap + * + * + * pixel_mode :: the target surface's pixel_mode + * num_grays :: number of grays levels for PAL8 pixel mode + * width :: width in pixels + * height :: height in pixels + * + * + * bit :: descriptor of the new bitmap + * + * + * Error code. 0 means success. + * + * + * This function really allocates a pixel buffer, zero it, then + * returns a descriptor for it. + * + * Call grDoneBitmap when you're done with it.. + * + **********************************************************************/ + + extern int grNewBitmap( grPixelMode pixel_mode, + int num_grays, + int width, + int height, + grBitmap *bit ); + + + /********************************************************************** + * + * + * grBlitGlyphToBitmap + * + * + * writes a given glyph bitmap to a target surface. + * + * + * target :: handle to target bitmap + * glyph :: handle to source glyph bitmap + * x :: position of left-most pixel of glyph image in target surface + * y :: position of top-most pixel of glyph image in target surface + * color :: color to be used to draw a monochrome glyph + * + * + * Error code. 0 means success + * + * + * There are only two supported source pixel modes : monochrome + * and gray. The 8-bit images can have any number of grays between + * 2 and 128, and conversions to the target surface is handled + * _automatically_. + * + * Note however that you should avoid blitting a gray glyph to a gray + * bitmap with fewer levels of grays, as this would much probably + * give unpleasant results.. + * + * This function performs clipping + * + **********************************************************************/ + + extern int grBlitGlyphToBitmap( grBitmap* target, + grBitmap* glyph, + grPos x, + grPos y, + grColor color ); + + + /********************************************************************** + * + * + * grFillRectangle + * + * + * this function is used to fill a given rectangle on a surface + * + * + * surface :: handle to target surface + * x :: x coordinate of the top-left corner of the rectangle + * y :: y coordinate of the top-left corner of the rectangle + * width :: rectangle width in pixels + * height :: rectangle height in pixels + * color :: fill color + * + **********************************************************************/ + + extern void grFillRectangle( grBitmap* surface, + grPos x, + grPos y, + grPos width, + grPos height, + grColor color ); + + + + /********************************************************************** + * + * + * grWriteCellChar + * + * + * The graphics sub-system contains an internal Latin1 8x8 font + * which can be used to display simple strings of text without + * using FreeType. + * + * This function writes a single 8x8 character on the target bitmap. + * + * + * target :: handle to target surface + * x :: x pixel position of character cell's top left corner + * y :: y pixel position of character cell's top left corner + * charcode :: Latin-1 character code + * color :: color to be used to draw the character + * + **********************************************************************/ + + extern + void grWriteCellChar( grBitmap* target, + int x, + int y, + int charcode, + grColor color ); + + + /********************************************************************** + * + * + * grWriteCellString + * + * + * The graphics sub-system contains an internal Latin1 8x8 font + * which can be used to display simple strings of text without + * using FreeType. + * + * This function writes a string with the internal font + * + * + * target :: handle to target bitmap + * x :: x pixel position of string's top left corner + * y :: y pixel position of string's top left corner + * string :: Latin-1 text string + * color :: color to be used to draw the character + * + **********************************************************************/ + + extern + void grWriteCellString( grBitmap* target, + int x, + int y, + const char* string, + grColor color ); + + /********************************************************************** + * + * + * grDoneBitmap + * + * + * destroys a bitmap + * + * + * bitmap :: handle to bitmap descriptor + * + * + * This function does NOT release the bitmap descriptor, only + * the pixel buffer. + * + **********************************************************************/ + + extern void grDoneBitmap( grBitmap* bit ); + + + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /******** ********/ + /******** DEVICE-SPECIFIC DEFINITIONS AND ROUTINES ********/ + /******** ********/ + /******** ********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /* forward declaration - the definition of grDevice is not visible */ + /* to clients.. */ + typedef struct grDevice_ grDevice; + + + /********************************************************************** + * + * + * grDeviceChain + * + * + * a simple structure used to implement a linked list of + * graphics device descriptors. The list is called a + * "device chain" + * + * + * name :: ASCII name of the device, e.g. "x11", "os2pm", etc.. + * device :: handle to the device descriptor. + * next :: next element in chain + * + * + * the 'device' field is a blind pointer; it is thus unusable by + * client applications.. + * + **********************************************************************/ + + typedef struct grDeviceChain_ grDeviceChain; + + struct grDeviceChain_ + { + const char* name; + grDevice* device; + grDeviceChain* next; + }; + + + /********************************************************************** + * + * + * grInitDevices + * + * + * This function is in charge of initialising all system-specific + * devices. A device is responsible for creating and managing one + * or more "surfaces". A surface is either a window or a screen, + * depending on the system. + * + * + * a pointer to the first element of a device chain. The chain can + * be parsed to find the available devices on the current system + * + * + * If a device cannot be initialised correctly, it is not part of + * the device chain returned by this function. For example, if an + * X11 device was compiled in the library, it will be part of + * the returned device chain only if a connection to the display + * could be establisged + * + * If no driver could be initialised, this function returns NULL. + * + **********************************************************************/ + + extern + grDeviceChain* grInitDevices( void ); + + + + /********************************************************************** + * + * + * grGetDeviceModes + * + * + * queries the available pixel modes for a device. + * + * + * device_name :: name of device to be used. 0 for the default + * device. For a list of available devices, see + * grInitDevices. + * + * + * num_modes :: number of available modes. 0 in case of error, + * which really is an invalid device name. + * + * pixel_modes :: array of available pixel modes for this device + * this table is internal to the device and should + * not be freed by client applications. + * + * + * error code. 0 means success. invalid device name otherwise + * + * + * All drivers are _required_ to support at least the following + * pixel formats : + * + * - gr_pixel_mode_mono : i.e. monochrome bitmaps + * - gr_pixel_mode_gray : with any number of gray levels between + * 2 and 256. + * + * the pixel modes do not provide the number of grays in the case + * of "gray" devices. You should try to create a surface with the + * maximal number (256, that is) and see the value returned in + * the bitmap descriptor. + * + **********************************************************************/ + + extern void grGetDeviceModes( const char* device_name, + int *num_modes, + grPixelMode* *pixel_modes ); + + + + /********************************************************************** + * + * + * grNewSurface + * + * + * creates a new device-specific surface. A surface is either + * a window or a screen, depending on the device. + * + * + * device :: name of the device to use. A value of NULL means + * the default device (which depends on the system). + * for a list of available devices, see grInitDevices. + * + * + * bitmap :: handle to a bitmap descriptor containing the + * requested pixel mode, number of grays and dimensions + * for the surface. the bitmap's 'pitch' and 'buffer' + * fields are ignored on input. + * + * On output, the bitmap describes the surface's image + * completely. It is possible to write directly in it + * with grBlitGlyphToBitmap, even though the use of + * grBlitGlyphToSurface is recommended. + * + * + * handle to the corresponding surface object. 0 in case of error + * + * + * All drivers are _required_ to support at least the following + * pixel formats : + * + * - gr_pixel_mode_mono : i.e. monochrome bitmaps + * - gr_pixel_mode_gray : with any number of gray levels between + * 2 and 256. + * + * This function might change the bitmap descriptor's fields. For + * example, when displaying a full-screen surface, the bitmap's + * dimensions will be set to those of the screen (e.g. 640x480 + * or 800x600); also, the bitmap's 'buffer' field might point to + * the Video Ram depending on the mode requested.. + * + * The surface contains a copy of the returned bitmap descriptor, + * you can thus discard the 'bitmap' parameter after the call. + * + **********************************************************************/ + + extern grSurface* grNewSurface( const char* device, + grBitmap* bitmap ); + + + + /********************************************************************** + * + * + * grRefreshRectangle + * + * + * this function is used to indicate that a given surface rectangle + * was modified and thus needs re-painting. It really is useful for + * windowed or gray surfaces. + * + * + * surface :: handle to target surface + * x :: x coordinate of the top-left corner of the rectangle + * y :: y coordinate of the top-left corner of the rectangle + * width :: rectangle width in pixels + * height :: rectangle height in pixels + * + **********************************************************************/ + + extern void grRefreshRectangle( grSurface* surface, + grPos x, + grPos y, + grPos width, + grPos height ); + + + /********************************************************************** + * + * + * grRefreshSurface + * + * + * a variation of grRefreshRectangle which repaints the whole surface + * to the screen. + * + * + * surface :: handle to target surface + * + **********************************************************************/ + + extern void grRefreshSurface( grSurface* surface ); + + + + /********************************************************************** + * + * + * grWriteSurfaceChar + * + * + * This function is equivalent to calling grWriteCellChar on the + * surface's bitmap, then invoking grRefreshRectangle. + * + * The graphics sub-system contains an internal Latin1 8x8 font + * which can be used to display simple strings of text without + * using FreeType. + * + * This function writes a single 8x8 character on the target bitmap. + * + * + * target :: handle to target surface + * x :: x pixel position of character cell's top left corner + * y :: y pixel position of character cell's top left corner + * charcode :: Latin-1 character code + * color :: color to be used to draw the character + * + **********************************************************************/ + + extern + void grWriteSurfaceChar( grSurface* target, + int x, + int y, + int charcode, + grColor color ); + + + /********************************************************************** + * + * + * grWriteSurfaceString + * + * + * This function is equivalent to calling grWriteCellString on the + * surface's bitmap, then invoking grRefreshRectangle. + * + * The graphics sub-system contains an internal Latin1 8x8 font + * which can be used to display simple strings of text without + * using FreeType. + * + * This function writes a string with the internal font + * + * + * target :: handle to target bitmap + * x :: x pixel position of string's top left corner + * y :: y pixel position of string's top left corner + * string :: Latin-1 text string + * color :: color to be used to draw the character + * + **********************************************************************/ + + extern + void grWriteSurfaceString( grSurface* target, + int x, + int y, + const char* string, + grColor color ); + + + /********************************************************************** + * + * + * grSetTitle + * + * + * set the window title of a given windowed surface. + * + * + * surface :: handle to target surface + * title_string :: the new title + * + **********************************************************************/ + + extern void grSetTitle( grSurface* surface, + const char* title_string ); + + + + + /********************************************************************** + * + * + * grListenSurface + * + * + * listen the events for a given surface + * + * + * surface :: handle to target surface + * event_mask :: the event mask (mode) + * + * + * event :: the returned event + * + * + * XXX : For now, only keypresses are supported. + * + **********************************************************************/ + + extern + int grListenSurface( grSurface* surface, + int event_mask, + grEvent *event ); + + +#endif /* GRAPH_H */ diff --git a/demos/graph/grblit.c b/demos/graph/grblit.c new file mode 100644 index 000000000..f0346e196 --- /dev/null +++ b/demos/graph/grblit.c @@ -0,0 +1,1268 @@ +/****************************************************************************/ +/* */ +/* The FreeType project -- a free and portable quality TrueType renderer. */ +/* */ +/* Copyright 1996-1999 by */ +/* D. Turner, R.Wilhelm, and W. Lemberg */ +/* */ +/* blitter.c: Support for blitting of bitmaps with various depth. */ +/* */ +/****************************************************************************/ + +#include "grblit.h" +#include "grobjs.h" + + static + int compute_clips( grBlitter* blit, + int x_offset, + int y_offset ) + { + int xmin, ymin, xmax, ymax, width, height, target_width; + + /* perform clipping and setup variables */ + width = blit->source.width; + height = blit->source.rows; + + switch ( blit->source.mode ) + { + case gr_pixel_mode_mono: + width = (width + 7) & -8; + break; + + case gr_pixel_mode_pal4: + width = (width + 1) & -2; + break; + + default: + ; + } + + xmin = x_offset; + ymin = y_offset; + xmax = xmin + width-1; + ymax = ymin + height-1; + + /* clip if necessary */ + if ( width == 0 || height == 0 || + xmax < 0 || xmin >= blit->target.width || + ymax < 0 || ymin >= blit->target.rows ) + return 1; + + /* set up clipping and cursors */ + blit->yread = 0; + if ( ymin < 0 ) + { + blit->yread -= ymin; + height += ymin; + blit->ywrite = 0; + } + else + blit->ywrite = ymin; + + if ( ymax >= blit->target.rows ) + height -= ymax - blit->target.rows + 1; + + blit->xread = 0; + if ( xmin < 0 ) + { + blit->xread -= xmin; + width += xmin; + blit->xwrite = 0; + } + else + blit->xwrite = xmin; + + target_width = blit->target.width; + + switch ( blit->target.mode ) + { + case gr_pixel_mode_mono: + target_width = (target_width + 7) & -8; + break; + case gr_pixel_mode_pal4: + target_width = (target_width + 1) & -2; + break; + + default: + ; + } + + blit->right_clip = xmax - target_width + 1; + if ( blit->right_clip > 0 ) + width -= blit->right_clip; + else + blit->right_clip = 0; + + blit->width = width; + blit->height = height; + + /* set read and write to the top-left corner of the read */ + /* and write areas before clipping. */ + + blit->read = (unsigned char*)blit->source.buffer; + blit->write = (unsigned char*)blit->target.buffer; + + blit->read_line = blit->source.pitch; + blit->write_line = blit->target.pitch; + + if ( blit->read_line < 0 ) + blit->read -= (blit->source.rows-1) * blit->read_line; + + if ( blit->write_line < 0 ) + blit->write -= (blit->target.rows-1) * blit->write_line; + + /* now go to the start line. Note that we do not move the */ + /* x position yet, as this is dependent on the pixel format */ + blit->read += blit->yread * blit->read_line; + blit->write += blit->ywrite * blit->write_line; + + return 0; + } + + +/**************************************************************************/ +/* */ +/* blit_mono_to_mono */ +/* */ +/**************************************************************************/ + + static + void blit_mono_to_mono( grBlitter* blit, + grColor color ) + { + int shift, left_clip, x, y; + byte* read; + byte* write; + + (void)color; /* unused argument */ + + left_clip = ( blit->xread > 0 ); + shift = ( blit->xwrite - blit->xread ) & 7; + + read = blit->read + (blit->xread >> 3); + write = blit->write + (blit->xwrite >> 3); + + if ( shift == 0 ) + { + y = blit->height; + do + { + byte* _read = read; + byte* _write = write; + + x = blit->width; + + do + { + *_write++ |= *_read++; + x -= 8; + } while ( x > 0 ); + + read += blit->read_line; + write += blit->write_line; + y--; + } while ( y > 0 ); + } + else + { + int first, last, count; + + + first = blit->xwrite >> 3; + last = (blit->xwrite + blit->width-1) >> 3; + + count = last - first; + + if ( blit->right_clip ) + count++; + + y = blit->height; + + do + { + unsigned char* _read = read; + unsigned char* _write = write; + unsigned char old; + int shift2 = (8-shift); + + if ( left_clip ) + old = (*_read++) << shift2; + else + old = 0; + + x = count; + while ( x > 0 ) + { + unsigned char val; + + val = *_read++; + *_write++ |= ( (val >> shift) | old ); + old = val << shift2; + x--; + } + + if ( !blit->right_clip ) + *_write |= old; + + read += blit->read_line; + write += blit->write_line; + y--; + + } while ( y > 0 ); + } + } + + +/**************************************************************************/ +/* */ +/* blit_mono_to_pal8 */ +/* */ +/**************************************************************************/ + + static + void blit_mono_to_pal8( grBlitter* blit, + grColor color ) + { + int x, y; + unsigned int left_mask; + unsigned char* read; + unsigned char* write; + + read = blit->read + (blit->xread >> 3); + write = blit->write + blit->xwrite; + + left_mask = 0x80 >> (blit->xread & 7); + + y = blit->height; + do + { + unsigned char* _read = read; + unsigned char* _write = write; + unsigned int mask = left_mask; + unsigned int val = *_read; + + + x = blit->width; + do + { + if ( mask == 0x80 ) + val = *_read++; + + if ( val & mask ) + *_write = (unsigned char)color.value; + + mask >>= 1; + if ( mask == 0 ) + mask = 0x80; + + _write++; + x--; + } while ( x > 0 ); + + read += blit->read_line; + write += blit->write_line; + y--; + } while ( y > 0 ); + } + + +/**************************************************************************/ +/* */ +/* blit_mono_to_pal4 */ +/* */ +/**************************************************************************/ + + static + void blit_mono_to_pal4( grBlitter* blit, + grColor color ) + { + int x, y, phase; + unsigned int left_mask; + unsigned char* read; + unsigned char* write; + unsigned char col; + + + col = color.value & 15; + read = blit->read + (blit->xread >> 3); + write = blit->write + (blit->xwrite >> 1); + + /* now begin blit */ + left_mask = 0x80 >> (blit->xread & 7); + phase = blit->xwrite & 1; + + y = blit->height; + do + { + unsigned char* _read = read; + unsigned char* _write = write; + unsigned int mask = left_mask; + int _phase = phase; + unsigned int val = *_read; + + x = blit->width; + do + { + if ( mask == 0x80 ) + val = *_read++; + + if ( val & mask ) + { + if ( _phase ) + *_write = (*_write & 0xF0) | col; + else + *_write = (*_write & 0x0F) | (col << 4); + } + + mask >>= 1; + if ( mask == 0 ) + mask = 0x80; + + _write += _phase; + _phase ^= 1; + x--; + } while ( x > 0 ); + + read += blit->read_line; + write += blit->write_line; + y--; + } while ( y > 0 ); + } + + +/**************************************************************************/ +/* */ +/* blit_mono_to_rgb16 */ +/* */ +/**************************************************************************/ + + static + void blit_mono_to_rgb16( grBlitter* blit, + grColor color ) + { + int x, y; + unsigned int left_mask; + unsigned char* read; + unsigned char* write; + + read = blit->read + (blit->xread >> 3); + write = blit->write + blit->xwrite*2; + + left_mask = 0x80 >> (blit->xread & 7); + + y = blit->height; + do + { + unsigned char* _read = read; + unsigned char* _write = write; + unsigned int mask = left_mask; + unsigned int val = *_read; + + x = blit->width; + do + { + if ( mask == 0x80 ) + val = *_read++; + + if ( val & mask ) + *(short*)_write = (short)color.value; + + mask >>= 1; + if ( mask == 0 ) + mask = 0x80; + + _write +=2; + x--; + } while ( x > 0 ); + + read += blit->read_line; + write += blit->write_line; + y--; + } while ( y > 0 ); + } + + +/**************************************************************************/ +/* */ +/* blit_mono_to_rgb24 */ +/* */ +/**************************************************************************/ + + static + void blit_mono_to_rgb24( grBlitter* blit, + grColor color ) + { + int x, y; + unsigned int left_mask; + unsigned char* read; + unsigned char* write; + + read = blit->read + (blit->xread >> 3); + write = blit->write + blit->xwrite*3; + + left_mask = 0x80 >> (blit->xread & 7); + + y = blit->height; + do + { + unsigned char* _read = read; + unsigned char* _write = write; + unsigned int mask = left_mask; + unsigned int val = *_read; + + x = blit->width; + do + { + if ( mask == 0x80 ) + val = *_read++; + + if ( val & mask ) + { + _write[0] = color.chroma[0]; + _write[1] = color.chroma[1]; + _write[2] = color.chroma[2]; + } + + mask >>= 1; + if ( mask == 0 ) + mask = 0x80; + + _write += 3; + x--; + } while ( x > 0 ); + + read += blit->read_line; + write += blit->write_line; + y--; + } while ( y > 0 ); + } + + +/**************************************************************************/ +/* */ +/* blit_mono_to_rgb32 */ +/* */ +/**************************************************************************/ + + static + void blit_mono_to_rgb32( grBlitter* blit, + grColor color ) + { + int x, y; + unsigned int left_mask; + unsigned char* read; + unsigned char* write; + + read = blit->read + (blit->xread >> 3); + write = blit->write + blit->xwrite*4; + + left_mask = 0x80 >> (blit->xread & 7); + + y = blit->height; + do + { + unsigned char* _read = read; + unsigned char* _write = write; + unsigned int mask = left_mask; + unsigned int val = *_read; + + x = blit->width; + do + { + if ( mask == 0x80 ) + val = *_read++; + + if ( val & mask ) + { + /* this could be greatly optimised as a *(long*)_write = color.value */ + /* but this wouldn't work on 64-bits systems... stupid C types! */ + _write[0] = color.chroma[0]; + _write[1] = color.chroma[1]; + _write[2] = color.chroma[2]; + _write[3] = color.chroma[3]; + } + + mask >>= 1; + if ( mask == 0 ) + mask = 0x80; + + _write += 4; + x--; + } while ( x > 0 ); + + read += blit->read_line; + write += blit->write_line; + y--; + } while ( y > 0 ); + } + + + + static + const grBlitterFunc gr_mono_blitters[gr_pixel_mode_max] = + { + 0, + blit_mono_to_mono, + blit_mono_to_pal4, + blit_mono_to_pal8, + blit_mono_to_pal8, + blit_mono_to_rgb16, + blit_mono_to_rgb16, + blit_mono_to_rgb24, + blit_mono_to_rgb32 + }; + + + /*******************************************************************/ + /* */ + /* Saturation tables */ + /* */ + /*******************************************************************/ + + typedef struct grSaturation_ + { + int count; + const byte* table; + + } grSaturation; + + + static + const byte gr_saturation_5[8] = { 0, 1, 2, 3, 4, 4, 4, 4 }; + + + static + const byte gr_saturation_17[32] = + { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + }; + + + static + grSaturation gr_saturations[ GR_MAX_SATURATIONS ] = + { + { 5, gr_saturation_5 }, + { 17, gr_saturation_17 } + }; + + static + int gr_num_saturations = 2; + + static + grSaturation* gr_last_saturation = gr_saturations; + + + extern + const byte* grGetSaturation( int num_grays ) + { + /* first of all, scan the current saturations table */ + grSaturation* sat = gr_saturations; + grSaturation* limit = sat + gr_num_saturations; + + if ( num_grays < 2 ) + { + grError = gr_err_bad_argument; + return 0; + } + + for ( ; sat < limit; sat++ ) + { + if ( sat->count == num_grays ) + { + gr_last_saturation = sat; + return sat->table; + } + } + + /* not found, simply create a new entry if there is room */ + if (gr_num_saturations < GR_MAX_SATURATIONS) + { + int i; + const byte* table; + + table = (const byte*)grAlloc( (3*num_grays-1)*sizeof(byte) ); + if (!table) return 0; + + sat->count = num_grays; + sat->table = table; + + for ( i = 0; i < num_grays; i++, table++ ) + *(unsigned char*)table = (unsigned char)i; + + for ( i = 2*num_grays-1; i > 0; i--, table++ ) + *(unsigned char*)table = (unsigned char)(num_grays-1); + + gr_num_saturations++; + gr_last_saturation = sat; + return sat->table; + } + grError = gr_err_saturation_overflow; + return 0; + } + + + + /*******************************************************************/ + /* */ + /* conversion tables */ + /* */ + /*******************************************************************/ + + typedef struct grConversion_ + { + int target_grays; + int source_grays; + const byte* table; + + } grConversion; + + + + static + const byte gr_gray5_to_gray17[5] = { 0, 4, 8, 12, 16 }; + + + static + const byte gr_gray5_to_gray128[5] = { 0, 32, 64, 96, 127 }; + + + static + const unsigned char gr_gray17_to_gray128[17] = + { + 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120, 127 + }; + + static + grConversion gr_conversions[ GR_MAX_CONVERSIONS ] = + { + { 17, 5, gr_gray5_to_gray17 }, + { 128, 5, gr_gray5_to_gray128 }, + { 128, 17, gr_gray17_to_gray128 } + }; + + static + int gr_num_conversions = 3; + + static + grConversion* gr_last_conversion = gr_conversions; + + + extern + const byte* grGetConversion( int target_grays, + int source_grays ) + { + grConversion* conv = gr_conversions; + grConversion* limit = conv + gr_num_conversions; + + if ( target_grays < 2 || source_grays < 2 ) + { + grError = gr_err_bad_argument; + return 0; + } + + /* otherwise, scan table */ + for ( ; conv < limit; conv++ ) + { + if ( conv->target_grays == target_grays && + conv->source_grays == source_grays ) + { + gr_last_conversion = conv; + return conv->table; + } + } + + /* not found, add a new conversion to the table */ + if (gr_num_conversions < GR_MAX_CONVERSIONS) + { + const byte* table; + int n; + + table = (const byte*)grAlloc( source_grays*sizeof(byte) ); + if (!table) + return 0; + + conv->target_grays = target_grays; + conv->source_grays = source_grays; + conv->table = table; + + for ( n = 0; n < source_grays; n++ ) + ((unsigned char*)table)[n] = (unsigned char)(n*(target_grays-1)) / + (source_grays-1); + + gr_num_conversions++; + gr_last_conversion = conv; + return table; + } + grError = gr_err_conversion_overflow; + return 0; + } + + + + +/**************************************************************************/ +/* */ +/* blit_gray_to_gray */ +/* */ +/**************************************************************************/ + + static + void blit_gray_to_gray( grBlitter* blit, + const byte* saturation, + const byte* conversion ) + { + int y; + unsigned char* read; + unsigned char* write; + unsigned char max1; + unsigned char max2; + + max1 = (unsigned char)(blit->source.grays-1); + max2 = (unsigned char)(blit->target.grays-1); + + read = (unsigned char*)blit->read + blit->xread; + write = (unsigned char*)blit->write + blit->xwrite; + + y = blit->height; + do + { + unsigned char* _read = read; + unsigned char* _write = write; + int x = blit->width; + + while (x > 0) + { +#ifdef GR_CONFIG_GRAY_SKIP_WHITE + unsigned char val = *_read; + + if (val) + { + if (val == max) + *_write = max2; + else + *_write = saturation[ (int)*_write + conversion[ *_read ] ]; + } +#else + *_write = saturation[ (int)*_write + conversion[ *_read ] ]; +#endif + _write++; + _read++; + x--; + } + + read += blit->read_line; + write += blit->write_line; + y--; + } + while (y > 0); + } + + +/**************************************************************************/ +/* */ +/* blit_gray_to_gray_simple */ +/* */ +/**************************************************************************/ + + static + void blit_gray_to_gray_simple( grBlitter* blit, + const byte* saturation ) + { + int y; + unsigned char* read; + unsigned char* write; + unsigned char max; + + max = (unsigned char)(blit->source.grays-1); + + read = (unsigned char*)blit->read + blit->xread; + write = (unsigned char*)blit->write + blit->xwrite; + + y = blit->height; + do + { + unsigned char* _read = read; + unsigned char* _write = write; + int x = blit->width; + + while (x > 0) + { +#ifdef GR_CONFIG_GRAY_SKIP_WHITE + unsigned char val = *_read; + + if (val) + { + if (val == max) + *_write = val; + else + *_write = saturation[ (int)*_write + *_read ]; + } +#else + *_write = saturation[ (int)*_write + *_read ]; +#endif + _write++; + _read++; + x--; + } + + read += blit->read_line; + write += blit->write_line; + y--; + } + while (y > 0); + } + + + +#define compose_pixel( a, b, n, max ) \ + { \ + int d, half = max >> 1; \ + \ + d = (int)b.chroma[0] - a.chroma[0]; \ + a.chroma[0] += (n*d + half)/max; \ + \ + d = (int)b.chroma[1] - a.chroma[1]; \ + a.chroma[1] += (n*d + half)/max; \ + \ + d = (int)b.chroma[2] - a.chroma[2]; \ + a.chroma[2] += (n*d + half)/max; \ + } + + +#define extract555( pixel, color ) \ + color.chroma[0] = (pixel >> 10) & 0x1F; \ + color.chroma[1] = (pixel >> 5) & 0x1F; \ + color.chroma[2] = (pixel ) & 0x1F; + + +#define extract565( pixel, color ) \ + color.chroma[0] = (pixel >> 11) & 0x1F; \ + color.chroma[1] = (pixel >> 5) & 0x3F; \ + color.chroma[2] = (pixel ) & 0x1F; + + +#define inject555( color ) \ + ( ( (unsigned short)color.chroma[0] << 10 ) | \ + ( (unsigned short)color.chroma[1] << 5 ) | \ + color.chroma[2] ) + + +#define inject565( color ) \ + ( ( (unsigned short)color.chroma[0] << 11 ) | \ + ( (unsigned short)color.chroma[1] << 5 ) | \ + color.chroma[2] ) + + +/**************************************************************************/ +/* */ +/* blit_gray_to_555 */ +/* */ +/**************************************************************************/ + + static + void blit_gray_to_555( grBlitter* blit, + grColor color, + int max ) + { + int y; + unsigned char* read; + unsigned char* write; + long color2; + + read = blit->read + blit->xread; + write = blit->write + 2*blit->xwrite; + + /* convert color to R:G:B triplet */ + color2 = color.value; + extract555( color2, color ); + + y = blit->height; + do + { + unsigned char* _read = read; + unsigned char* _write = write; + int x = blit->width; + + while (x > 0) + { + unsigned char val; + + val = *_read; + if (val) + { + unsigned short* pixel = (unsigned short*)_write; + + if (val == max) + { + pixel[0] = (short)color2; + } + else + { + /* compose gray value */ + unsigned short pix16 = *pixel; + grColor pix; + + extract555( pix16, pix ); + + compose_pixel( pix, color, val, max ); + *pixel = inject555(pix); + } + } + _write += 2; + _read ++; + x--; + } + + read += blit->read_line; + write += blit->write_line; + y--; + } + while (y > 0); + } + + +/**************************************************************************/ +/* */ +/* blit_gray_to_565 */ +/* */ +/**************************************************************************/ + + static + void blit_gray_to_565( grBlitter* blit, + grColor color, + int max ) + { + int y; + unsigned char* read; + unsigned char* write; + long color2; + + read = blit->read + blit->xread; + write = blit->write + 2*blit->xwrite; + + color2 = color.value; + extract565( color2, color ); + + y = blit->height; + do + { + unsigned char* _read = read; + unsigned char* _write = write; + int x = blit->width; + + while (x > 0) + { + unsigned char val; + + val = *_read; + if (val) + { + unsigned short* pixel = (unsigned short*)_write; + + if (val == max) + { + pixel[0] = (short)color2; + } + else + { + /* compose gray value */ + unsigned short pix16 = *pixel; + grColor pix; + + extract565( pix16, pix ); + + compose_pixel( pix, color, val, max ); + *pixel = inject565( pix ); + } + } + _write +=2; + _read ++; + x--; + } + + read += blit->read_line; + write += blit->write_line; + y--; + } + while (y > 0); + } + + +/**************************************************************************/ +/* */ +/* blit_gray_to_24 */ +/* */ +/**************************************************************************/ + + static + void blit_gray_to_24( grBlitter* blit, + grColor color, + int max ) + { + int y; + unsigned char* read; + unsigned char* write; + + read = blit->read + blit->xread; + write = blit->write + 3*blit->xwrite; + + y = blit->height; + do + { + unsigned char* _read = read; + unsigned char* _write = write; + int x = blit->width; + + while (x > 0) + { + unsigned char val; + + val = *_read; + if (val) + { + if (val == max) + { + _write[0] = color.chroma[0]; + _write[1] = color.chroma[1]; + _write[2] = color.chroma[2]; + } + else + { + /* compose gray value */ + grColor pix; + + pix.chroma[0] = _write[0]; + pix.chroma[1] = _write[1]; + pix.chroma[2] = _write[2]; + + compose_pixel( pix, color, val, max ); + + _write[0] = pix.chroma[0]; + _write[1] = pix.chroma[1]; + _write[2] = pix.chroma[2]; + } + } + _write += 3; + _read ++; + x--; + } + + read += blit->read_line; + write += blit->write_line; + y--; + } + while (y > 0); + } + + +/**************************************************************************/ +/* */ +/* blit_gray_to_32 */ +/* */ +/**************************************************************************/ + + static + void blit_gray_to_32( grBlitter* blit, + grColor color, + int max ) + { + int y; + unsigned char* read; + unsigned char* write; + + read = blit->read + blit->xread; + write = blit->write + 4*blit->xwrite; + + y = blit->height; + do + { + unsigned char* _read = read; + unsigned char* _write = write; + int x = blit->width; + + while (x > 0) + { + unsigned char val; + + val = *_read; + if (val) + { + if (val == max) + { + _write[0] = color.chroma[0]; + _write[1] = color.chroma[1]; + _write[2] = color.chroma[2]; + _write[3] = color.chroma[3]; + } + else + { + /* compose gray value */ + grColor pix; + + pix.chroma[0] = _write[0]; + pix.chroma[1] = _write[1]; + pix.chroma[2] = _write[2]; + + compose_pixel( pix, color, val, max ); + + _write[0] = pix.chroma[0]; + _write[1] = pix.chroma[1]; + _write[2] = pix.chroma[2]; + } + } + _write += 4; + _read ++; + x--; + } + + read += blit->read_line; + write += blit->write_line; + y--; + } + while (y > 0); + } + + + /********************************************************************** + * + * + * grBlitGlyphBitmap + * + * + * writes a given glyph bitmap to a target surface. + * + * + * surface :: handle to target surface + * x :: position of left-most pixel of glyph image in surface + * y :: position of top-most pixel of glyph image in surface + * bitmap :: source glyph image + * + * + * Error code. 0 means success + * + **********************************************************************/ + + typedef void (*grColorGlyphBlitter)( grBlitter* blit, + grColor color, + int max_gray ); + + static + const grColorGlyphBlitter gr_color_blitters[gr_pixel_mode_max] = + { + 0, + 0, + 0, + 0, + blit_gray_to_555, + blit_gray_to_565, + blit_gray_to_24, + blit_gray_to_32 + }; + + + extern int grBlitGlyphToBitmap( grBitmap* target, + grBitmap* glyph, + grPos x, + grPos y, + grColor color ) + { + grBlitter blit; + grPixelMode mode; + + /* check arguments */ + if (!target || !glyph) + { + grError = gr_err_bad_argument; + return -1; + } + + + /* set up blitter and compute clipping. Return immediately if needed */ + blit.source = *glyph; + blit.target = *target; + mode = target->mode; + + if ( compute_clips( &blit, x, y ) ) + return 0; + + + /* handle monochrome bitmap blitting */ + if (glyph->mode == gr_pixel_mode_mono) + { + if ( mode <= gr_pixel_mode_none || mode >= gr_pixel_mode_max ) + { + grError = gr_err_bad_source_depth; + return -1; + } + + gr_mono_blitters[mode]( &blit, color ); + goto End; + } + + /* handle gray bitmap composition */ + if (glyph->mode == gr_pixel_mode_gray && + glyph->grays > 1 ) + { + int target_grays = target->grays; + int source_grays = glyph->grays; + const byte* saturation; + + if ( mode == gr_pixel_mode_gray && target_grays > 1 ) + { + /* rendering into a gray target - use special composition */ + /* routines.. */ + if ( gr_last_saturation->count == target_grays ) + saturation = gr_last_saturation->table; + else + { + saturation = grGetSaturation( target_grays ); + if (!saturation) return -3; + } + + + if ( target_grays == source_grays ) + blit_gray_to_gray_simple( &blit, saturation ); + else + { + const byte* conversion; + + if ( gr_last_conversion->target_grays == target_grays && + gr_last_conversion->source_grays == source_grays ) + conversion = gr_last_conversion->table; + else + { + conversion = grGetConversion( target_grays, source_grays ); + if (!conversion) return -3; + }; + + blit_gray_to_gray( &blit, saturation, conversion ); + } + } + else + { + /* rendering into a color target */ + if ( mode <= gr_pixel_mode_gray || + mode >= gr_pixel_mode_max ) + { + grError = gr_err_bad_target_depth; + return -1; + } + + gr_color_blitters[mode]( &blit, color, source_grays-1 ); + } + goto End; + } + + /* we don't support the blitting of bitmaps of the following */ + /* types : pal4, pal8, rgb555, rgb565, rgb24, rgb32 */ + /* */ + grError = gr_err_bad_source_depth; + return -2; + + End: + return 0; + } + + +/* End */ diff --git a/demos/graph/grblit.h b/demos/graph/grblit.h new file mode 100644 index 000000000..4d0b6e5a8 --- /dev/null +++ b/demos/graph/grblit.h @@ -0,0 +1,25 @@ +/****************************************************************************/ +/* */ +/* The FreeType project -- a free and portable quality TrueType renderer. */ +/* */ +/* Copyright 1996-1999 by */ +/* D. Turner, R.Wilhelm, and W. Lemberg */ +/* */ +/* blitter.h: Support for blitting of bitmaps with various depth. */ +/* */ +/****************************************************************************/ + +#ifndef GRBLIT_H +#define GRBLIT_H + +#include "grobjs.h" + + int grBlitMono( grBitmap* target, + grBitmap* source, + int x_offset, + int y_offset, + grColor color ); + + +#endif /* GRBLIT_H */ +/* End */ diff --git a/demos/graph/grconfig.h b/demos/graph/grconfig.h new file mode 100644 index 000000000..02d8f4dfb --- /dev/null +++ b/demos/graph/grconfig.h @@ -0,0 +1,9 @@ +#ifndef GRCONFIG_H +#define GRCONFIG_H + +#define GR_MAX_SATURATIONS 8 +#define GR_MAX_CONVERSIONS 16 + +#define GR_MAX_DEVICES 8 + +#endif /* GRCONFIG_H */ diff --git a/demos/graph/grdevice.c b/demos/graph/grdevice.c new file mode 100644 index 000000000..3d2eb287b --- /dev/null +++ b/demos/graph/grdevice.c @@ -0,0 +1,361 @@ +#include "grobjs.h" +#include "grdevice.h" +#include + + grDeviceChain gr_device_chain[ GR_MAX_DEVICES ]; + int gr_num_devices = 0; + + static + grDevice* find_device( const char* device_name ) + { + int index = 0; + + if (device_name) + { + for ( index = gr_num_devices-1; index > 0; index-- ) + if ( strcmp( device_name, gr_device_chain[index].name ) == 0 ) + break; + } + + if ( index < 0 || gr_num_devices <= 0 || !gr_device_chain[index].device ) + { + grError = gr_err_invalid_device; + return 0; + } + + return gr_device_chain[index].device; + } + + + + /********************************************************************** + * + * + * grGetDeviceModes + * + * + * queries the available pixel modes for a device. + * + * + * device_name :: name of device to be used. 0 for the default + * device. For a list of available devices, see + * grInitDevices. + * + * + * num_modes :: number of available modes. 0 in case of error, + * which really is an invalid device name. + * + * pixel_modes :: array of available pixel modes for this device + * this table is internal to the device and should + * not be freed by client applications. + * + * + * error code. 0 means success. invalid device name otherwise + * + * + * All drivers are _required_ to support at least the following + * pixel formats : + * + * - gr_pixel_mode_mono : i.e. monochrome bitmaps + * - gr_pixel_mode_gray : with any number of gray levels between + * 2 and 256. + * + * the pixel modes do not provide the number of grays in the case + * of "gray" devices. You should try to create a surface with the + * maximal number (256, that is) and see the value returned in + * the bitmap descriptor. + * + **********************************************************************/ + + extern void grGetDeviceModes( const char* device_name, + int *num_modes, + grPixelMode* *pixel_modes ) + { + grDevice* device; + + *num_modes = 0; + *pixel_modes = 0; + + device = find_device( device_name ); + if (device) + { + *num_modes = device->num_pixel_modes; + *pixel_modes = device->pixel_modes; + } + } + + + /********************************************************************** + * + * + * grNewSurface + * + * + * creates a new device-specific surface. A surface is either + * a window or a screen, depending on the device. + * + * + * device :: name of the device to use. A value of NULL means + * the default device (which depends on the system). + * for a list of available devices, see grInitDevices. + * + * + * bitmap :: handle to a bitmap descriptor containing the + * requested pixel mode, number of grays and dimensions + * for the surface. the bitmap's 'pitch' and 'buffer' + * fields are ignored on input. + * + * On output, the bitmap describes the surface's image + * completely. It is possible to write directly in it + * with grBlitGlyphToBitmap, even though the use of + * grBlitGlyphToSurface is recommended. + * + * + * handle to the corresponding surface object. 0 in case of error + * + * + * All drivers are _required_ to support at least the following + * pixel formats : + * + * - gr_pixel_mode_mono : i.e. monochrome bitmaps + * - gr_pixel_mode_gray : with any number of gray levels between + * 2 and 256. + * + * This function might change the bitmap descriptor's fields. For + * example, when displaying a full-screen surface, the bitmap's + * dimensions will be set to those of the screen (e.g. 640x480 + * or 800x600); also, the bitmap's 'buffer' field might point to + * the Video Ram depending on the mode requested.. + * + * The surface contains a copy of the returned bitmap descriptor, + * you can thus discard the 'bitmap' parameter after the call. + * + **********************************************************************/ + + extern grSurface* grNewSurface( const char* device_name, + grBitmap* bitmap ) + { + grDevice* device; + grSurface* surface; + + /* Now find the device */ + device = find_device( device_name ); + if (!device) return 0; + + surface = (grSurface*)grAlloc( device->surface_objsize ); + if (!surface) return 0; + + if ( !device->init_surface( surface, bitmap ) ) + { + grFree( surface ); + surface = 0; + } + return surface; + } + + + /********************************************************************** + * + * + * grRefreshRectangle + * + * + * this function is used to indicate that a given surface rectangle + * was modified and thus needs re-painting. It really is useful for + * windowed or gray surfaces. + * + * + * surface :: handle to target surface + * x :: x coordinate of the top-left corner of the rectangle + * y :: y coordinate of the top-left corner of the rectangle + * width :: rectangle width in pixels + * height :: rectangle height in pixels + * + **********************************************************************/ + + extern void grRefreshRectangle( grSurface* surface, + grPos x, + grPos y, + grPos width, + grPos height ) + { + if (surface->refresh_rect) + surface->refresh_rect( surface, x, y, width, height ); + } + + + + /********************************************************************** + * + * + * grWriteSurfaceChar + * + * + * This function is equivalent to calling grWriteCellChar on the + * surface's bitmap, then invoking grRefreshRectangle. + * + * The graphics sub-system contains an internal Latin1 8x8 font + * which can be used to display simple strings of text without + * using FreeType. + * + * This function writes a single 8x8 character on the target bitmap. + * + * + * target :: handle to target surface + * x :: x pixel position of character cell's top left corner + * y :: y pixel position of character cell's top left corner + * charcode :: Latin-1 character code + * color :: color to be used to draw the character + * + **********************************************************************/ + + extern + void grWriteSurfaceChar( grSurface* target, + int x, + int y, + int charcode, + grColor color ) + { + grWriteCellChar( &target->bitmap, x, y, charcode, color ); + if (target->refresh_rect) + target->refresh_rect( target, x, y, 8, 8 ); + } + + + /********************************************************************** + * + * + * grWriteSurfaceString + * + * + * This function is equivalent to calling grWriteCellString on the + * surface's bitmap, then invoking grRefreshRectangle. + * + * The graphics sub-system contains an internal Latin1 8x8 font + * which can be used to display simple strings of text without + * using FreeType. + * + * This function writes a string with the internal font + * + * + * target :: handle to target bitmap + * x :: x pixel position of string's top left corner + * y :: y pixel position of string's top left corner + * string :: Latin-1 text string + * color :: color to be used to draw the character + * + **********************************************************************/ + + extern + void grWriteSurfaceString( grSurface* target, + int x, + int y, + const char* string, + grColor color ) + { + int len; + + len = strlen(string); + grWriteCellString( &target->bitmap, x, y, string, color ); + if (target->refresh_rect) + target->refresh_rect( target, x, y, 8*len, 8 ); + } + + + /********************************************************************** + * + * + * grRefreshSurface + * + * + * a variation of grRefreshRectangle which repaints the whole surface + * to the screen. + * + * + * surface :: handle to target surface + * + **********************************************************************/ + + extern void grRefreshSurface( grSurface* surface ) + { + if (surface->refresh_rect) + surface->refresh_rect( surface, 0, 0, + surface->bitmap.width, + surface->bitmap.rows ); + } + + + + /********************************************************************** + * + * + * grSetTitle + * + * + * set the window title of a given windowed surface. + * + * + * surface :: handle to target surface + * title_string :: the new title + * + **********************************************************************/ + + extern void grSetTitle( grSurface* surface, + const char* title_string ) + { + if (surface->set_title) + surface->set_title( surface, title_string ); + } + + + + + /********************************************************************** + * + * + * grListenSurface + * + * + * listen the events for a given surface + * + * + * surface :: handle to target surface + * event_mask :: the event mask (mode) + * + * + * event :: the returned event + * + * + * XXX : For now, only keypresses are supported. + * + **********************************************************************/ + + extern + int grListenSurface( grSurface* surface, + int event_mask, + grEvent *event ) + { + return surface->listen_event( surface, event_mask, event ); + } + + +#if 0 + static + void gr_done_surface( grSurface* surface ) + { + if (surface) + { + /* first of all, call the device-specific destructor */ + surface->done(surface); + + /* then remove the bitmap if we're owner */ + if (surface->owner) + grFree( surface->bitmap.buffer ); + + surface->owner = 0; + surface->bitmap.buffer = 0; + grFree( surface ); + } + } +#endif + diff --git a/demos/graph/grdevice.h b/demos/graph/grdevice.h new file mode 100644 index 000000000..a43460932 --- /dev/null +++ b/demos/graph/grdevice.h @@ -0,0 +1,126 @@ +/*************************************************************************** + * + * grdevice.h + * + * Graphics device interface + * + * Copyright 1999 - The FreeType Development Team - www.freetype.org + * + * + ***************************************************************************/ + +#ifndef GRDEVICE_H +#define GRDEVICE_H + +#include "graph.h" + + + /******************************************************************** + * + * + * grDeviceInitFunc + * + * + * Simple device initialiser function + * + * + * error code. 0 means success + * + ********************************************************************/ + + typedef int (*grDeviceInitFunc)( void ); + + + /******************************************************************** + * + * + * grDeviceDoneFunc + * + * + * Simple device finaliser function + * + * + * error code. 0 means success + * + ********************************************************************/ + + typedef void (*grDeviceDoneFunc)( void ); + + + /******************************************************************** + * + * + * grDeviceInitSurfaceFunc + * + * + * initializes a new surface for the device. This may be a window + * or a video screen, depending on the device. + * + * + * surface :: handle to target surface + * + * + * bitmap :: handle to bitmap descriptor + * + ********************************************************************/ + + typedef int (*grDeviceInitSurfaceFunc)( grSurface* surface, + grBitmap* bitmap ); + + + /******************************************************************** + * + * + * grDevice + * + * + * Simple device interface structure + * + * + * surface_objsize :: size in bytes of a single surface object for + * this device. + * + * device_name :: name of device, e.g. "x11", "os2pm", "directx" etc.. + * init :: device initialisation routine + * done :: device finalisation + * new_surface :: function used to create a new surface (screen or + * window) from the device + * + * num_pixel_modes :: the number of pixel modes supported by this + * device. This value _must_ be set to -1 + * default, unless the device provides a + * static set of pixel modes (fullscreen). + * + * pixel_modes :: an array of pixel modes supported by this + * device + * + * + * the fields "num_pixel_modes" and "pixel_modes" must be + * set by the "init" function. + * + * This allows windowed devices to "discover" at run-time the + * available pixel modes they can provide depending on the + * current screen depth. + * + ********************************************************************/ + + struct grDevice_ + { + int surface_objsize; + const char* device_name; /* name of device */ + + grDeviceInitFunc init; + grDeviceDoneFunc done; + + grDeviceInitSurfaceFunc init_surface; + + int num_pixel_modes; + grPixelMode* pixel_modes; + }; + + + extern grDeviceChain gr_device_chain[]; + extern int gr_num_devices; + + +#endif /* GRDEVICE_H */ diff --git a/demos/graph/grevents.h b/demos/graph/grevents.h new file mode 100644 index 000000000..c32f75b9d --- /dev/null +++ b/demos/graph/grevents.h @@ -0,0 +1,117 @@ +#ifndef GREVENTS_H +#define GREVENTS_H + + +#define gr_event_none 0 +#define gr_event_wait 1 +#define gr_event_poll 2 +#define gr_event_flush 3 + +#define gr_mouse_down 0x04 +#define gr_mouse_move 0x08 +#define gr_mouse_up 0x10 +#define gr_mouse_drag 0x20 + +#define gr_key_down 0x40 +#define gr_key_up 0x80 + + +#define gr_event_mouse 0x3C +#define gr_event_key 0xC0 + +#define gr_event_type (gr_event_mouse | gr_event_key) + + + typedef enum grKey_ + { + grKeyNone = 0, + + grKeyF1, + grKeyF2, + grKeyF3, + grKeyF4, + grKeyF5, + grKeyF6, + grKeyF7, + grKeyF8, + grKeyF9, + grKeyF10, + grKeyF11, + grKeyF12, + + grKeyLeft, + grKeyRight, + grKeyUp, + grKeyDown, + + grKeyIns, + grKeyDel, + grKeyHome, + grKeyEnd, + grKeyPageUp, + grKeyPageDown, + + grKeyEsc, + grKeyTab, + grKeyBackSpace, + grKeyReturn, + + grKeyMax, + grKeyForceShort = 0x7FFF /* this forces the grKey to be stored */ + /* on at least one short ! */ + + } grKey; + +#define grKEY(c) ((grKey)(c)) + +#define grKeyAlt ((grKey)0x8000) +#define grKeyCtrl ((grKey)0x4000) +#define grKeyShift ((grKey)0x2000) + +#define grKeyModifiers ((grKey)0xE000) + +#define grKey0 grKEY('0') +#define grKey1 grKEY('1') +#define grKey2 grKEY('2') +#define grKey3 grKEY('3') +#define grKey4 grKEY('4') +#define grKey5 grKEY('5') +#define grKey6 grKEY('6') +#define grKey7 grKEY('7') +#define grKey8 grKEY('8') +#define grKey9 grKEY('9') + + +#define grKeyPlus grKEY('+') +#define grKeyLess grKEY('-') +#define grKeyEqual grKEY('=') +#define grKeyMult grKEY('*') +#define grKeyDollar grKEY('$') +#define grKeySmaller grKEY('<') +#define grKeyGreater grKEY('>') +#define grKeyQuestion grKEY('?') +#define grKeyComma grKEY(',') +#define grKeyDot grKEY('.') +#define grKeySemiColumn grKEY(';') +#define grKeyColumn grKEY(':') +#define grKeyDiv grKEY('/') +#define grKeyExclam grKEY('!') +#define grKeyPercent grKEY('%') +#define grKeyLeftParen grKEY('(') +#define grKeyRightParen grKEY('(') +#define grKeyAt grKEY('@') +#define grKeyUnder grKEY('_') + + + typedef struct grEvent_ + { + int type; + grKey key; + int x, y; + + } grEvent; + + + +#endif /* GREVENTS_H */ + diff --git a/demos/graph/grfont.c b/demos/graph/grfont.c new file mode 100644 index 000000000..8b9df372c --- /dev/null +++ b/demos/graph/grfont.c @@ -0,0 +1,354 @@ +#include "grfont.h" + + /* font characters */ + + const unsigned char font_8x8[2048] = + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7E, 0x81, 0xA5, 0x81, 0xBD, 0x99, 0x81, 0x7E, + 0x7E, 0xFF, 0xDB, 0xFF, 0xC3, 0xE7, 0xFF, 0x7E, + 0x6C, 0xFE, 0xFE, 0xFE, 0x7C, 0x38, 0x10, 0x00, + 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x10, 0x00, + 0x38, 0x7C, 0x38, 0xFE, 0xFE, 0x92, 0x10, 0x7C, + 0x00, 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x7C, + 0x00, 0x00, 0x18, 0x3C, 0x3C, 0x18, 0x00, 0x00, + 0xFF, 0xFF, 0xE7, 0xC3, 0xC3, 0xE7, 0xFF, 0xFF, + 0x00, 0x3C, 0x66, 0x42, 0x42, 0x66, 0x3C, 0x00, + 0xFF, 0xC3, 0x99, 0xBD, 0xBD, 0x99, 0xC3, 0xFF, + 0x0F, 0x07, 0x0F, 0x7D, 0xCC, 0xCC, 0xCC, 0x78, + 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18, + 0x3F, 0x33, 0x3F, 0x30, 0x30, 0x70, 0xF0, 0xE0, + 0x7F, 0x63, 0x7F, 0x63, 0x63, 0x67, 0xE6, 0xC0, + 0x99, 0x5A, 0x3C, 0xE7, 0xE7, 0x3C, 0x5A, 0x99, + 0x80, 0xE0, 0xF8, 0xFE, 0xF8, 0xE0, 0x80, 0x00, + 0x02, 0x0E, 0x3E, 0xFE, 0x3E, 0x0E, 0x02, 0x00, + 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x7E, 0x3C, 0x18, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00, + 0x7F, 0xDB, 0xDB, 0x7B, 0x1B, 0x1B, 0x1B, 0x00, + 0x3E, 0x63, 0x38, 0x6C, 0x6C, 0x38, 0x86, 0xFC, + 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0x7E, 0x00, + 0x18, 0x3C, 0x7E, 0x18, 0x7E, 0x3C, 0x18, 0xFF, + 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00, + 0x00, 0x18, 0x0C, 0xFE, 0x0C, 0x18, 0x00, 0x00, + 0x00, 0x30, 0x60, 0xFE, 0x60, 0x30, 0x00, 0x00, + 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xFE, 0x00, 0x00, + 0x00, 0x24, 0x66, 0xFF, 0x66, 0x24, 0x00, 0x00, + 0x00, 0x18, 0x3C, 0x7E, 0xFF, 0xFF, 0x00, 0x00, + 0x00, 0xFF, 0xFF, 0x7E, 0x3C, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18, 0x00, + 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x6C, 0x6C, 0xFE, 0x6C, 0xFE, 0x6C, 0x6C, 0x00, + 0x18, 0x7E, 0xC0, 0x7C, 0x06, 0xFC, 0x18, 0x00, + 0x00, 0xC6, 0xCC, 0x18, 0x30, 0x66, 0xC6, 0x00, + 0x38, 0x6C, 0x38, 0x76, 0xDC, 0xCC, 0x76, 0x00, + 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x30, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00, + 0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00, + 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00, + 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, + 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, + 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0x80, 0x00, + 0x7C, 0xCE, 0xDE, 0xF6, 0xE6, 0xC6, 0x7C, 0x00, + 0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0xFC, 0x00, + 0x78, 0xCC, 0x0C, 0x38, 0x60, 0xCC, 0xFC, 0x00, + 0x78, 0xCC, 0x0C, 0x38, 0x0C, 0xCC, 0x78, 0x00, + 0x1C, 0x3C, 0x6C, 0xCC, 0xFE, 0x0C, 0x1E, 0x00, + 0xFC, 0xC0, 0xF8, 0x0C, 0x0C, 0xCC, 0x78, 0x00, + 0x38, 0x60, 0xC0, 0xF8, 0xCC, 0xCC, 0x78, 0x00, + 0xFC, 0xCC, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x00, + 0x78, 0xCC, 0xCC, 0x78, 0xCC, 0xCC, 0x78, 0x00, + 0x78, 0xCC, 0xCC, 0x7C, 0x0C, 0x18, 0x70, 0x00, + 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, + 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x30, + 0x18, 0x30, 0x60, 0xC0, 0x60, 0x30, 0x18, 0x00, + 0x00, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x00, 0x00, + 0x60, 0x30, 0x18, 0x0C, 0x18, 0x30, 0x60, 0x00, + 0x3C, 0x66, 0x0C, 0x18, 0x18, 0x00, 0x18, 0x00, + 0x7C, 0xC6, 0xDE, 0xDE, 0xDC, 0xC0, 0x7C, 0x00, + 0x30, 0x78, 0xCC, 0xCC, 0xFC, 0xCC, 0xCC, 0x00, + 0xFC, 0x66, 0x66, 0x7C, 0x66, 0x66, 0xFC, 0x00, + 0x3C, 0x66, 0xC0, 0xC0, 0xC0, 0x66, 0x3C, 0x00, + 0xF8, 0x6C, 0x66, 0x66, 0x66, 0x6C, 0xF8, 0x00, + 0xFE, 0x62, 0x68, 0x78, 0x68, 0x62, 0xFE, 0x00, + 0xFE, 0x62, 0x68, 0x78, 0x68, 0x60, 0xF0, 0x00, + 0x3C, 0x66, 0xC0, 0xC0, 0xCE, 0x66, 0x3A, 0x00, + 0xCC, 0xCC, 0xCC, 0xFC, 0xCC, 0xCC, 0xCC, 0x00, + 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x1E, 0x0C, 0x0C, 0x0C, 0xCC, 0xCC, 0x78, 0x00, + 0xE6, 0x66, 0x6C, 0x78, 0x6C, 0x66, 0xE6, 0x00, + 0xF0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xFE, 0x00, + 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6, 0xC6, 0x00, + 0xC6, 0xE6, 0xF6, 0xDE, 0xCE, 0xC6, 0xC6, 0x00, + 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x00, + 0xFC, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0, 0x00, + 0x7C, 0xC6, 0xC6, 0xC6, 0xD6, 0x7C, 0x0E, 0x00, + 0xFC, 0x66, 0x66, 0x7C, 0x6C, 0x66, 0xE6, 0x00, + 0x7C, 0xC6, 0xE0, 0x78, 0x0E, 0xC6, 0x7C, 0x00, + 0xFC, 0xB4, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xFC, 0x00, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x00, + 0xC6, 0xC6, 0xC6, 0xC6, 0xD6, 0xFE, 0x6C, 0x00, + 0xC6, 0xC6, 0x6C, 0x38, 0x6C, 0xC6, 0xC6, 0x00, + 0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x30, 0x78, 0x00, + 0xFE, 0xC6, 0x8C, 0x18, 0x32, 0x66, 0xFE, 0x00, + 0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00, + 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x02, 0x00, + 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00, + 0x10, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, + 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00, + 0xE0, 0x60, 0x60, 0x7C, 0x66, 0x66, 0xDC, 0x00, + 0x00, 0x00, 0x78, 0xCC, 0xC0, 0xCC, 0x78, 0x00, + 0x1C, 0x0C, 0x0C, 0x7C, 0xCC, 0xCC, 0x76, 0x00, + 0x00, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00, + 0x38, 0x6C, 0x64, 0xF0, 0x60, 0x60, 0xF0, 0x00, + 0x00, 0x00, 0x76, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8, + 0xE0, 0x60, 0x6C, 0x76, 0x66, 0x66, 0xE6, 0x00, + 0x30, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x0C, 0x00, 0x1C, 0x0C, 0x0C, 0xCC, 0xCC, 0x78, + 0xE0, 0x60, 0x66, 0x6C, 0x78, 0x6C, 0xE6, 0x00, + 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x00, 0x00, 0xCC, 0xFE, 0xFE, 0xD6, 0xD6, 0x00, + 0x00, 0x00, 0xB8, 0xCC, 0xCC, 0xCC, 0xCC, 0x00, + 0x00, 0x00, 0x78, 0xCC, 0xCC, 0xCC, 0x78, 0x00, + 0x00, 0x00, 0xDC, 0x66, 0x66, 0x7C, 0x60, 0xF0, + 0x00, 0x00, 0x76, 0xCC, 0xCC, 0x7C, 0x0C, 0x1E, + 0x00, 0x00, 0xDC, 0x76, 0x62, 0x60, 0xF0, 0x00, + 0x00, 0x00, 0x7C, 0xC0, 0x70, 0x1C, 0xF8, 0x00, + 0x10, 0x30, 0xFC, 0x30, 0x30, 0x34, 0x18, 0x00, + 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, + 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x00, + 0x00, 0x00, 0xC6, 0xC6, 0xD6, 0xFE, 0x6C, 0x00, + 0x00, 0x00, 0xC6, 0x6C, 0x38, 0x6C, 0xC6, 0x00, + 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8, + 0x00, 0x00, 0xFC, 0x98, 0x30, 0x64, 0xFC, 0x00, + 0x1C, 0x30, 0x30, 0xE0, 0x30, 0x30, 0x1C, 0x00, + 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00, + 0xE0, 0x30, 0x30, 0x1C, 0x30, 0x30, 0xE0, 0x00, + 0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0x00, + 0x7C, 0xC6, 0xC0, 0xC6, 0x7C, 0x0C, 0x06, 0x7C, + 0x00, 0xCC, 0x00, 0xCC, 0xCC, 0xCC, 0x76, 0x00, + 0x1C, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00, + 0x7E, 0x81, 0x3C, 0x06, 0x3E, 0x66, 0x3B, 0x00, + 0xCC, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00, + 0xE0, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00, + 0x30, 0x30, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00, + 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0x78, 0x0C, 0x38, + 0x7E, 0x81, 0x3C, 0x66, 0x7E, 0x60, 0x3C, 0x00, + 0xCC, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00, + 0xE0, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00, + 0xCC, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x7C, 0x82, 0x38, 0x18, 0x18, 0x18, 0x3C, 0x00, + 0xE0, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, + 0xC6, 0x10, 0x7C, 0xC6, 0xFE, 0xC6, 0xC6, 0x00, + 0x30, 0x30, 0x00, 0x78, 0xCC, 0xFC, 0xCC, 0x00, + 0x1C, 0x00, 0xFC, 0x60, 0x78, 0x60, 0xFC, 0x00, + 0x00, 0x00, 0x7F, 0x0C, 0x7F, 0xCC, 0x7F, 0x00, + 0x3E, 0x6C, 0xCC, 0xFE, 0xCC, 0xCC, 0xCE, 0x00, + 0x78, 0x84, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00, + 0x00, 0xCC, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00, + 0x00, 0xE0, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00, + 0x78, 0x84, 0x00, 0xCC, 0xCC, 0xCC, 0x76, 0x00, + 0x00, 0xE0, 0x00, 0xCC, 0xCC, 0xCC, 0x76, 0x00, + 0x00, 0xCC, 0x00, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8, + 0xC3, 0x18, 0x3C, 0x66, 0x66, 0x3C, 0x18, 0x00, + 0xCC, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0x78, 0x00, + 0x18, 0x18, 0x7E, 0xC0, 0xC0, 0x7E, 0x18, 0x18, + 0x38, 0x6C, 0x64, 0xF0, 0x60, 0xE6, 0xFC, 0x00, + 0xCC, 0xCC, 0x78, 0x30, 0xFC, 0x30, 0xFC, 0x30, + 0xF8, 0xCC, 0xCC, 0xFA, 0xC6, 0xCF, 0xC6, 0xC3, + 0x0E, 0x1B, 0x18, 0x3C, 0x18, 0x18, 0xD8, 0x70, + 0x1C, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00, + 0x38, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x00, 0x1C, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00, + 0x00, 0x1C, 0x00, 0xCC, 0xCC, 0xCC, 0x76, 0x00, + 0x00, 0xF8, 0x00, 0xB8, 0xCC, 0xCC, 0xCC, 0x00, + 0xFC, 0x00, 0xCC, 0xEC, 0xFC, 0xDC, 0xCC, 0x00, + 0x3C, 0x6C, 0x6C, 0x3E, 0x00, 0x7E, 0x00, 0x00, + 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x7C, 0x00, 0x00, + 0x18, 0x00, 0x18, 0x18, 0x30, 0x66, 0x3C, 0x00, + 0x00, 0x00, 0x00, 0xFC, 0xC0, 0xC0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xFC, 0x0C, 0x0C, 0x00, 0x00, + 0xC6, 0xCC, 0xD8, 0x36, 0x6B, 0xC2, 0x84, 0x0F, + 0xC3, 0xC6, 0xCC, 0xDB, 0x37, 0x6D, 0xCF, 0x03, + 0x18, 0x00, 0x18, 0x18, 0x3C, 0x3C, 0x18, 0x00, + 0x00, 0x33, 0x66, 0xCC, 0x66, 0x33, 0x00, 0x00, + 0x00, 0xCC, 0x66, 0x33, 0x66, 0xCC, 0x00, 0x00, + 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, + 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, + 0xDB, 0xF6, 0xDB, 0x6F, 0xDB, 0x7E, 0xD7, 0xED, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0x18, 0x18, + 0x18, 0x18, 0xF8, 0x18, 0xF8, 0x18, 0x18, 0x18, + 0x36, 0x36, 0x36, 0x36, 0xF6, 0x36, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, 0xFE, 0x36, 0x36, 0x36, + 0x00, 0x00, 0xF8, 0x18, 0xF8, 0x18, 0x18, 0x18, + 0x36, 0x36, 0xF6, 0x06, 0xF6, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x00, 0x00, 0xFE, 0x06, 0xF6, 0x36, 0x36, 0x36, + 0x36, 0x36, 0xF6, 0x06, 0xFE, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0xFE, 0x00, 0x00, 0x00, + 0x18, 0x18, 0xF8, 0x18, 0xF8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xF8, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x1F, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0xFF, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x1F, 0x18, 0x1F, 0x18, 0x18, 0x18, + 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x37, 0x30, 0x3F, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3F, 0x30, 0x37, 0x36, 0x36, 0x36, + 0x36, 0x36, 0xF7, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFF, 0x00, 0xF7, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, + 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0x36, 0x36, 0xF7, 0x00, 0xF7, 0x36, 0x36, 0x36, + 0x18, 0x18, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0xFF, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x3F, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x1F, 0x18, 0x1F, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1F, 0x18, 0x1F, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x3F, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0xFF, 0x36, 0x36, 0x36, + 0x18, 0x18, 0xFF, 0x18, 0xFF, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0xF8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x18, 0x18, 0x18, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, + 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x76, 0xDC, 0xC8, 0xDC, 0x76, 0x00, + 0x00, 0x78, 0xCC, 0xF8, 0xCC, 0xF8, 0xC0, 0xC0, + 0x00, 0xFC, 0xCC, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, + 0x00, 0x00, 0xFE, 0x6C, 0x6C, 0x6C, 0x6C, 0x00, + 0xFC, 0xCC, 0x60, 0x30, 0x60, 0xCC, 0xFC, 0x00, + 0x00, 0x00, 0x7E, 0xD8, 0xD8, 0xD8, 0x70, 0x00, + 0x00, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0xC0, + 0x00, 0x76, 0xDC, 0x18, 0x18, 0x18, 0x18, 0x00, + 0xFC, 0x30, 0x78, 0xCC, 0xCC, 0x78, 0x30, 0xFC, + 0x38, 0x6C, 0xC6, 0xFE, 0xC6, 0x6C, 0x38, 0x00, + 0x38, 0x6C, 0xC6, 0xC6, 0x6C, 0x6C, 0xEE, 0x00, + 0x1C, 0x30, 0x18, 0x7C, 0xCC, 0xCC, 0x78, 0x00, + 0x00, 0x00, 0x7E, 0xDB, 0xDB, 0x7E, 0x00, 0x00, + 0x06, 0x0C, 0x7E, 0xDB, 0xDB, 0x7E, 0x60, 0xC0, + 0x38, 0x60, 0xC0, 0xF8, 0xC0, 0x60, 0x38, 0x00, + 0x78, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x00, + 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x00, + 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x7E, 0x00, + 0x60, 0x30, 0x18, 0x30, 0x60, 0x00, 0xFC, 0x00, + 0x18, 0x30, 0x60, 0x30, 0x18, 0x00, 0xFC, 0x00, + 0x0E, 0x1B, 0x1B, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xD8, 0xD8, 0x70, + 0x18, 0x18, 0x00, 0x7E, 0x00, 0x18, 0x18, 0x00, + 0x00, 0x76, 0xDC, 0x00, 0x76, 0xDC, 0x00, 0x00, + 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x0F, 0x0C, 0x0C, 0x0C, 0xEC, 0x6C, 0x3C, 0x1C, + 0x58, 0x6C, 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, + 0x70, 0x98, 0x30, 0x60, 0xF8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3C, 0x3C, 0x3C, 0x3C, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + + static + grBitmap gr_charcell = + { + 8, /* rows */ + 8, /* width */ + gr_pixel_mode_mono, /* mode */ + 1, /* pitch */ + 0, /* grays */ + 0 /* buffer */ + }; + + void grWriteCellChar( grBitmap* target, + int x, + int y, + int charcode, + grColor color ) + { + if (charcode < 0 || charcode > 255) + return; + + gr_charcell.buffer = (char*)font_8x8 + 8*charcode; + grBlitGlyphToBitmap( target, &gr_charcell, x, y, color ); + } + + + void grWriteCellString( grBitmap* target, + int x, + int y, + const char* string, + grColor color ) + { + while (*string) + { + gr_charcell.buffer = (char*)font_8x8 + 8*(int)(unsigned char)*string++; + grBlitGlyphToBitmap( target, &gr_charcell, x, y, color ); + x += 8; + } + } + + static int gr_cursor_x = 0; + static int gr_cursor_y = 0; + static grBitmap* gr_text_bitmap = 0; + static int gr_margin_right = 0; + static int gr_margin_top = 0; + + extern void grGotobitmap( grBitmap* bitmap ) + { + gr_text_bitmap = bitmap; + } + + extern void grSetMargin( int right, int top ) + { + gr_margin_top = top << 3; + gr_margin_right = right << 3; + } + + extern void grGotoxy ( int x, int y ) + { + gr_cursor_x = x; + gr_cursor_y = y; + } + + extern void grWrite ( const char* string ) + { + if (string) + { + grWriteCellString( gr_text_bitmap, + gr_margin_right + (gr_cursor_x << 3), + gr_margin_top + (gr_cursor_y << 3), + string, + (grColor)127L ); + + gr_cursor_x += strlen(string); + } + } + + extern void grLn() + { + gr_cursor_y ++; + gr_cursor_x = 0; + } + + extern void grWriteln( const char* string ) + { + grWrite( string ); + grLn(); + } + + diff --git a/demos/graph/grfont.h b/demos/graph/grfont.h new file mode 100644 index 000000000..1456af2f3 --- /dev/null +++ b/demos/graph/grfont.h @@ -0,0 +1,16 @@ +#ifndef GRFONT_H +#define GRFONT_H + +#include "graph.h" + + extern const unsigned char font_8x8[]; + + extern void grGotobitmap( grBitmap* bitmap ); + extern void grSetMargin( int right, int top ); + extern void grGotoxy ( int x, int y ); + + extern void grWrite ( const char* string ); + extern void grWriteln( const char* string ); + extern void grLn(); + +#endif /* GRFONT_H */ diff --git a/demos/graph/grinit.c b/demos/graph/grinit.c new file mode 100644 index 000000000..223710689 --- /dev/null +++ b/demos/graph/grinit.c @@ -0,0 +1,78 @@ +#include "grobjs.h" +#include "grdevice.h" +#include + +#define GR_INIT_DEVICE_CHAIN ((grDeviceChain*)0) +#define GR_INIT_BUILD + +#ifdef DEVICE_X11 +#include "grx11.h" +#endif + +#ifdef DEVICE_OS2_PM +#include "gros2pm.h" +#endif + + + + /********************************************************************** + * + * + * grInitDevices + * + * + * This function is in charge of initialising all system-specific + * devices. A device is responsible for creating and managing one + * or more "surfaces". A surface is either a window or a screen, + * depending on the system. + * + * + * a pointer to the first element of a device chain. The chain can + * be parsed to find the available devices on the current system + * + * + * If a device cannot be initialised correctly, it is not part of + * the device chain returned by this function. For example, if an + * X11 device was compiled in the library, it will be part of + * the returned device chain only if a connection to the display + * could be establisged + * + * If no driver could be initialised, this function returns NULL. + * + **********************************************************************/ + + extern + grDeviceChain* grInitDevices( void ) + { + grDeviceChain* chain = GR_INIT_DEVICE_CHAIN; + grDeviceChain* cur = gr_device_chain; + + while (chain) + { + /* initialie the device */ + grDevice* device; + + device = chain->device; + if ( device->init() == 0 && + gr_num_devices < GR_MAX_DEVICES ) + + { + /* successful device initialisation - add it to our chain */ + cur->next = 0; + cur->device = device; + cur->name = device->device_name; + + if (cur > gr_device_chain) + cur[-1].next = cur; + + cur++; + gr_num_devices++; + } + chain = chain->next; + } + + return (gr_num_devices > 0 ? gr_device_chain : 0 ); + } + + + diff --git a/demos/graph/grobjs.c b/demos/graph/grobjs.c new file mode 100644 index 000000000..7ebdb270a --- /dev/null +++ b/demos/graph/grobjs.c @@ -0,0 +1,213 @@ +#include "grobjs.h" +#include + + + int grError = 0; + + + /******************************************************************** + * + * + * grRealloc + * + * + * Simple memory re-allocation. + * + * + * block :: original memory block address + * size :: new requested block size in bytes + * + * + * the memory block address. 0 in case of error + * + ********************************************************************/ + + char* grAlloc( long size ) + { + char* p; + + p = (char*)malloc(size); + if (!p && size > 0) + { + grError = gr_err_memory; + } + + if (p) + memset( p, 0, size ); + + return p; + } + + + /******************************************************************** + * + * + * grRealloc + * + * + * Simple memory re-allocation. + * + * + * block :: original memory block address + * size :: new requested block size in bytes + * + * + * the memory block address. 0 in case of error + * + ********************************************************************/ + + char* grRealloc( const char* block, long size ) + { + char* p; + + p = realloc( (char*)block, size ); + if (!p && size > 0) + { + grError = gr_err_memory; + } + return p; + } + + + /******************************************************************** + * + * + * grFree + * + * + * Simple memory release + * + * + * block :: target block + * + ********************************************************************/ + + void grFree( const void* block ) + { + if (block) + free( (char*)block ); + } + + + + static + int check_mode( grPixelMode pixel_mode, + int num_grays ) + { + if ( pixel_mode <= gr_pixel_mode_none || + pixel_mode >= gr_pixel_mode_max ) + goto Fail; + + if ( pixel_mode != gr_pixel_mode_gray || + ( num_grays >= 2 && num_grays < 256 ) ) + return 0; + + Fail: + grError = gr_err_bad_argument; + return grError; + } + + + /********************************************************************** + * + * + * grNewBitmap + * + * + * creates a new bitmap + * + * + * pixel_mode :: the target surface's pixel_mode + * num_grays :: number of grays levels for PAL8 pixel mode + * width :: width in pixels + * height :: height in pixels + * + * + * bit :: descriptor of the new bitmap + * + * + * Error code. 0 means success. + * + **********************************************************************/ + + extern int grNewBitmap( grPixelMode pixel_mode, + int num_grays, + int width, + int height, + grBitmap *bit ) + { + int pitch; + + /* check mode */ + if (check_mode(pixel_mode,num_grays)) + goto Fail; + + /* check dimensions */ + if (width < 0 || height < 0) + { + grError = gr_err_bad_argument; + goto Fail; + } + + bit->width = width; + bit->rows = height; + bit->mode = pixel_mode; + bit->grays = num_grays; + + pitch = width; + + switch (pixel_mode) + { + case gr_pixel_mode_mono : pitch = (width+7) >> 3; break; + case gr_pixel_mode_pal4 : pitch = (width+3) >> 2; break; + + case gr_pixel_mode_pal8 : + case gr_pixel_mode_gray : pitch = width; break; + + case gr_pixel_mode_rgb555: + case gr_pixel_mode_rgb565: pitch = width*2; break; + + case gr_pixel_mode_rgb24 : pitch = width*3; break; + + case gr_pixel_mode_rgb32 : pitch = width*4; break; + + default: + grError = gr_err_bad_target_depth; + return 0; + } + + bit->pitch = pitch; + bit->buffer = grAlloc( (long)bit->pitch * bit->rows ); + if (!bit->buffer) goto Fail; + + return 0; + + Fail: + return grError; + } + + /********************************************************************** + * + * + * grDoneBitmap + * + * + * destroys a bitmap + * + * + * bitmap :: handle to bitmap descriptor + * + * + * This function does NOT release the bitmap descriptor, only + * the pixel buffer. + * + **********************************************************************/ + + extern void grDoneBitmap( grBitmap* bit ) + { + grFree( bit->buffer ); + bit->buffer = 0; + } + + + diff --git a/demos/graph/grobjs.h b/demos/graph/grobjs.h new file mode 100644 index 000000000..79eb31d86 --- /dev/null +++ b/demos/graph/grobjs.h @@ -0,0 +1,186 @@ +/*************************************************************************** + * + * grobjs.h + * + * basic object classes defintions + * + * Copyright 1999 - The FreeType Development Team - www.freetype.org + * + * + * + * + ***************************************************************************/ + +#ifndef GROBJS_H +#define GROBJS_H + +#include "graph.h" +#include "grconfig.h" +#include "grtypes.h" + + + typedef struct grBiColor_ + { + grColor foreground; + grColor background; + + int num_levels; + int max_levels; + grColor* levels; + + } grBiColor; + + + + /********************************************************************** + * + * Technical note : explaining how the blitter works. + * + * The blitter is used to "draw" a given source bitmap into + * a given target bitmap. + * + * The function called 'compute_clips' is used to compute clipping + * constraints. These lead us to compute two areas : + * + * - the read area : is the rectangle, within the source bitmap, + * which will be effectively "drawn" in the + * target bitmap. + * + * - the write area : is the rectangle, within the target bitmap, + * which will effectively "receive" the pixels + * from the read area + * + * Note that both areas have the same dimensions, but are + * located in distinct surfaces. + * + * These areas are computed by 'compute_clips' which is called + * by each blitting function. + * + * Note that we use the Y-downwards convention within the blitter + * + **********************************************************************/ + + typedef struct grBlitter_ + { + int width; /* width in pixels of the areas */ + int height; /* height in pixels of the areas */ + + int xread; /* x position of start point in read area */ + int yread; /* y position of start point in read area */ + + int xwrite; /* x position of start point in write area */ + int ywrite; /* y position of start point in write area */ + + int right_clip; /* amount of right clip */ + + unsigned char* read; /* top left corner of read area in source map */ + unsigned char* write; /* top left corner of write area in target map */ + + int read_line; /* byte increment to go down one row in read area */ + int write_line; /* byte increment to go down one row in write area */ + + grBitmap source; /* source bitmap descriptor */ + grBitmap target; /* target bitmap descriptor */ + + } grBlitter; + + + + typedef void (*grBlitterFunc)( grBlitter* blitter, + grColor color ); + + typedef void (*grSetTitleFunc)( grSurface* surface, + const char* title_string ); + + typedef void (*grRefreshRectFunc)( grSurface* surface, + int x, + int y, + int width, + int height ); + + typedef void (*grDoneSurfaceFunc)( grSurface* surface ); + + typedef int (*grListenEventFunc)( grSurface* surface, + int event_mode, + grEvent *event ); + + + + struct grSurface_ + { + grDevice* device; + grBitmap bitmap; + grBool refresh; + grBool owner; + + const byte* saturation; /* used for gray surfaces only */ + grBlitterFunc blit_mono; /* 0 by default, set by grBlit.. */ + + grRefreshRectFunc refresh_rect; + grSetTitleFunc set_title; + grListenEventFunc listen_event; + grDoneSurfaceFunc done; + }; + + + + /******************************************************************** + * + * + * grAlloc + * + * + * Simple memory allocation. The returned block is always zero-ed + * + * + * size :: size in bytes of the requested block + * + * + * the memory block address. 0 in case of error + * + ********************************************************************/ + + extern char* grAlloc( long size ); + + + /******************************************************************** + * + * + * grRealloc + * + * + * Simple memory re-allocation. + * + * + * block :: original memory block address + * size :: new requested block size in bytes + * + * + * the memory block address. 0 in case of error + * + ********************************************************************/ + + extern char* grRealloc( const char* block, long size ); + + + /******************************************************************** + * + * + * grFree + * + * + * Simple memory release + * + * + * block :: target block + * + ********************************************************************/ + + extern void grFree( const void* block ); + + + extern grDevice* gr_devices[]; + extern int gr_num_devices; + extern int gr_max_devices; + +#endif /* GROBJS_H */ diff --git a/demos/graph/gros2pm.c b/demos/graph/gros2pm.c new file mode 100644 index 000000000..e7a63ce72 --- /dev/null +++ b/demos/graph/gros2pm.c @@ -0,0 +1,895 @@ +#include "gros2pm.h" + + +#define INCL_DOS +#define INCL_WIN +#define INCL_GPI +#define INCL_SUB + +#include +#include +#include +#include + + + static void Panic( const char* message ) + { + fprintf( stderr, "%s", message ); + exit(1); + } + + typedef struct Translator + { + ULONG os2key; + grKey grkey; + + } Translator; + + + static + Translator key_translators[] = + { + { VK_BACKSPACE, grKeyBackSpace }, + { VK_TAB, grKeyTab }, + { VK_ENTER, grKeyReturn }, + { VK_ESC, grKeyEsc }, + { VK_HOME, grKeyHome }, + { VK_LEFT, grKeyLeft }, + { VK_UP, grKeyUp }, + { VK_RIGHT, grKeyRight }, + { VK_DOWN, grKeyDown }, + { VK_PAGEUP, grKeyPageUp }, + { VK_PAGEDOWN, grKeyPageDown }, + { VK_END, grKeyEnd }, + { VK_F1, grKeyF1 }, + { VK_F2, grKeyF2 }, + { VK_F3, grKeyF3 }, + { VK_F4, grKeyF4 }, + { VK_F5, grKeyF5 }, + { VK_F6, grKeyF6 }, + { VK_F7, grKeyF7 }, + { VK_F8, grKeyF8 }, + { VK_F9, grKeyF9 }, + { VK_F10, grKeyF10 }, + { VK_F11, grKeyF11 }, + { VK_F12, grKeyF12 } + }; + + +#define MAX_PIXEL_MODES 32 + + static int num_pixel_modes = 0; + static grPixelMode pixel_modes[ MAX_PIXEL_MODES ]; + static int pixel_depth[ MAX_PIXEL_MODES ]; + + static HAB gr_anchor; /* device anchor block */ + + typedef POINTL PMBlitPoints[4]; + + + typedef struct grPMSurface_ + { + grSurface root; + grBitmap image; + + HAB anchor; /* handle to anchor block for surface's window */ + HWND frame_window; /* handle to window's frame */ + HWND client_window; /* handle to window's client */ + HWND title_window; /* handle to window's title bar */ + + HPS image_ps; /* memory presentation space used to hold */ + /* the surface's content under PM */ + HDC image_dc; /* memory device context for the image */ + + HEV event_lock; /* semaphore used in listen_surface */ + HMTX image_lock; /* a mutex used to synchronise access */ + /* to the memory presentation space */ + /* used to hold the surface */ + + TID message_thread; /* thread used to process this surface's */ + /* messages.. */ + + PBITMAPINFO2 bitmap_header;/* os/2 bitmap descriptor */ + HBITMAP os2_bitmap; /* Handle to OS/2 bitmap contained in image */ + BOOL ready; /* ??? */ + + long shades[256]; /* indices of gray levels in pixel_mode_gray */ + + POINTL surface_blit[4]; /* surface blitting table */ + POINTL magnify_blit[4]; /* magnifier blitting table */ + int magnification; /* level of magnification */ + POINTL magnify_center; + SIZEL magnify_size; + + grEvent event; + + PMBlitPoints blit_points; + + } grPMSurface; + + + + static + void enable_os2_iostreams( void ) + { + PTIB thread_block; + PPIB process_block; + + /* XXX : This is a very nasty hack, it fools OS/2 and let the program */ + /* call PM functions, even though stdin/stdout/stderr are still */ + /* directed to the standard i/o streams.. */ + /* The program must be compiled with WINDOWCOMPAT */ + /* */ + /* Credits go to Michal for finding this !! */ + /* */ + DosGetInfoBlocks( &thread_block, &process_block ); + process_block->pib_ultype = 3; + } + + + + static + int init_device( void ) + { + enable_os2_iostreams(); + + /* create an anchor block. This will allow this thread (i.e. the */ + /* main one) to call Gpi functions.. */ + gr_anchor = WinInitialize(0); + if (!gr_anchor) + { + /* could not initialise Presentation Manager */ + return -1; + } + + return 0; + } + + + + static + void done_device( void ) + { + /* Indicates that we do not use the Presentation Manager, this */ + /* will also release all associated resources.. */ + WinTerminate( gr_anchor ); + } + + + + /* close a given window */ + static + void done_surface( grPMSurface* surface ) + { + if ( surface->frame_window ) + WinDestroyWindow( surface->frame_window ); + + WinReleasePS( surface->image_ps ); + + grDoneBitmap( &surface->image ); + grDoneBitmap( &surface->root.bitmap ); + } + + + + + + static + void add_pixel_mode( grPixelMode pixel_mode, + int depth ) + { + if ( num_pixel_modes >= MAX_PIXEL_MODES ) + Panic( "X11.Too many pixel modes\n" ); + + pixel_modes[ num_pixel_modes ] = pixel_mode; + pixel_depth[ num_pixel_modes ] = depth; + + num_pixel_modes++; + } + + +#define LOCK(x) DosRequestMutexSem( x, SEM_INDEFINITE_WAIT ); +#define UNLOCK(x) DosReleaseMutexSem( x ) + + + static + const int pixel_mode_bit_count[] = + { + 0, + 1, + 4, + 8, /* pal8 */ + 8, /* gray */ + 15, + 16, + 24, + 32 + }; + + + /************************************************************************ + * + * Technical note : how the OS/2 Presntation Manager driver works + * + * PM is, in my opinion, a bloated and over-engineered graphics + * sub-system, even though it has lots of nice features. Here are + * a few tidbits about it : + * + * + * - under PM, a "bitmap" is a device-specific object whose bits are + * not directly accessible to the client application. This means + * that we must use a scheme like the following to display our + * surfaces : + * + * - hold, for each surface, its own bitmap buffer where the + * rest of MiGS writes directly. + * + * - create a PM bitmap object with the same dimensions (and + * possibly format). + * + * - copy the content of each updated rectangle into the + * PM bitmap with the function 'GpiSetBitmapBits'. + * + * - finally, "blit" the PM bitmap to the screen calling + * 'GpiBlitBlt' + * + * - but there is more : you cannot directly blit a PM bitmap to the + * screen with PM. The 'GpiBlitBlt' only works with presentation + * spaces. This means that we also need to create, for each surface : + * + * - a memory presentation space, used to hold the PM bitmap + * - a "memory device context" for the presentation space + * + * The blit is then performed from the memory presentation space + * to the screen's presentation space.. + * + * + * - because each surface creates its own event-handling thread, + * we must protect the surface's presentation space from concurrent + * accesses (i.e. calls to 'GpiSetBitmapBits' when drawing to the + * surface, and calls to 'GpiBlitBlt' when drawing it on the screen + * are performed in two different threads). + * + * we use a simple mutex to do this. + * + * + * - we also use a semaphore to perform a rendez-vous between the + * main and event-handling threads (needed in "listen_event"). + * + ************************************************************************/ + + static + void RunPMWindow( grPMSurface* surface ); + + + + + + + + + + + + + static + void convert_gray_to_pal8( grPMSurface* surface, + int x, + int y, + int w, + int h ) + { + grBitmap* target = &surface->image; + grBitmap* source = &surface->root.bitmap; + byte* write = (byte*)target->buffer + y*target->pitch + x; + byte* read = (byte*)source->buffer + y*source->pitch + x; + long* palette = surface->shades; + + while (h > 0) + { + byte* _write = write; + byte* _read = read; + byte* limit = _write + w; + + for ( ; _write < limit; _write++, _read++ ) + *_write = (byte) palette[ *_read ]; + + write += target->pitch; + read += source->pitch; + h--; + } + } + + + static + void convert_gray_to_16( grPMSurface* surface, + int x, + int y, + int w, + int h ) + { + grBitmap* target = &surface->image; + grBitmap* source = &surface->root.bitmap; + byte* write = (byte*)target->buffer + y*target->pitch + 2*x; + byte* read = (byte*)source->buffer + y*source->pitch + x; + long* palette = surface->shades; + + while (h > 0) + { + byte* _write = write; + byte* _read = read; + byte* limit = _write + 2*w; + + for ( ; _write < limit; _write += 2, _read++ ) + *(short*)_write = (short)palette[ *_read ]; + + write += target->pitch; + read += source->pitch; + h--; + } + } + + + static + void convert_gray_to_24( grPMSurface* surface, + int x, + int y, + int w, + int h ) + { + grBitmap* target = &surface->image; + grBitmap* source = &surface->root.bitmap; + byte* write = (byte*)target->buffer + y*target->pitch + 3*x; + byte* read = (byte*)source->buffer + y*source->pitch + x; + + while (h > 0) + { + byte* _write = write; + byte* _read = read; + byte* limit = _write + 3*w; + + for ( ; _write < limit; _write += 3, _read++ ) + { + byte color = *_read; + + _write[0] = + _write[1] = + _write[2] = color; + } + + write += target->pitch; + read += source->pitch; + h--; + } + } + + + static + void convert_gray_to_32( grPMSurface* surface, + int x, + int y, + int w, + int h ) + { + grBitmap* target = &surface->image; + grBitmap* source = &surface->root.bitmap; + byte* write = (byte*)target->buffer + y*target->pitch + 4*x; + byte* read = (byte*)source->buffer + y*source->pitch + x; + + while (h > 0) + { + byte* _write = write; + byte* _read = read; + byte* limit = _write + 4*w; + + for ( ; _write < limit; _write += 4, _read++ ) + { + byte color = *_read; + + _write[0] = + _write[1] = + _write[2] = + _write[3] = color; + } + + write += target->pitch; + read += source->pitch; + h--; + } + } + + + static + void convert_rectangle( grPMSurface* surface, + int x, + int y, + int w, + int h ) + { + int z; + + /* first of all, clip to the surface's area */ + if ( x >= surface->image.width || + x+w <= 0 || + y >= surface->image.rows || + y+h <= 0 ) + return; + + if ( x < 0 ) + { + w += x; + x = 0; + } + + z = (x + w) - surface->image.width; + if (z > 0) + w -= z; + + z = (y + h) - surface->image.rows; + if (z > 0) + h -= z; + + /* convert the rectangle to the target depth for gray surfaces */ + if (surface->root.bitmap.mode == gr_pixel_mode_gray) + { + switch (surface->image.mode) + { + case gr_pixel_mode_pal8 : + convert_gray_to_pal8( surface, x, y, w, h ); + break; + + case gr_pixel_mode_rgb555: + case gr_pixel_mode_rgb565: + convert_gray_to_16 ( surface, x, y, w, h ); + break; + + case gr_pixel_mode_rgb24: + convert_gray_to_24 ( surface, x, y, w, h ); + break; + + case gr_pixel_mode_rgb32: + convert_gray_to_32 ( surface, x, y, w, h ); + break; + + default: + ; + } + } + } + + + static + void refresh_rectangle( grPMSurface* surface, + int x, + int y, + int w, + int h ) + { + convert_rectangle( surface, x, y, w, h ); + + WinInvalidateRect( surface->client_window, NULL, FALSE ); + WinUpdateWindow( surface->frame_window ); + } + + + static + void set_title( grPMSurface* surface, + const char* title ) + { + WinSetWindowText( surface->title_window, (PSZ)title ); + } + + + + static + void listen_event( grPMSurface* surface, + int event_mask, + grEvent* grevent ) + { + ULONG ulRequestCount; + + (void) event_mask; /* ignored for now */ + + /* the listen_event function blocks until there is an event to process */ + DosWaitEventSem( surface->event_lock, SEM_INDEFINITE_WAIT ); + DosQueryEventSem( surface->event_lock, &ulRequestCount ); + *grevent = surface->event; + DosResetEventSem( surface->event_lock, &ulRequestCount ); + + return; + } + + + static + int init_surface( grPMSurface* surface, + grBitmap* bitmap ) + { + PBITMAPINFO2 bit; + SIZEL sizl = { 0, 0 }; + LONG palette[256]; + + /* create the bitmap - under OS/2, we support all modes as PM */ + /* handles all conversions automatically.. */ + if ( grNewBitmap( surface->root.bitmap.mode, + surface->root.bitmap.grays, + surface->root.bitmap.width, + surface->root.bitmap.rows, + bitmap ) ) + return grError; + + surface->root.bitmap = *bitmap; + + /* create the image and event lock */ + DosCreateEventSem( NULL, &surface->event_lock, 0, TRUE ); + DosCreateMutexSem( NULL, &surface->image_lock, 0, FALSE ); + + /* create the image's presentation space */ + surface->image_dc = DevOpenDC( gr_anchor, + OD_MEMORY, (PSZ)"*", 0L, 0L, 0L ); + + surface->image_ps = GpiCreatePS( gr_anchor, + surface->image_dc, + &sizl, + PU_PELS | GPIT_MICRO | + GPIA_ASSOC | GPIF_DEFAULT ); + + GpiSetBackMix( surface->image_ps, BM_OVERPAINT ); + + /* create the image's PM bitmap */ + bit = (PBITMAPINFO2)grAlloc( sizeof(BITMAPINFO2) + 256*sizeof(RGB2) ); + surface->bitmap_header = bit; + + bit->cbFix = sizeof( BITMAPINFOHEADER2 ); + bit->cx = surface->root.bitmap.width; + bit->cy = surface->root.bitmap.rows; + bit->cPlanes = 1; + + bit->argbColor[0].bBlue = 0; + bit->argbColor[0].bGreen = 0; + bit->argbColor[0].bRed = 0; + + bit->argbColor[1].bBlue = 255; + bit->argbColor[1].bGreen = 255; + bit->argbColor[1].bRed = 255; + + bit->cBitCount = pixel_mode_bit_count[ surface->root.bitmap.mode ]; + + surface->os2_bitmap = GpiCreateBitmap( surface->image_ps, + (PBITMAPINFOHEADER2)bit, + 0L, NULL, NULL ); + + GpiSetBitmap( surface->image_ps, surface->os2_bitmap ); + + bit->cbFix = sizeof( BITMAPINFOHEADER2 ); + GpiQueryBitmapInfoHeader( surface->os2_bitmap, + (PBITMAPINFOHEADER2)bit ); + + /* for gr_pixel_mode_gray, create a gray-levels logical palette */ + if ( bitmap->mode == gr_pixel_mode_gray ) + { + int x, count; + + count = bitmap->grays; + for ( x = 0; x < count; x++ ) + palette[x] = (((count-x)*255)/count) * 0x010101; + + /* create logical color table */ + GpiCreateLogColorTable( surface->image_ps, + (ULONG) LCOL_PURECOLOR, + (LONG) LCOLF_CONSECRGB, + (LONG) 0L, + (LONG) count, + (PLONG) palette ); + + /* now, copy the color indexes to surface->shades */ + for ( x = 0; x < count; x++ ) + surface->shades[x] = GpiQueryColorIndex( surface->image_ps, + 0, palette[x] ); + } + + /* set up the blit points array */ + surface->blit_points[1].x = surface->root.bitmap.width; + surface->blit_points[1].y = surface->root.bitmap.rows; + surface->blit_points[3] = surface->blit_points[1]; + + /* Finally, create the event handling thread for the surface's window */ + DosCreateThread( &surface->message_thread, + (PFNTHREAD) RunPMWindow, + (ULONG) surface, + 0UL, + 32920 ); + + surface->root.done = (grDoneSurfaceFunc) done_surface; + surface->root.refresh_rect = (grRefreshRectFunc) refresh_rectangle; + surface->root.set_title = (grSetTitleFunc) set_title; + surface->root.listen_event = (grListenEventFunc) listen_event; + + convert_rectangle( surface, 0, 0, bitmap->width, bitmap->rows ); + return 0; + } + + + + MRESULT EXPENTRY Message_Process( HWND handle, + ULONG mess, + MPARAM parm1, + MPARAM parm2 ); + + + static + void RunPMWindow( grPMSurface* surface ) + { + unsigned char class_name[] = "DisplayClass"; + ULONG class_flags; + + static HMQ queue; + QMSG message; + + /* create an anchor to allow this thread to use PM */ + surface->anchor = WinInitialize(0); + if (!surface->anchor) + { + printf( "Error doing WinInitialize()\n" ); + return; + } + + /* create a message queue */ + queue = WinCreateMsgQueue( surface->anchor, 0 ); + if (!queue) + { + printf( "Error doing >inCreateMsgQueue()\n" ); + return; + } + + /* register the window class */ + if ( !WinRegisterClass( surface->anchor, + (PSZ) class_name, + (PFNWP) Message_Process, + CS_SIZEREDRAW, + 0 ) ) + { + printf( "Error doing WinRegisterClass()\n" ); + return; + } + + /* create the PM window */ + class_flags = FCF_TITLEBAR | FCF_MINBUTTON | FCF_DLGBORDER | + FCF_TASKLIST | FCF_SYSMENU; + + surface->frame_window = WinCreateStdWindow( + HWND_DESKTOP, + WS_VISIBLE, + &class_flags, + (PSZ) class_name, + (PSZ) "FreeType PM Graphics", + WS_VISIBLE, + 0, 0, + &surface->client_window ); + if (!surface->frame_window) + { + printf( "Error doing WinCreateStdWindow()\n" ); + return; + } + + /* find the title window handle */ + surface->title_window = WinWindowFromID( surface->frame_window, + FID_TITLEBAR ); + + /* set Window size and position */ + WinSetWindowPos( surface->frame_window, + 0L, + (SHORT) 60, + (SHORT) WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN ) - + surface->root.bitmap.rows + 100, + + (SHORT) WinQuerySysValue( HWND_DESKTOP, SV_CYDLGFRAME )*2 + + surface->root.bitmap.width, + + (SHORT) WinQuerySysValue( HWND_DESKTOP, SV_CYTITLEBAR ) + + WinQuerySysValue( HWND_DESKTOP, SV_CYDLGFRAME )*2 + + surface->root.bitmap.rows, + + SWP_SIZE | SWP_MOVE ); + + /* save the handle to the current surface within the window words */ + WinSetWindowPtr( surface->frame_window,QWL_USER, surface ); + + /* run the message queue till the end */ + while ( WinGetMsg( surface->anchor, &message, (HWND)NULL, 0, 0 ) ) + WinDispatchMsg( surface->anchor, &message ); + + /* clean-up */ + WinDestroyWindow( surface->frame_window ); + surface->frame_window = 0; + + WinDestroyMsgQueue( queue ); + WinTerminate( surface->anchor ); + + /* await death... */ + while ( 1 ) + DosSleep( 100 ); + } + + + + + /* Message processing for our PM Window class */ + MRESULT EXPENTRY Message_Process( HWND handle, + ULONG mess, + MPARAM parm1, + MPARAM parm2 ) + { + static HDC screen_dc; + static HPS screen_ps; + static BOOL minimized; + + SIZEL sizl; + SWP swp; + + grPMSurface* surface; + + /* get the handle to the window's surface */ + surface = (grPMSurface*)WinQueryWindowPtr( handle, QWL_USER ); + + switch( mess ) + { + case WM_DESTROY: + /* warn the main thread to quit if it didn't know */ + surface->event.type = gr_event_key; + surface->event.key = grKeyEsc; + DosPostEventSem( surface->event_lock ); + break; + + case WM_CREATE: + /* set original magnification */ + minimized = FALSE; + + /* create Device Context and Presentation Space for screen. */ + screen_dc = WinOpenWindowDC( handle ); + screen_ps = GpiCreatePS( surface->anchor, + screen_dc, + &sizl, + PU_PELS | GPIT_MICRO | + GPIA_ASSOC | GPIF_DEFAULT ); + + /* take the input focus */ + WinFocusChange( HWND_DESKTOP, handle, 0L ); + break; + + case WM_MINMAXFRAME: + /* to update minimized if changed */ + swp = *((PSWP) parm1); + if ( swp.fl & SWP_MINIMIZE ) + minimized = TRUE; + if ( swp.fl & SWP_RESTORE ) + minimized = FALSE; + return WinDefWindowProc( handle, mess, parm1, parm2 ); + break; + + case WM_ERASEBACKGROUND: + case WM_PAINT: + /* copy the memory image of the screen out to the real screen */ + DosRequestMutexSem( surface->image_lock, SEM_INDEFINITE_WAIT ); + WinBeginPaint( handle, screen_ps, NULL ); + + /* main image and magnified picture */ + GpiBitBlt( screen_ps, + surface->image_ps, + 4L, + surface->blit_points, + ROP_SRCCOPY, BBO_AND ); + + WinEndPaint( screen_ps ); + DosReleaseMutexSem( surface->image_lock ); + break; + + case WM_CHAR: + if ( CHARMSG( &mess )->fs & KC_KEYUP ) + break; + + /* look for a specific vkey */ + { + int count = sizeof( key_translators )/sizeof( key_translators[0] ); + Translator* trans = key_translators; + Translator* limit = trans + count; + + for ( ; trans < limit; trans++ ) + if ( CHARMSG(&mess)->vkey == trans->os2key ) + { + surface->event.key = trans->grkey; + goto Do_Key_Event; + } + } + + /* otherwise, simply record the character code */ + if ( (CHARMSG( &mess )->fs & KC_CHAR) == 0 ) + break; + + surface->event.key = CHARMSG(&mess)->chr; + + Do_Key_Event: + surface->event.type = gr_event_key; + DosPostEventSem( surface->event_lock ); + break; + + default: + return WinDefWindowProc( handle, mess, parm1, parm2 ); + } + + return (MRESULT) FALSE; + } + + + + + + + +#if 0 + static + grKey KeySymTogrKey( key ) + { + grKey k; + int count = sizeof(key_translators)/sizeof(key_translators[0]); + Translator* trans = key_translators; + Translator* limit = trans + count; + + k = grKeyNone; + + while ( trans < limit ) + { + if ( trans->xkey == key ) + { + k = trans->grkey; + break; + } + trans++; + } + + return k; + } + + + + static + void listen_event( grPMSurface* surface, + int event_mask, + grEvent* grevent ) + { + grKey grkey; + + /* XXXX : For now, ignore the event mask, and only exit when */ + /* a key is pressed.. */ + (void)event_mask; + + + /* Now, translate the keypress to a grKey */ + /* If this wasn't part of the simple translated keys, simply get the charcode */ + /* from the character buffer */ + grkey = grKEY(key_buffer[key_cursor++]); + + Set_Key: + grevent->type = gr_key_down; + grevent->key = grkey; + } + +#endif + + + + grDevice gr_os2pm_device = + { + sizeof( grPMSurface ), + "os2pm", + + init_device, + done_device, + + (grDeviceInitSurfaceFunc) init_surface, + + 0, + 0 + + }; + + diff --git a/demos/graph/gros2pm.h b/demos/graph/gros2pm.h new file mode 100644 index 000000000..229358025 --- /dev/null +++ b/demos/graph/gros2pm.h @@ -0,0 +1,23 @@ +#ifndef GROS2PM_H +#define GROS2PM_H + +#include "grobjs.h" + + extern + grDevice gr_os2pm_device; + +#ifdef GR_INIT_BUILD + static + grDeviceChain gr_os2pm_device_chain = + { + "os2pm", + &gr_os2pm_device, + GR_INIT_DEVICE_CHAIN + }; + +#undef GR_INIT_DEVICE_CHAIN +#define GR_INIT_DEVICE_CHAIN &gr_os2pm_device_chain + +#endif /* GR_INIT_BUILD */ + +#endif /* GROS2PM_H */ diff --git a/demos/graph/grtypes.h b/demos/graph/grtypes.h new file mode 100644 index 000000000..aca1856be --- /dev/null +++ b/demos/graph/grtypes.h @@ -0,0 +1,52 @@ +/*************************************************************************** + * + * grtypes.h + * + * basic type defintions + * + * Copyright 1999 - The FreeType Development Team - www.freetype.org + * + * + * + * + ***************************************************************************/ + +#ifndef GRTYPES_H +#define GRTYPES_H + + typedef unsigned char byte; + +#if 0 + typedef signed char uchar; + + typedef unsigned long ulong; + typedef unsigned short ushort; + typedef unsigned int uint; +#endif + + typedef struct grDimension_ + { + int x; + int y; + + } grDimension; + +#define gr_err_ok 0 +#define gr_err_memory -1 +#define gr_err_bad_argument -2 +#define gr_err_bad_target_depth -3 +#define gr_err_bad_source_depth -4 +#define gr_err_saturation_overflow -5 +#define gr_err_conversion_overflow -6 +#define gr_err_invalid_device -7 + + +#ifdef GR_MAKE_OPTION_SINGLE_OBJECT +#define GR_LOCAL_DECL static +#define GR_LOCAL_FUNC static +#else +#define GR_LOCAL_DECL extern +#define GR_LOCAL_FUNC /* void */ +#endif + +#endif /* GRTYPES_H */ diff --git a/demos/graph/grx11.c b/demos/graph/grx11.c new file mode 100644 index 000000000..99d853868 --- /dev/null +++ b/demos/graph/grx11.c @@ -0,0 +1,936 @@ +#include "grx11.h" + + +#ifdef TEST +#include "grfont.h" +#endif + +#include +#include +#include +#include +#include +#include +#include + + static void Panic( const char* message ) + { + fprintf( stderr, "%s", message ); + exit(1); + } + + typedef struct Translator + { + KeySym xkey; + grKey grkey; + + } Translator; + + static + Translator key_translators[] = + { + { XK_BackSpace, grKeyBackSpace }, + { XK_Tab, grKeyTab }, + { XK_Return, grKeyReturn }, + { XK_Escape, grKeyEsc }, + { XK_Home, grKeyHome }, + { XK_Left, grKeyLeft }, + { XK_Up, grKeyUp }, + { XK_Right, grKeyRight }, + { XK_Down, grKeyDown }, + { XK_Page_Up, grKeyPageUp }, + { XK_Page_Down, grKeyPageDown }, + { XK_End, grKeyEnd }, + { XK_Begin, grKeyHome }, + { XK_F1, grKeyF1 }, + { XK_F2, grKeyF2 }, + { XK_F3, grKeyF3 }, + { XK_F4, grKeyF4 }, + { XK_F5, grKeyF5 }, + { XK_F6, grKeyF6 }, + { XK_F7, grKeyF7 }, + { XK_F8, grKeyF8 }, + { XK_F9, grKeyF9 }, + { XK_F10, grKeyF10 }, + { XK_F11, grKeyF11 }, + { XK_F12, grKeyF12 } + }; + + +#ifdef TEST + +#define grAlloc malloc + +#endif + + + static Display* display; + static char* displayname = ""; + + static Cursor idle; + static Cursor busy; + +#define MAX_PIXEL_MODES 32 + + typedef XPixmapFormatValues XDepth; + + static int num_pixel_modes = 0; + static grPixelMode pixel_modes[ MAX_PIXEL_MODES ]; + static XDepth pixel_depth[ MAX_PIXEL_MODES ]; + + typedef struct grXSurface_ + { + grSurface root; + grBitmap image; + + Window win; + Visual* visual; + Colormap colormap; + int depth; + Bool gray; + + GC gc; + + XColor color[256]; /* gray levels palette for 8-bit modes */ + XImage* ximage; + + int win_org_x; + int win_org_y; + int win_width; + int win_height; + + int image_width; + int image_height; + + } grXSurface; + + + + + /* close a given window */ + static + void done_surface( grXSurface* surface ) + { + XUnmapWindow( display, surface->win ); + } + + + + /* close the device, i.e. the display connection */ + static + void done_device( void ) + { + XCloseDisplay( display ); + } + + + + static + void add_pixel_mode( grPixelMode pixel_mode, + XDepth* depth ) + { + if ( num_pixel_modes >= MAX_PIXEL_MODES ) + Panic( "X11.Too many pixel modes\n" ); + + pixel_modes[ num_pixel_modes ] = pixel_mode; + pixel_depth[ num_pixel_modes ] = *depth; + + num_pixel_modes++; + } + + + + static + int init_device( void ) + { + XDepth dummy; + + XrmInitialize(); + + display = XOpenDisplay( displayname ); + if (!display) + { + return -1; + /* Panic( "Gr:error: cannot open X11 display\n" ); */ + } + + idle = XCreateFontCursor( display, XC_left_ptr ); + busy = XCreateFontCursor( display, XC_watch ); + + num_pixel_modes = 0; + + /* always enable the 8-bit gray levels pixel mode */ + /* even if its display is emulated through a constrained palette */ + /* or another color mode */ + dummy.depth = 8; + dummy.bits_per_pixel = 8; + dummy.scanline_pad = 8; + add_pixel_mode( gr_pixel_mode_gray, &dummy ); + + { + int count; + XDepth* format; + XDepth* formats; + XVisualInfo template; + + formats = XListPixmapFormats( display, &count ); + format = formats; + +#ifdef TEST + printf( "available pixmap formats\n" ); + printf( "depth pixbits scanpad\n" ); +#endif + + while ( count-- > 0 ) + { +#ifdef TEST + printf( " %3d %3d %3d\n", + format->depth, + format->bits_per_pixel, + format->scanline_pad ); +#endif + + if ( format->depth == 1 ) + /* usually, this should be the first format */ + add_pixel_mode( gr_pixel_mode_mono, format ); + + else if ( format->depth == 8 ) + add_pixel_mode( gr_pixel_mode_pal8, format ); + + /* note, the 32-bit modes return a depth of 24, and 32 bits per pixel */ + else if ( format->depth == 24 ) + { + if ( format->bits_per_pixel == 24 ) + add_pixel_mode( gr_pixel_mode_rgb24, format ); + + else if ( format->bits_per_pixel == 32 ) + add_pixel_mode( gr_pixel_mode_rgb32, format ); + } + + else if ( format->depth == 16 ) + { + int count2; + XVisualInfo* visuals; + XVisualInfo* visual; + + template.depth = format->depth; + visuals = XGetVisualInfo( display, + VisualDepthMask, + &template, + &count2 ); + visual = visuals; + + while ( count2-- > 0 ) + { +#ifdef TEST + const char* string = "unknown"; + + switch (visual->class) + { + case TrueColor: string = "TrueColor"; break; + case DirectColor: string = "DirectColor"; break; + case PseudoColor: string = "PseudoColor"; break; + case StaticGray : string = "StaticGray"; break; + case StaticColor: string = "StaticColor"; break; + case GrayScale: string = "GrayScale"; break; + } + + printf( "> RGB %02x:%02x:%02x, colors %3d, bits %2d %s\n", + visual->red_mask, + visual->green_mask, + visual->blue_mask, + visual->colormap_size, + visual->bits_per_rgb, + string ); +#endif + if ( visual->red_mask == 0xf800 && + visual->green_mask == 0x07e0 && + visual->blue_mask == 0x001f ) + add_pixel_mode( gr_pixel_mode_rgb565, format ); + + else if ( visual->red_mask == 0x7c00 && + visual->green_mask == 0x03e0 && + visual->blue_mask == 0x001f ) + add_pixel_mode( gr_pixel_mode_rgb555, format ); + + /* other 16-bit modes are ignored */ + visual++; + } + + XFree( visuals ); + } + + format++; + } + + XFree( formats ); + } + + gr_x11_device.num_pixel_modes = num_pixel_modes; + gr_x11_device.pixel_modes = pixel_modes; + + return 0; + } + + + + + + + + + + + + + static + void convert_gray_to_pal8( grXSurface* surface, + int x, + int y, + int w, + int h ) + { + grBitmap* target = &surface->image; + grBitmap* source = &surface->root.bitmap; + byte* write = (byte*)target->buffer + y*target->pitch + x; + byte* read = (byte*)source->buffer + y*source->pitch + x; + XColor* palette = surface->color; + + while (h > 0) + { + byte* _write = write; + byte* _read = read; + byte* limit = _write + w; + + for ( ; _write < limit; _write++, _read++ ) + *_write = (byte) palette[ *_read ].pixel; + + write += target->pitch; + read += source->pitch; + h--; + } + } + + + static + void convert_gray_to_16( grXSurface* surface, + int x, + int y, + int w, + int h ) + { + grBitmap* target = &surface->image; + grBitmap* source = &surface->root.bitmap; + byte* write = (byte*)target->buffer + y*target->pitch + 2*x; + byte* read = (byte*)source->buffer + y*source->pitch + x; + XColor* palette = surface->color; + + while (h > 0) + { + byte* _write = write; + byte* _read = read; + byte* limit = _write + 2*w; + + for ( ; _write < limit; _write += 2, _read++ ) + *(short*)_write = (short)palette[ *_read ].pixel; + + write += target->pitch; + read += source->pitch; + h--; + } + } + + + static + void convert_gray_to_24( grXSurface* surface, + int x, + int y, + int w, + int h ) + { + grBitmap* target = &surface->image; + grBitmap* source = &surface->root.bitmap; + byte* write = (byte*)target->buffer + y*target->pitch + 3*x; + byte* read = (byte*)source->buffer + y*source->pitch + x; + + while (h > 0) + { + byte* _write = write; + byte* _read = read; + byte* limit = _write + 3*w; + + for ( ; _write < limit; _write += 3, _read++ ) + { + byte color = *_read; + + _write[0] = + _write[1] = + _write[2] = color; + } + + write += target->pitch; + read += source->pitch; + h--; + } + } + + + static + void convert_gray_to_32( grXSurface* surface, + int x, + int y, + int w, + int h ) + { + grBitmap* target = &surface->image; + grBitmap* source = &surface->root.bitmap; + byte* write = (byte*)target->buffer + y*target->pitch + 4*x; + byte* read = (byte*)source->buffer + y*source->pitch + x; + + while (h > 0) + { + byte* _write = write; + byte* _read = read; + byte* limit = _write + 4*w; + + for ( ; _write < limit; _write += 4, _read++ ) + { + byte color = *_read; + + _write[0] = + _write[1] = + _write[2] = + _write[3] = color; + } + + write += target->pitch; + read += source->pitch; + h--; + } + } + + + static + void convert_rectangle( grXSurface* surface, + int x, + int y, + int w, + int h ) + { + int z; + + /* first of all, clip to the surface's area */ + if ( x >= surface->image.width || + x+w <= 0 || + y >= surface->image.rows || + y+h <= 0 ) + return; + + if ( x < 0 ) + { + w += x; + x = 0; + } + + z = (x + w) - surface->image.width; + if (z > 0) + w -= z; + + z = (y + h) - surface->image.rows; + if (z > 0) + h -= z; + + /* convert the rectangle to the target depth for gray surfaces */ + if (surface->gray) + { + switch (surface->depth) + { + case 8 : convert_gray_to_pal8( surface, x, y, w, h ); break; + case 16: convert_gray_to_16 ( surface, x, y, w, h ); break; + case 24: convert_gray_to_24 ( surface, x, y, w, h ); break; + case 32: convert_gray_to_32 ( surface, x, y, w, h ); break; + } + } + } + + + static + void refresh_rectangle( grXSurface* surface, + int x, + int y, + int w, + int h ) + { + if (surface->gray) + convert_rectangle( surface, x, y, w, h ); + + XPutImage( display, + surface->win, + surface->gc, + surface->ximage, + x, y, x, y, w, h ); + } + + + static + void set_title( grXSurface* surface, + const char* title ) + { + XStoreName( display, surface->win, title ); + } + + + + static + grKey KeySymTogrKey( KeySym key ) + { + grKey k; + int count = sizeof(key_translators)/sizeof(key_translators[0]); + Translator* trans = key_translators; + Translator* limit = trans + count; + + k = grKeyNone; + + while ( trans < limit ) + { + if ( trans->xkey == key ) + { + k = trans->grkey; + break; + } + trans++; + } + + return k; + } + + + + static + void listen_event( grXSurface* surface, + int event_mask, + grEvent* grevent ) + { + static char key_buffer[10]; + static int key_cursor = 0; + static int key_number = 0; + static XEvent x_event; + KeySym key; + + int bool_exit; + grKey grkey; + + XComposeStatus compose; + + /* XXXX : For now, ignore the event mask, and only exit when */ + /* a key is pressed.. */ + (void)event_mask; + + bool_exit = key_cursor < key_number; + + XDefineCursor( display, surface->win, idle ); + + while ( !bool_exit ) + { + XNextEvent( display, &x_event ); + + switch ( x_event.type ) + { + case KeyPress: + key_number = XLookupString( &x_event.xkey, + key_buffer, + sizeof ( key_buffer ), + &key, + &compose ); + key_cursor = 0; + + if ( key_number == 0 || + key > 512 ) + { + /* this may be a special key like F1, F2, etc.. */ + grkey = KeySymTogrKey(key); + if (grkey != grKeyNone) + goto Set_Key; + } + else + bool_exit = 1; + break; + + case MappingNotify: + XRefreshKeyboardMapping( &x_event.xmapping ); + break; + + case Expose: + refresh_rectangle( surface, + x_event.xexpose.x, + x_event.xexpose.y, + x_event.xexpose.width, + x_event.xexpose.height ); + break; + + /* You should add more cases to handle mouse events, etc. */ + } + } + + XDefineCursor( display, surface->win, busy ); + XFlush ( display ); + + /* Now, translate the keypress to a grKey */ + /* If this wasn't part of the simple translated keys, simply get the charcode */ + /* from the character buffer */ + grkey = grKEY(key_buffer[key_cursor++]); + + Set_Key: + grevent->type = gr_key_down; + grevent->key = grkey; + } + + + + + grXSurface* init_surface( grXSurface* surface, + grBitmap* bitmap ) + { + int screen; + grBitmap* image; + char grays; + XDepth* format; + int image_depth; + + screen = DefaultScreen( display ); + + surface->colormap = DefaultColormap( display, screen ); + surface->depth = DefaultDepth( display, screen ); + surface->visual = DefaultVisual( display, screen ); + + image = &surface->image; + + /* force the surface image depth to 1 if necessary */ + /* as this should be supported by all windows */ + image_depth = surface->depth; + if (bitmap->mode == gr_pixel_mode_mono) + image_depth = 1; + + grays = ( bitmap->mode == gr_pixel_mode_gray && + bitmap->grays >= 2 ); + + surface->gray = grays; + + /* copy dimensions */ + image->width = bitmap->width; + image->rows = bitmap->rows; + image->mode = bitmap->mode; + image->pitch = 0; + image->grays = 0; + image->buffer = 0; + + /* find the supported format corresponding to the request */ + format = 0; + + if (grays) + { + /* choose the default depth in case of grays rendering */ + int i; + for ( i = 0; i < num_pixel_modes; i++ ) + if ( image_depth == pixel_depth[i].depth ) + { + format = pixel_depth + i; + break; + } + } + else + { + /* otherwise, select the format depending on the pixel mode */ + int i; + + format = 0; + for ( i = 0; i < num_pixel_modes; i++ ) + if ( pixel_modes[i] == bitmap->mode ) + { + format = pixel_depth + i; + break; + } + } + + if (!format) + { + grError = gr_err_bad_argument; + return 0; + } + + + /* correct surface.depth. This is required because in the case */ + /* of 32-bits pixels, the value of "format.depth" is 24 under X11 */ + if ( format->depth == 24 && + format->bits_per_pixel == 32 ) + image_depth = 32; + + /* allocate surface image */ + { + int bits, over; + + bits = image->width * format->bits_per_pixel; + over = bits % format->scanline_pad; + + if (over) + bits += format->scanline_pad - over; + + if (!grays) + { + image->width = bits; + bitmap->width = bits; + } + image->pitch = bits >> 3; + } + + image->buffer = grAlloc( image->pitch * image->rows ); + if (!image->buffer) return 0; + + /* now, allocate a gray pal8 pixmap, only when we asked */ + /* for an 8-bit pixmap */ + if ( grays ) + { + /* pad pitch to 32 bits */ + bitmap->pitch = (bitmap->width + 3) & -4; + bitmap->buffer = grAlloc( bitmap->pitch * bitmap->rows ); + if (!bitmap->buffer) + Panic( "grX11: could not allocate surface bitmap!\n" ); + } + else /* otherwise */ + { + *bitmap = *image; + } + + surface->root.bitmap = *bitmap; + + /* Now create the surface X11 image */ + surface->ximage = XCreateImage( display, + surface->visual, + format->depth, + format->depth == 1 ? XYBitmap : ZPixmap, + 0, + (char*)image->buffer, + image->width, + image->rows, + 8, + 0 ); + if ( !surface->ximage ) + Panic( "grX11: cannot create surface X11 image\n" ); + + + /* allocate gray levels in the case of gray surface */ + if ( grays ) + { + XColor* color = surface->color; + int i; + + for ( i = 0; i < bitmap->grays; i++, color++ ) + { + color->red = + color->green = + color->blue = 65535 - ( i * 65535 ) / bitmap->grays; + + if ( !XAllocColor( display, surface->colormap, color ) ) + Panic( "ERROR: cannot allocate Color\n" ); + } + } + else if ( image_depth == 1 ) + { + surface->ximage->byte_order = MSBFirst; + surface->ximage->bitmap_bit_order = MSBFirst; + } + + { + XTextProperty xtp; + XSizeHints xsh; + XSetWindowAttributes xswa; + + xswa.border_pixel = BlackPixel( display, screen ); + xswa.background_pixel = WhitePixel( display, screen ); + xswa.cursor = busy; + + xswa.event_mask = KeyPressMask | ExposureMask; + + surface->win = XCreateWindow( display, + RootWindow( display, screen ), + 0, + 0, + image->width, + image->rows, + 10, + surface->depth, + InputOutput, + surface->visual, + CWBackPixel | CWBorderPixel | + CWEventMask | CWCursor, + &xswa ); + + XMapWindow( display, surface->win ); + + surface->gc = XCreateGC( display, RootWindow( display, screen ), 0L, NULL ); + XSetForeground( display, surface->gc, xswa.border_pixel ); + XSetBackground( display, surface->gc, xswa.background_pixel ); + + + /* make window manager happy :-) */ + xtp.value = (unsigned char*)"FreeType"; + xtp.encoding = 31; + xtp.format = 8; + xtp.nitems = strlen( (char*)xtp.value ); + + xsh.x = 0; + xsh.y = 0; + + xsh.width = image->width; + xsh.height = image->rows; + xsh.flags = (PPosition | PSize); + xsh.flags = 0; + + XSetWMProperties( display, surface->win, &xtp, &xtp, NULL, 0, &xsh, NULL, NULL ); + } + + surface->root.done = (grDoneSurfaceFunc) done_surface; + surface->root.refresh_rect = (grRefreshRectFunc) refresh_rectangle; + surface->root.set_title = (grSetTitleFunc) set_title; + surface->root.listen_event = (grListenEventFunc) listen_event; + + convert_rectangle( surface, 0, 0, bitmap->width, bitmap->rows ); + return surface; + } + + + + + grDevice gr_x11_device = + { + sizeof( grXSurface ), + "x11", + + init_device, + done_device, + + (grDeviceInitSurfaceFunc) init_surface, + + 0, + 0 + + }; + +#ifdef TEST + +typedef struct grKeyName +{ + grKey key; + const char* name; + +} grKeyName; + + +static +const grKeyName key_names[] = +{ + { grKeyF1, "F1" }, + { grKeyF2, "F2" }, + { grKeyF3, "F3" }, + { grKeyF4, "F4" }, + { grKeyF5, "F5" }, + { grKeyF6, "F6" }, + { grKeyF7, "F7" }, + { grKeyF8, "F8" }, + { grKeyF9, "F9" }, + { grKeyF10, "F10" }, + { grKeyF11, "F11" }, + { grKeyF12, "F12" }, + { grKeyEsc, "Esc" }, + { grKeyHome, "Home" }, + { grKeyEnd, "End" }, + + { grKeyPageUp, "Page_Up" }, + { grKeyPageDown, "Page_Down" }, + { grKeyLeft, "Left" }, + { grKeyRight, "Right" }, + { grKeyUp, "Up" }, + { grKeyDown, "Down" }, + { grKeyBackSpace, "BackSpace" }, + { grKeyReturn, "Return" } +}; + +int main( void ) +{ + grSurface* surface; + int n; + + grInit(); + surface = grNewScreenSurface( 0, gr_pixel_mode_gray, 320, 400, 128 ); + if (!surface) + Panic("Could not create window\n" ); + else + { + grColor color; + grEvent event; + const char* string; + int x; + + grSetSurfaceRefresh( surface, 1 ); + grSetTitle(surface,"X11 driver demonstration" ); + + for ( x = -10; x < 10; x++ ) + { + for ( n = 0; n < 128; n++ ) + { + color.value = (n*3) & 127; + grWriteCellChar( surface, + x + ((n % 60) << 3), + 80 + (x+10)*8*3 + ((n/60) << 3), n, color ); + } + + } + color.value = 64; + grWriteCellString( surface, 0, 0, "just an example", color ); + + do + { + listen_event((grXSurface*)surface, 0, &event); + + /* return if ESC was pressed */ + if ( event.key == grKeyEsc ) + return 0; + + /* otherwise, display key string */ + color.value = (color.value + 8) & 127; + { + int count = sizeof(key_names)/sizeof(key_names[0]); + grKeyName* name = key_names; + grKeyName* limit = name + count; + const char* kname = 0; + char kname_temp[16]; + + while (name < limit) + { + if ( name->key == event.key ) + { + kname = name->name; + break; + } + name++; + } + + if (!kname) + { + sprintf( kname_temp, "char '%c'", (char)event.key ); + kname = kname_temp; + } + + grWriteCellString( surface, 30, 30, kname, color ); + grRefreshSurface(surface); + paint_rectangle( surface, 0, 0, surface->bitmap.width, surface->bitmap.rows ); + } + } while (1); + } + + return 0; + + +} +#endif /* TEST */ + diff --git a/demos/graph/grx11.h b/demos/graph/grx11.h new file mode 100644 index 000000000..cd77112c0 --- /dev/null +++ b/demos/graph/grx11.h @@ -0,0 +1,24 @@ +#ifndef GRX11_H +#define GRX11_H + +#include "grobjs.h" +#include "grdevice.h" + + extern + grDevice gr_x11_device; + +#ifdef GR_INIT_BUILD + static + grDeviceChain gr_x11_device_chain = + { + "x11", + &gr_x11_device, + GR_INIT_DEVICE_CHAIN + }; + +#undef GR_INIT_DEVICE_CHAIN +#define GR_INIT_DEVICE_CHAIN &gr_x11_device_chain + +#endif /* GR_INIT_BUILD */ + +#endif /* GRX11_H */ diff --git a/demos/graph/migs.html b/demos/graph/migs.html new file mode 100644 index 000000000..365b9c97a --- /dev/null +++ b/demos/graph/migs.html @@ -0,0 +1,304 @@ + + + + + + + + +
MiGS Overview +
A Minimalist Graphics Subsystem +

+


+ +

+Introduction

+ +
This document details the design and implementation of MiGS, +the minimalist graphics subsystem used by the FreeType 2 demonstration +programs. Its purpose is mainly to help writers of new demo programs, as +well as developers who would like port the subsystem to other platforms.
+ +
+

+I - Design goals

+ +
MiGS is a tiny graphics subsystem used to demo text rendering +through the FreeType library. It was mainly written to provide the abilities +to :
+ +
    +
      +
    • +draw a monochrome glyph bitmap to many kinds of target surfaces (i.e. really +bitmaps/pixmaps)
    • + +
    • +draw an anti-aliased glyph bitmap, with any level of grays, to many kinds +of target surfaces
    • + +
    • +display a simple window on many systems like X11, OS/2 and Windows
    • + +
    • +accept simple events (keypresses and mouse buttons) in this window.
    • + +
    • +to be portable and present a unified API on all running systems
    • +
    + +


    MiGS uses system-specific "drivers" in order to perform display +and event handling. The blitting functions are not device-specific. MiGS +can be built and/or used with no system-specific features, like for example, +to generate simple GIF, PNG, TIFF, etc.. images without ever needing to +display them.

+ +

+ +

+ +

+II - Surfaces, bitmaps and windows

+ +
A surface in MiGS models a drawable region where glyph images +can be rendered, a surface always contains a bitmap descriptor as well +as a few other things that will be described later in this section. +

Some surfaces can be displayed, they are then either called windowed +surfaces or screen surfaces depending on the nature of the device +used to display them. Each device is implemented by a very simple +driver in the MiGS code. Here are a few example devices that are +or could be written to display surfaces : +

- an X11 device +
- a Win 32 GDI device +
- an OS/2 Presentation Manager device +
- a fullscreen SVGALib device on Linux +
- a GGI visual device +
- an OS/2 "Dive" device, or the equivalent Win32 "DirectX" device +

etc.. +

NOTE: For now, only the X11 device was written and tested.. More +devices should come later +

Before explaining how to create a surface, we need to explain how MiGS +manages bitmaps and renders glyph images to them. +

+1. Bitmaps :

+ +
A bitmap in MiGS features the following things : +
    +
  • +a width in pixels
  • + +
  • +a height in pixels
  • + +
  • +a pixel mode, which indicates how the pixels are stored in +the surface's buffer
  • + +
  • +a pitch, whose absolute values is the number of bytes taken +by each surface row
  • + +
  • +a number of valid gray levels (see below)
  • + +
  • +a buffer, holding the surface's pixels
  • +
+ +


MiGS uses the "Y downwards" convention, which means that +increasing +Y coordinates correspond to lower rows of the bitmap. Hence, +the coordinate (0,0) always corresponds to the bitmap's +top-left +pixel. +

The bitmap's rows can be stored either "downwards" or "upwards" +in the pixel buffer. +

In the first case (downwards), increasing memory addresses in +the pixel buffer correspond to lower rows of the bitmap(e.g. PC video modes), +and the pitch should be equal to the number of bytes +taken by each row. The first pixel buffer byte corresponds to the +upper row. +

In the second case (upwards), increasing memory addresses in +the pixel buffer correspond to upper rows of the bitmap and the pitch +should be equal to the opposite of the number of bytes +taken by each row. The first pixel buffer byte corresponds to the lower +row. +

In all cases, the pitch is the increment to be used +to go from one bitmap row to the one below it. +

The supported pixel modes are : +

    +
  • +1-bit monochrome bitmaps. With "0" as the background, and "1" as the foreground.
  • + +
  • +4-bit color bitmaps, using an arbitrary palette.
  • + +
  • +8-bit color bitmaps, using an arbitrary palette.
  • + +
  • +8-bit gray bitmaps, using a given N number of gray levels in the range +0..N-1.
  • + +
  • +15-bit color bitmaps, also known as RGB555
  • + +
  • +16-bit color bitmaps, also known as RGB565
  • + +
  • +24-bit color bitmaps, also known as RGB
  • + +
  • +32-bit color bitmaps, also known as RGBA (though the A is ignored by MiGS)
  • +
+The bitmap's number of gray levels is only relevant for 8-bit +gray bitmaps, and indicates the range of gray levels that can be +found in the bitmap. If a bitmap as N gray levels, it is said to be N-grayscales, +and the pixels within it must all have values between 0, considered as +the background color, and N-1, considered as the foreground +color. +

N-grayscale bitmaps are crucial for the rendering of anti-aliased text. +
 

+ +

+2. Glyph images :

+ +
The glyph images that can be drawn on bitmaps through MiGS +are bitmaps themselves, though limited to the following pixel modes : +

1-bit monochrome glyph bitmaps +

These can be drawn on any kind of bitmap. Note that only +the "lit" pixels (i.e. the bits set to 1) are effectively drawn to +the target, as opaque blitting isn't supported (remember, it's a minimalist +library !)
+ +


N-grayscales glyph images (with any value of N >= 2) +

These can be drawn to all RGB bitmaps (15, 16, 24 & +32 bits/pixel), as well as any other M-grayscales bitmaps. In the latter +case, the values of N and M need not be equal, as the library is +able to perform automatic conversions on the fly. +

For example, it is possible to render a 5-grayscales glyph image into +a 128-grayscales bitmap. Moreover, it is also possible to render a 17-grayscales +glyph image into a 5-grayscales bitmap, even if this will result in a +loss of quality. This feature is crucial in order to experiment easily +with other anti-aliasing algorithms for FreeType +
 

+Note that you can only draw monochrome bitmaps to the following +pixel modes : monochrome, 4-bit color and 8-bit color.
+ +

+3. Windows and Screens:

+ +
In order to debug FreeType, displaying a surface in a window +or in full-screen mode, is required. MiGS thus makes a difference between +simple +surfaces, which only contain a bitmap, windowed surfaces, which +are used to display their content in a window, and screen surfaces, +which are used to display their content in a full-screen mode (SVGAlib, +DirectX, GGI or wathever). +

A few important things must be said about non-simple surfaces. +
  +

    +
  • +First, they might contain some system-specific data which is used to manage +the display in a window or on the screen. This must be completely hidden +to MiGS clients. Indeed, rendering to any kind of surface is achieved through +exactly +the same function calls.
  • +
+ +
    +
  • +Second, they may contain a bitmap whose pixel mode doesn't correspond to +the screen's depth used to display it. For example, the surface might contain +an 128-grayscale bitmap, while the screen is in RGB24 mode. Some conversion +must be performed to display the surface. This can either happen in the +system-specific graphics library (e.g. on OS/2, a single Presentation Manager +call is used to blit a N-grayscale image to any kind of window) +or in the system-specific part of MiGS (e.g. the X11 MiGS driver must convert +the surface's bitmap into the appropriate X11 image each time a +repaint is requested). Again this must be completely hidden to MiGS clients
  • +
+Surfaces have also a few fields that are only used when displaying them +in Windows : +

a title string +

This is simply a text string that is displayed on the title +bar of the surface's window. It can also appear at the top or bottom of +full-screen surfaces if the MiGS driver supports it. The title string can +be changed with a call to grSetTitle, and is ignored for simple +surfaces.
+ +


a refresh flag +

This boolean flag is only used for window surfaces, and some +fullscreen ones (depending on the driver implementation). When set, it +indicates that each glyph image blit must be displayed immediately. By +default, this flag is set to False, which means that demo programs must +call the grRefreshSurface(surface) function to display the whole +contents of a surface one it has been updated. +

The refresh flag can be set with grSetSurfaceRefresh(surface,flag). +Note that a single surface rectangle can be forced to be displayed with +a call to grRefreshRectangle(surface,x,y,w,h) at any time.

+
+ +

+4. Devices :

+ +
As said before, each device is in charge of displaying a surface +in a given window or screen. Each device is managed through a very simple +driver, described to MiGS through a very simple "grDevice" structure. +

A grDevice contains, among other things, pointers to the functions used +to: +

- refresh/display a given rectangle of the surface to the window/screen +
- listen events (key presses and mouse) and send them back to client +apps. +
- for windowed devices, update the title bar. +

As said before, this is a highly minimalist system.. +
 

+
+ +
+

+III - Important implementation issues :

+ +
+

+1. Display surface negociation :

+ +
A display surface is created with the function grNewScreenSurface +which takes parameters indicating which device should be used, the pixel +dimensions of the requested surface, as well as its pixel mode. +

Because of some device-specific limitations, the resulting surface's +properties might not match exactly those requested for the call. Hence, +a developper should always take care of reading a new display surface's +bitmap descriptor in order to get its real dimensions, pixel +mode and eventually number of grays. +

The function grNewSurface will create a memory surface with the corresponding +bitmap. +
The function grNewBitmapSurface will create a surface from a pre-existing +bitmap. This is useful to draw text on loaded images, for example. +

Any surface (display or not) is destroyed with grDoneSurface.

+ +

+

+ +

+2. Supporting 8-bit grayscale mode :

+ +
It is important, for the debugging of FreeType anti-aliased +renderer(s), that _all_ devices should support the 8-bit gray mode. +The number of gray levels can be fixed or negociated as required by implementation-specific +issues. +

As most existing devices do not provide direct support for such a mode, +each 8-bit surface must thus contain : +

- an internal N-grayscale bitmap, used as the target of all glyph drawings +
- its own device-specific "image", which matches the display depth. +

Each time the device's "refresh_rect" function is called, it should +then : +
- convert the grayscales within the bitmap's rectangle into the image's +buffer and format. +
- display the corresponding image rectangle. +

This scheme is used, for example, by the X11 device.

+
+ + + diff --git a/demos/graph/rules.mk b/demos/graph/rules.mk new file mode 100644 index 000000000..d397e541d --- /dev/null +++ b/demos/graph/rules.mk @@ -0,0 +1,99 @@ +#************************************************************************** +#* +#* FreeType demo utilities sub-Makefile +#* +#* This Makefile is to be included by "freetype/demo/Makefile". Its +#* purpose is to compile MiGS (the Minimalist Graphics Subsystem) +#* +#* It is written for GNU Make. Other make utilities are not +#* supported.. !! +#* +#* +#* The following variables must be defined : +#* +#* CFLAGS : C flags to use when compiling the utilities. This +#* must NOT include the '-c' flag used to specify a +#* simple compilation. +#* +#* IFLAG : include path flag. This is typically "-I" but some +#* compilers use a different convention.. +#* +#* LFLAG : add link directory flag. Usually '-L' but could be +#* different.. +#* +#* OBJ_DIR : target location of the object files +#* +#* UTIL_DIR : location of the utilities sources. I.e. this +#* directory (usually "freetype/demo/graph"). +#* +#* +#* It also defines the following variables +#* +#* SIMPLE_UTILS : list of object files for the non-graphical utilities +#* +#* GRAPH_UTILS : all object files, including the graphics sub-system +#* +#* GRAPH_FLAGS : additional compile flags for graphical apps +#* GRAPH_LINK : additional link flags for graphical apps +#* +#************************************************************************** + +########################################################################## +# +# +# +# +# + +GRAPH_INCLUDES := graph +GRAPH_LIB := $(OBJ_)graph.a +GRAPH_LINK := $(GRAPH_LIB) + +GRAPH_ := graph$(SEP) + +GRAPH_H := $(GRAPH_)graph.h \ + $(GRAPH_)grtypes.h \ + $(GRAPH_)grobjs.h \ + $(GRAPH_)grdevice.h \ + $(GRAPH_)grblit.h + + +GRAPH_OBJS := $(OBJ_)grblit.$O \ + $(OBJ_)grobjs.$O \ + $(OBJ_)grfont.$O \ + $(OBJ_)grdevice.$O \ + $(OBJ_)grinit.$O + + +# Add the rules used to detect and compile graphics driver depending +# on the current platform.. +# +include $(wildcard config/*/rules.mk) + +######################################################################### +# +# Build the "graph" library from its objects. This should be changed +# in the future in order to support more systems. Probably something +# like a `config/' hierarchy with a system-specific rules file +# to indicate how to make a library file, but for know, I'll stick to +# unix and OS/2-gcc.. +# +# +$(GRAPH_LIB): $(GRAPH_OBJS) + ar -r $@ $(GRAPH_OBJS) + + +# pattern rule for normal sources +# +$(OBJ_)%.$O: $(GRAPH_)%.c $(GRAPH_H) + $(CC) $(CFLAGS) $(GRAPH_INCLUDES:%=$I%) $T$@ $< + + +# a special rule is used for 'grinit.o' as it needs the definition +# of some macros like "-DDEVICE_X11" or "-DDEVICE_OS2_PM" +# +$(OBJ_)grinit.$O: $(GRAPH_)grinit.c + $(CC) $(CFLAGS) $(GRAPH_INCLUDES:%=$I%) $I$(DEVICE_INCLUDES:%=$I%) $T$@ $< \ + $(DEVICES:%=$DDEVICE_%) + + diff --git a/demos/graph/xtest.c b/demos/graph/xtest.c new file mode 100644 index 000000000..4c6295e1d --- /dev/null +++ b/demos/graph/xtest.c @@ -0,0 +1,125 @@ +#include "graph.h" +#include "grfont.h" /* dispara^itra bientot */ +#include + + +static +void Panic( const char* message ) +{ + fprintf( stderr, "PANIC: %s\n", message ); + exit(1); +} + + +typedef struct grKeyName +{ + grKey key; + const char* name; + +} grKeyName; + + +static +const grKeyName key_names[] = +{ + { grKeyF1, "F1" }, + { grKeyF2, "F2" }, + { grKeyF3, "F3" }, + { grKeyF4, "F4" }, + { grKeyF5, "F5" }, + { grKeyF6, "F6" }, + { grKeyF7, "F7" }, + { grKeyF8, "F8" }, + { grKeyF9, "F9" }, + { grKeyF10, "F10" }, + { grKeyF11, "F11" }, + { grKeyF12, "F12" }, + { grKeyEsc, "Esc" }, + { grKeyHome, "Home" }, + { grKeyEnd, "End" }, + + { grKeyPageUp, "Page_Up" }, + { grKeyPageDown, "Page_Down" }, + { grKeyLeft, "Left" }, + { grKeyRight, "Right" }, + { grKeyUp, "Up" }, + { grKeyDown, "Down" }, + { grKeyBackSpace, "BackSpace" }, + { grKeyReturn, "Return" } +}; + +int main( void ) +{ + grSurface* surface; + int n; + + grInit(); + surface = grNewScreenSurface( 0, gr_pixel_mode_gray, 320, 400, 128 ); + if (!surface) + Panic("Could not create window\n" ); + else + { + grColor color; + grEvent event; + const char* string; + int x; + + grSetSurfaceRefresh( surface, 1 ); + grSetTitle(surface,"X11 driver demonstration" ); + + for ( x = -10; x < 10; x++ ) + { + for ( n = 0; n < 128; n++ ) + { + color.value = (n*3) & 127; + grWriteCellChar( surface, + x + ((n % 60) << 3), + 80 + (x+10)*8*3 + ((n/60) << 3), n, color ); + } + + } + color.value = 64; + grWriteCellString( surface, 0, 0, "just an example", color ); + + do + { + grListenSurface( surface, 0, &event); + + /* return if ESC was pressed */ + if ( event.key == grKeyEsc ) + return 0; + + /* otherwise, display key string */ + color.value = (color.value + 8) & 127; + { + int count = sizeof(key_names)/sizeof(key_names[0]); + grKeyName* name = (grKeyName*)key_names; + grKeyName* limit = name + count; + const char* kname = 0; + char kname_temp[16]; + + while (name < limit) + { + if ( name->key == event.key ) + { + kname = (const char*)name->name; + break; + } + name++; + } + + if (!kname) + { + sprintf( kname_temp, "char '%c'", (char)event.key ); + kname = kname_temp; + } + + grWriteCellString( surface, 30, 30, kname, color ); + grRefreshSurface(surface); + } + } while (1); + } + + return 0; +} + diff --git a/demos/obj/README b/demos/obj/README new file mode 100644 index 000000000..f11d2c105 --- /dev/null +++ b/demos/obj/README @@ -0,0 +1 @@ +This directory contains all the object files generated for the demonstration programs diff --git a/demos/src/common.c b/demos/src/common.c new file mode 100644 index 000000000..8a5740535 --- /dev/null +++ b/demos/src/common.c @@ -0,0 +1,244 @@ +/* + * This is a cheap replacement for getopt() because that routine is not + * available on some platforms and behaves differently on other platforms. + * This code was written from scratch without looking at any other + * implementation. + * + * This code is hereby expressly placed in the public domain. + * mleisher@crl.nmsu.edu (Mark Leisher) + * 10 October 1997 + */ + +#ifndef lint +#ifdef __GNUC__ + static char rcsid[] __attribute__ ((unused)) = "$Id$"; +#else + static char rcsid[] = "$Id$"; +#endif +#endif + +#include "common.h" + +#include +#include +#include +#include + + /* + * Externals visible to programs. + */ + + int opterr = 1; + int optind = 1; + char* optarg; + + /* + * Internal variables that are used to detect when the global values + * need to be reset. + */ + + static int cmdac; +#ifdef __STDC__ + static const char* cmdname; + static char* const* cmdav; +#else + static char* cmdname; + static char** cmdav; +#endif + + int +#ifdef __STDC__ + getopt( int ac, char* const* av, const char* pat ) +#else + getopt( ac, av, pat ) + int ac; + char** av; + char* pat; +#endif + { + int opt; +#ifdef __STDC__ + const char* p; + const char* pp; +#else + char* p; + char* pp; +#endif + + /* + * If there is no pattern, indicate the parsing is done. + */ + if ( pat == 0 || *pat == 0 ) + return -1; + + /* + * Always reset the option argument to NULL. + */ + optarg = 0; + + /* + * If the number of arguments or argument list do not match the last + * values seen, reset the internal pointers and the globals. + */ + if ( ac != cmdac || av != cmdav ) + { + optind = 1; + cmdac = ac; + cmdav = av; + + /* + * Determine the command name in case it is needed for warning + * messages. + */ + for ( cmdname = 0, p = av[0]; *p; p++ ) + { + if ( *p == '/' || *p == '\\' ) + cmdname = p; + } + /* + * Skip the path separator if the name was assigned. + */ + if ( cmdname ) + cmdname++; + else + cmdname = av[0]; + } + + /* + * If the next index is greater than or equal to the number of + * arguments, then the command line is done. + */ + if ( optind >= ac ) + return -1; + + /* + * Test the next argument for one of three cases: + * 1. The next argument does not have an initial '-'. + * 2. The next argument is '-'. + * 3. The next argument is '--'. + * + * In either of these cases, command line processing is done. + */ + if ( av[optind][0] != '-' || + strcmp( av[optind], "-" ) == 0 || + strcmp( av[optind], "--" ) == 0 ) + return -1; + + /* + * Point at the next command line argument and increment the + * command line index. + */ + p = av[optind++]; + + /* + * Look for the first character of the command line option. + */ + for ( opt = *(p + 1), pp = pat; *pp && *pp != opt; pp++ ) + ; + + /* + * If nothing in the pattern was recognized, then issue a warning + * and return a '?'. + */ + if ( *pp == 0 ) + { + if ( opterr ) + fprintf( stderr, "%s: illegal option -- %c\n", cmdname, opt ); + return '?'; + } + + /* + * If the option expects an argument, get it. + */ + if ( *(pp + 1) == ':' && (optarg = av[optind]) == 0 ) + { + /* + * If the option argument is NULL, issue a warning and return a '?'. + */ + if ( opterr ) + fprintf( stderr, "%s: option requires an argument -- %c\n", + cmdname, opt ); + opt = '?'; + } + else if ( optarg ) + /* + * Increment the option index past the argument. + */ + optind++; + + /* + * Return the option character. + */ + return opt; + } + + +/****************************************************************************/ +/* */ +/* The FreeType project -- a free and portable quality TrueType renderer. */ +/* */ +/* Copyright 1996-1998 by */ +/* D. Turner, R.Wilhelm, and W. Lemberg */ +/* */ +/* ft_basename(): */ +/* */ +/* a stupid but useful function... */ +/* */ +/* rewritten by DavidT to get rid of GPLed programs in the FreeType demos. */ +/* */ +/****************************************************************************/ + + char* +#ifdef __STDC__ + ft_basename ( const char* name ) +#else + ft_basename ( name ) + char* name; +#endif + { +#ifdef __STDC__ + const char* base; + const char* current; +#else + char* base; + char* current; +#endif + char c; + + base = name; + current = name; + + c = *current; + + while ( c ) + { + if ( c == '/' || c == '\\' ) + base = current + 1; + + current++; + c = *current; + } + + return (char*)base; + } + + +#ifdef __STDC__ + void Panic( const char* fmt, ... ) +#else + void Panic( fmt ) + const char* fmt; +#endif + { + va_list ap; + + + va_start( ap, fmt ); + vprintf( fmt, ap ); + va_end( ap ); + + exit( 1 ); + } + + +/* End */ diff --git a/demos/src/common.h b/demos/src/common.h new file mode 100644 index 000000000..e1377086f --- /dev/null +++ b/demos/src/common.h @@ -0,0 +1,53 @@ +/* + * This is a cheap replacement for getopt() because that routine is not + * available on some platforms and behaves differently on other platforms. + * + * This code is hereby expressly placed in the public domain. + * mleisher@crl.nmsu.edu (Mark Leisher) + * 10 October 1997 + */ + +#ifndef _H_COMMON +#define _H_COMMON + +/* Note that by default, both functions are implemented in common.c */ + +#ifdef __cplusplus + extern "C" { +#endif + + extern int opterr; + extern int optind; + extern char* optarg; + + extern int getopt( +#ifdef __STDC__ + int argc, + char* const* argv, + const char* pattern +#endif + ); + + + extern char* ft_basename( +#ifdef __STDC__ + const char* name +#endif + ); + + /* print a message and exit */ + extern void Panic ( +#ifdef __STDC__ + const char* fmt, ... +#endif + ); + + +#ifdef __cplusplus + } +#endif + +#endif /* _H_COMMON */ + + +/* End */ diff --git a/demos/src/ftlint.c b/demos/src/ftlint.c new file mode 100644 index 000000000..0dc39263e --- /dev/null +++ b/demos/src/ftlint.c @@ -0,0 +1,169 @@ +/****************************************************************************/ +/* */ +/* The FreeType project -- a free and portable quality TrueType renderer. */ +/* */ +/* Copyright 1996-1998 by */ +/* D. Turner, R.Wilhelm, and W. Lemberg */ +/* */ +/* ftlint: a simple font tester. This program tries to load all the */ +/* glyphs of a given font. */ +/* */ +/* NOTE: This is just a test program that is used to show off and */ +/* debug the current engine. */ +/* */ +/****************************************************************************/ + +#include "freetype.h" +#include "ftobjs.h" +#include "ftdriver.h" + +#include +#include +#include + + +#define gettext( x ) ( x ) + + FT_Error error; + + FT_Library library; + FT_Face face; + FT_Size size; + FT_GlyphSlot slot; + + unsigned int num_glyphs; + int ptsize; + + int Fail; + int Num; + + + + static void Usage( char* name ) + { + printf( "ftlint: simple font tester -- part of the FreeType project\n" ); + printf( "----------------------------------------------------------\n" ); + printf( "\n" ); + printf( "Usage: %s ppem fontname[.ttf|.ttc] [fontname2..]\n", name ); + printf( "\n" ); + + exit( 1 ); + } + + + static void Panic( const char* message ) + { + fprintf( stderr, "%s\n error code = 0x%04x\n", message, error ); + exit(1); + } + + + int main( int argc, char** argv ) + { + int i, file_index; + unsigned int id; + char filename[128 + 4]; + char alt_filename[128 + 4]; + char* execname; + char* fname; + + + execname = argv[0]; + + if ( argc < 3 ) + Usage( execname ); + + if ( sscanf( argv[1], "%d", &ptsize ) != 1 ) + Usage( execname ); + + error = FT_Init_FreeType( &library ); + if (error) Panic( "Could not create library object" ); + + /* Now check all files */ + for ( file_index = 2; file_index < argc; file_index++ ) + { + fname = argv[file_index]; + i = strlen( fname ); + while ( i > 0 && fname[i] != '\\' && fname[i] != '/' ) + { + if ( fname[i] == '.' ) + i = 0; + i--; + } + + filename[128] = '\0'; + alt_filename[128] = '\0'; + + strncpy( filename, fname, 128 ); + strncpy( alt_filename, fname, 128 ); + + if ( i >= 0 ) + { + strncpy( filename + strlen( filename ), ".ttf", 4 ); + strncpy( alt_filename + strlen( alt_filename ), ".ttc", 4 ); + } + + i = strlen( filename ); + fname = filename; + + while ( i >= 0 ) + if ( filename[i] == '/' || filename[i] == '\\' ) + { + fname = filename + i + 1; + i = -1; + } + else + i--; + + printf( "%s: ", fname ); + + /* Load face */ + error = FT_New_Face( library, filename, 0, &face ); + if (error) + { + if (error == FT_Err_Invalid_File_Format) + printf( "unknow format\n" ); + else + printf( "could not find/open file\n" ); + continue; + } + if (error) Panic( "Could not open file" ); + + num_glyphs = face->num_glyphs; + + error = FT_Set_Char_Size( face, ptsize << 6, ptsize << 6, 72, 72 ); + if (error) Panic( "Could not set character size" ); + + Fail = 0; + { + for ( id = 0; id < num_glyphs; id++ ) + { + error = FT_Load_Glyph( face, id, FT_LOAD_DEFAULT ); + if (error) + { + if ( Fail < 10 ) + printf( "glyph %4u: 0x%04x\n" , id, error ); + Fail++; + } + } + } + + if ( Fail == 0 ) + printf( "OK.\n" ); + else + if ( Fail == 1 ) + printf( "1 fail.\n" ); + else + printf( "%d fails.\n", Fail ); + + FT_Done_Face( face ); + } + + FT_Done_FreeType(library); + exit( 0 ); /* for safety reasons */ + + return 0; /* never reached */ + } + + +/* End */ diff --git a/demos/src/ftsbit.c b/demos/src/ftsbit.c new file mode 100644 index 000000000..14f355319 --- /dev/null +++ b/demos/src/ftsbit.c @@ -0,0 +1,313 @@ +/****************************************************************************/ +/* */ +/* The FreeType project -- a free and portable quality TrueType renderer. */ +/* */ +/* Copyright 1996-1998 by */ +/* D. Turner, R.Wilhelm, and W. Lemberg */ +/* */ +/* ftsbit: a _very_ simple embedded bitmap dumper for FreeType 1.x. */ +/* */ +/* NOTE: This is just a test program that is used to show off and */ +/* debug the current engine. */ +/* */ +/****************************************************************************/ + + +#include +#include +#include + +#include "freetype.h" + + +#ifdef HAVE_LIBINTL_H + +#ifdef HAVE_LOCALE_H +#include +#endif + +#include +#include "ftxerr18.h" + +#else /* !HAVE_LIBINTL */ + +#define gettext( x ) ( x ) + + /* We ignore error message strings with this function */ + + static char* TT_ErrToString18( FT_Error error ) + { + static char temp[32]; + + sprintf( temp, "0x%04lx", error ); + return temp; + } + +#endif /* !HAVE_LIBINTL */ + + + FT_Error error; + FT_Library engine; + FT_Resource resource; + + FT_Face face; + FT_Size instance; + FT_GlyphSlot glyph; + + unsigned int num_glyphs; + int ptsize; + + int Fail; + int Num; + + + + static void Usage( char* name ) + { + printf( gettext( "ftsbit: simple TrueType 'sbit' dumper -- part of the FreeType project\n" ) ); + printf( "---------------------------------------------------------------------\n" ); + printf( "\n" ); + printf( gettext( "Usage: %s ppem fontname (index)* (index1-index2)*\n\n" ), name ); + printf( gettext( " or %s -a ppem fontname (dumps all glyphs)\n" ), name ); + printf( "\n" ); + + exit( EXIT_FAILURE ); + } + + + + static + void dump_bitmap( FT_GlyphSlot glyph, int glyph_index ) + { + /* Dump the resulting bitmap */ + { + int y; + unsigned char* line = (unsigned char*)glyph->bitmap.buffer; + + printf( "glyph index %d = %dx%d pixels, ", + glyph_index, glyph->bitmap.rows, glyph->bitmap.width ); + + printf( "advance = %d, minBearing = [%d,%d]\n", + glyph->metrics.horiAdvance >> 6, + glyph->metrics.horiBearingX >> 6, + glyph->metrics.horiBearingY >> 6 ); + + for ( y = 0; y < glyph->bitmap.rows; y++, line += glyph->bitmap.cols ) + { + unsigned char* ptr = line; + int x; + unsigned char mask = 0x80; + + for ( x = 0; x < glyph->bitmap.width; x++ ) + { + printf( "%c", (ptr[0] & mask) ? '*' : '.' ); + mask >>= 1; + if (mask == 0) + { + mask = 0x80; + ptr++; + } + } + + printf( "\n" ); + } + } + } + + + + static + void dump_range( FT_GlyphSlot glyph, + int first_glyph, + int last_glyph ) + { + int i; + + for ( i = first_glyph; i <= last_glyph; i++ ) + { + error = FT_Load_Glyph( glyph, + instance, + (unsigned short)i, + FT_LOAD_NO_OUTLINE, + 0 ); + if (error) + { + printf( " no bitmap for glyph %d\n", i ); + printf( gettext( "FreeType error message: %s\n" ), + TT_ErrToString18( error ) ); + continue; + } + + dump_bitmap(glyph,i); + } + } + + + + + int main( int argc, char** argv ) + { + int i; + char filename[128 + 4]; + char alt_filename[128 + 4]; + char* execname; + char* fname; + int dump_all = 0; + + +#ifdef HAVE_LIBINTL_H + setlocale( LC_ALL, "" ); + bindtextdomain( "freetype", LOCALEDIR ); + textdomain( "freetype" ); +#endif + + execname = argv[0]; + + if ( argc < 3 ) + Usage( execname ); + + if ( argv[1][0] == '-' && + argv[1][1] == 'a' ) + { + argv++; + argc--; + dump_all = 1; + } + + if ( sscanf( argv[1], "%d", &ptsize ) != 1 ) + Usage( execname ); + + /* Initialize engine */ + if ( (error = FT_Init_FreeType( &engine )) ) + { + fprintf( stderr, gettext( "Error while initializing engine\n" ) ); + goto Failure; + } + + /* Now check all files */ + fname = argv[2]; + i = strlen( fname ); + while ( i > 0 && fname[i] != '\\' && fname[i] != '/' ) + { + if ( fname[i] == '.' ) + i = 0; + i--; + } + + filename[128] = '\0'; + alt_filename[128] = '\0'; + + strncpy( filename, fname, 128 ); + strncpy( alt_filename, fname, 128 ); + + if ( i >= 0 ) + { + strncpy( filename + strlen( filename ), ".ttf", 4 ); + strncpy( alt_filename + strlen( alt_filename ), ".ttc", 4 ); + } + + /* Load face */ + error = FT_New_Resource( engine, filename, &resource ); + if (error) + { + strcpy( filename, alt_filename ); + error = FT_New_Resource( engine, alt_filename, &resource ); + } + + i = strlen( filename ); + fname = filename; + + while ( i >= 0 ) + if ( filename[i] == '/' || filename[i] == '\\' ) + { + fname = filename + i + 1; + i = -1; + } + else + i--; + + if ( error ) + { + printf( gettext( "Could not find or open file.\n" ) ); + goto Failure; + } + + error = FT_New_Face( resource, 0, &face ); + if (error) + { + printf( gettext( "Could not create face object.\n " ) ); + goto Failure; + } + + /* get face properties */ + num_glyphs = face->num_glyphs; + + /* create instance */ + error = FT_New_Size( face, &instance ); + if ( error ) + { + printf( gettext( "Could not create instance.\n" ) ); + goto Failure; + } + + error = FT_Set_Pixel_Sizes( instance, ptsize, ptsize ); + if (error) + { + printf( gettext( "Could not set character size.\n" ) ); + goto Failure; + } + + glyph = face->slot; + + if (dump_all) + dump_range( glyph, 0, num_glyphs-1 ); + else + { + for ( i = 3; i < argc; i++ ) + { + /* check for range in argument string */ + int range_check = 0; + char* base = argv[i]; + char* cur = base; + int first, last; + + while (*cur) + { + if (*cur == '-') + { + range_check = 1; + break; + } + cur++; + } + + if (range_check) + { + if ( sscanf( argv[i], "%d-%d", &first, &last ) != 2 ) + Usage( execname ); + + dump_range( glyph, first, last ); + } + else + { + if ( sscanf( argv[i], "%d", &first ) != 1 ) + Usage( execname ); + + dump_range( glyph, first, first ); + } + } + } + + FT_Done_FreeType( engine ); + exit( EXIT_SUCCESS ); /* for safety reasons */ + + return 0; /* never reached */ + + Failure: + printf( gettext( "FreeType error message: %s\n" ), + TT_ErrToString18( error ) ); + exit( EXIT_FAILURE ); + } + + +/* End */ diff --git a/demos/src/fttimer.c b/demos/src/fttimer.c new file mode 100644 index 000000000..84fa22226 --- /dev/null +++ b/demos/src/fttimer.c @@ -0,0 +1,460 @@ +/****************************************************************************/ +/* */ +/* The FreeType project - a Free and Portable Quality TrueType Renderer. */ +/* */ +/* Copyright 1996-1998 by */ +/* D. Turner, R.Wilhelm, and W. Lemberg */ +/* */ +/* fttimer: A simple performance benchmark. Now with graylevel rendering */ +/* with the '-g' option. */ +/* */ +/* Be aware that the timer program benchmarks different things */ +/* in each release of the FreeType library. Thus, performance */ +/* should only be compared between similar release numbers. */ +/* */ +/* */ +/* NOTE: This is just a test program that is used to show off and */ +/* debug the current engine. In no way does it shows the final */ +/* high-level interface that client applications will use. */ +/* */ +/****************************************************************************/ + +#include "freetype.h" +#include "ftoutln.h" + +#include +#include +#include +#include /* for clock() */ + +#include "graph.h" + +/* SunOS 4.1.* does not define CLOCKS_PER_SEC, so include */ +/* to get the HZ macro which is the equivalent. */ +#if defined(__sun__) && !defined(SVR4) && !defined(__SVR4) +#include +#define CLOCKS_PER_SEC HZ +#endif + +#define CHARSIZE 400 /* character point size */ +#define MAX_GLYPHS 512 /* Maximum number of glyphs rendered at one time */ + + char Header[128]; + + FT_Error error; + FT_Library library; + + FT_Face face; + FT_Size size; + FT_GlyphSlot glyph; + + FT_Outline outline; + + FT_Pos* cur_x; + FT_Pos* cur_y; + + unsigned short* cur_endContour; + unsigned char* cur_touch; + + FT_Outline outlines[MAX_GLYPHS]; + + int num_glyphs; + int tab_glyphs; + int cur_glyph; + int cur_point; + unsigned short cur_contour; + + int pixel_size = CHARSIZE*96/72; + int repeat_count = 1; + + FT_Bitmap Bit; + grBitmap bit; + + int Fail; + int Num; + + int vio_Height, vio_Width; + + short visual; /* display glyphs while rendering */ + short gray_render; /* smooth fonts with gray levels */ + + + + static void Clear_Buffer(); + + static void Panic( const char* message ) + { + fprintf( stderr, "%s\n error code = 0x%04x\n", message, error ); + } + +/*******************************************************************/ +/* */ +/* Get_Time: */ +/* */ +/* Returns the current time in milliseconds. */ +/* */ +/*******************************************************************/ + + long Get_Time( void ) + { + return clock() * 10000 / CLOCKS_PER_SEC; + } + + +/*******************************************************************/ +/* */ +/* Init_Engine: */ +/* */ +/* Allocates bitmap, render pool and other structs... */ +/* */ +/*******************************************************************/ + + void Init_Engine( void ) + { + Bit.rows = bit.rows; + Bit.width = bit.width; + Bit.pitch = bit.pitch; + Bit.buffer = bit.buffer; + Bit.pixel_mode = gray_render ? ft_pixel_mode_grays : ft_pixel_mode_mono; + Bit.num_grays = bit.grays; + Clear_Buffer(); + } + + +/*******************************************************************/ +/* */ +/* Clear_Buffer: */ +/* */ +/* Clears current bitmap. */ +/* */ +/*******************************************************************/ + + static void Clear_Buffer( void ) + { + long size = Bit.rows * Bit.pitch; + + memset( Bit.buffer, 0, size ); + } + + +/*******************************************************************/ +/* */ +/* LoadTrueTypeChar: */ +/* */ +/* Loads a glyph into memory. */ +/* */ +/*******************************************************************/ + + FT_Error LoadChar( int idx ) + { + error = FT_Load_Glyph( face, idx, FT_LOAD_DEFAULT ); + if ( error ) + return error; + + glyph->outline.second_pass = 0; + glyph->outline.high_precision = 0; + glyph->outline.dropout_mode = 0; + + /* debugging */ +#if 0 + if ( idx == 0 && !visual ) + { + printf( "points = %d\n", outline.points ); + for ( j = 0; j < outline.points; j++ ) + printf( "%02x (%01hx,%01hx)\n", + j, outline.xCoord[j], outline.yCoord[j] ); + printf( "\n" ); + } +#endif + + /* create a new outline */ + FT_New_Outline( library, + glyph->outline.n_points, + glyph->outline.n_contours, + &outlines[cur_glyph] ); + + /* copy the glyph outline into it */ + glyph->outline.high_precision = 0; + glyph->outline.second_pass = 0; + FT_Copy_Outline( &glyph->outline, &outlines[cur_glyph] ); + + /* center outline around 0 */ + { + FT_BBox bbox; + + FT_Get_Outline_CBox( &glyph->outline, &bbox ); + FT_Translate_Outline( &outlines[cur_glyph], + - ( bbox.xMax - bbox.xMin )/2, + - ( bbox.yMax - bbox.yMin )/2 ); + } + /* translate it */ + FT_Translate_Outline( &outlines[cur_glyph], + Bit.width * 32 , + Bit.rows * 32 ); + cur_glyph++; + + return FT_Err_Ok; + } + + +/*******************************************************************/ +/* */ +/* ConvertRaster: */ +/* */ +/* Performs scan conversion. */ +/* */ +/*******************************************************************/ + + FT_Error ConvertRaster( int index ) + { + outlines[index].second_pass = 0; + outlines[index].high_precision = 0; + + return FT_Get_Outline_Bitmap( library, &outlines[index], &Bit ); + } + + + static void Usage() + { + fprintf( stderr, "fttimer: simple performance timer -- part of the FreeType project\n" ); + fprintf( stderr, "-----------------------------------------------------------------\n\n" ); + fprintf( stderr, "Usage: fttimer [options] fontname[.ttf|.ttc]\n\n" ); + fprintf( stderr, "options:\n"); + fprintf( stderr, " -r : repeat count to be used (default is 1)\n" ); + fprintf( stderr, " -s : character pixel size (default is 600)\n" ); + fprintf( stderr, " -v : display results..\n" ); + fprintf( stderr, " -g : render anti-aliased glyphs\n" ); + exit(1); + } + + + int main( int argc, char** argv ) + { + int i, total, base, rendered_glyphs; + char filename[128 + 4]; + char alt_filename[128 + 4]; + char* execname; + grSurface* surface = 0; + + long t, t0, tz0; + + + execname = argv[0]; + + gray_render = 0; + visual = 0; + + while ( argc > 1 && argv[1][0] == '-' ) + { + switch ( argv[1][1] ) + { + case 'g': + gray_render = 1; + break; + + case 'v': + visual = 1; + break; + + case 's': + argc--; + argv++; + if ( argc < 2 || + sscanf( argv[1], "%d", &pixel_size ) != 1 ) + Usage(); + break; + + case 'r': + argc--; + argv++; + if ( argc < 2 || + sscanf( argv[1], "%d", &repeat_count ) != 1 ) + Usage(); + if (repeat_count < 1) + repeat_count = 1; + break; + + default: + fprintf( stderr, "Unknown argument '%s'!\n", argv[1] ); + Usage(); + } + argc--; + argv++; + } + + if ( argc != 2 ) + Usage(); + + i = strlen( argv[1] ); + while ( i > 0 && argv[1][i] != '\\' ) + { + if ( argv[1][i] == '.' ) + i = 0; + i--; + } + + filename[128] = '\0'; + alt_filename[128] = '\0'; + + strncpy( filename, argv[1], 128 ); + strncpy( alt_filename, argv[1], 128 ); + + if ( i >= 0 ) + { + strncpy( filename + strlen( filename ), ".ttf", 4 ); + strncpy( alt_filename + strlen( alt_filename ), ".ttc", 4 ); + } + + /* Initialize engine */ + + if ( (error = FT_Init_FreeType( &library )) ) + Panic( "Error while initializing engine" ); + + /* Load face */ + + error = FT_New_Face( library, filename, 0, &face ); + if ( error == FT_Err_Cannot_Open_Stream ) + Panic( "Could not find/open font resource" ); + else if ( error ) + Panic( "Error while opening font resource" ); + + /* get face properties and allocate preload arrays */ + + num_glyphs = face->num_glyphs; + glyph = face->glyph; + + tab_glyphs = MAX_GLYPHS; + if ( tab_glyphs > num_glyphs ) + tab_glyphs = num_glyphs; + + /* create size */ + + error = FT_Set_Pixel_Sizes( face, pixel_size, pixel_size ); + if ( error ) Panic( "Could not reset instance" ); + + bit.mode = gray_render ? gr_pixel_mode_gray : gr_pixel_mode_mono; + bit.width = 640; + bit.rows = 480; + bit.grays = 128; + + if ( visual ) + { + if ( !grInitDevices() ) + Panic( "Could not initialize graphics.\n" ); + + surface = grNewSurface( 0, &bit ); + if (!surface) + Panic( "Could not open graphics window/screen.\n" ); + } + else + { + if ( grNewBitmap( bit.mode, + bit.grays, + bit.width, + bit.rows, + &bit ) ) + Panic( "Could not create rendering buffer.\n" ); + } + + Init_Engine(); + + Num = 0; + Fail = 0; + + total = num_glyphs; + base = 0; + + rendered_glyphs = 0; + + t0 = 0; /* Initial time */ + + tz0 = Get_Time(); + + while ( total > 0 ) + { + int repeat; + + /* First, preload 'tab_glyphs' in memory */ + cur_glyph = 0; + cur_point = 0; + cur_contour = 0; + + printf( "loading %d glyphs", tab_glyphs ); + + for ( Num = 0; Num < tab_glyphs; Num++ ) + { + error = LoadChar( base + Num ); + if ( error ) + Fail++; + + total--; + } + + base += tab_glyphs; + + if ( tab_glyphs > total ) + tab_glyphs = total; + + printf( ", rendering... " ); + + /* Now, render the loaded glyphs */ + + t = Get_Time(); + + for ( repeat = 0; repeat < repeat_count; repeat++ ) + { + for ( Num = 0; Num < cur_glyph; Num++ ) + { + if ( (error = ConvertRaster( Num )) ) + Fail++; + + else + { + rendered_glyphs ++; + + if ( Num == 0 && visual ) + { + sprintf( Header, "Glyph: %5d", Num ); + grSetTitle( surface, Header ); + grRefreshSurface( surface ); + Clear_Buffer(); + } + } + } + } + + t = Get_Time() - t; + if ( t < 0 ) + t += 1000 * 60 * 60; + + printf( " = %f s\n", (double)t / 10000 ); + t0 += t; + + /* Now free all loaded outlines */ + for ( Num = 0; Num < cur_glyph; Num++ ) + FT_Done_Outline( library, &outlines[Num] ); + } + + tz0 = Get_Time() - tz0; + + FT_Done_Face( face ); + + printf( "\n" ); + printf( "rendered glyphs = %d\n", rendered_glyphs ); + printf( "render time = %f s\n", (double)t0 / 10000 ); + printf( "fails = %d\n", Fail ); + printf( "average glyphs/s = %f\n", + (double)rendered_glyphs / t0 * 10000 ); + + printf( "total timing = %f s\n", (double)tz0 / 10000 ); + printf( "Fails = %d\n", Fail ); + + FT_Done_FreeType( library ); + + exit( 0 ); /* for safety reasons */ + + return 0; /* never reached */ + } + + +/* End */ diff --git a/demos/src/fttry.c b/demos/src/fttry.c new file mode 100644 index 000000000..1dd878eb5 --- /dev/null +++ b/demos/src/fttry.c @@ -0,0 +1,155 @@ +/****************************************************************************/ +/* */ +/* The FreeType project -- a free and portable quality TrueType renderer. */ +/* */ +/* Copyright 1996-1998 by */ +/* D. Turner, R.Wilhelm, and W. Lemberg */ +/* */ +/* ftlint: a simple TrueType instruction tester. */ +/* */ +/* NOTE: This is just a test program that is used to show off and */ +/* debug the current engine. */ +/* */ +/****************************************************************************/ + +#include "freetype.h" + +#include +#include +#include + + +#define gettext( x ) ( x ) + + FT_Error error; + + FT_Library library; + FT_Face face; + + unsigned int num_glyphs; + int ptsize; + + int Fail; + int Num; + + + + static void Usage( char* name ) + { + printf( "fttry: simple TrueType instruction tester -- part of the FreeType project\n" ); + printf( "--------------------------------------------------------------------------\n" ); + printf( "\n" ); + printf( "Usage: %s ppem glyph fontname [fontname2..]\n\n", name ); + printf( " or %s -u glyph fontname [fontname2..]\n", name ); + printf( " to load an unscaled glyph\n\n" ); + + exit( 1 ); + } + + + static void Panic( const char* message ) + { + fprintf( stderr, "%s\n error code = 0x%04x\n", message, error ); + exit(1); + } + + int main( int argc, char** argv ) + { + int i, file_index, glyph_index; + char filename[128 + 4]; + char alt_filename[128 + 4]; + char* execname; + char* fname; + int load_unscaled = 0; + + execname = argv[0]; + + if ( argc < 3 ) + Usage( execname ); + + if ( argv[1][0] == '-' && + argv[1][1] == 'u' ) + { + load_unscaled = 1; + } + else + { + if ( sscanf( argv[1], "%d", &ptsize ) != 1 ) + Usage( execname ); + } + argc--; + argv++; + + if ( sscanf( argv[1], "%d", &glyph_index ) != 1 ) + Usage( execname ); + + error = FT_Init_FreeType( &library ); + if (error) Panic( "Could not create library object" ); + + /* Now check all files */ + for ( file_index = 2; file_index < argc; file_index++ ) + { + fname = argv[file_index]; + i = strlen( fname ); + while ( i > 0 && fname[i] != '\\' && fname[i] != '/' ) + { + if ( fname[i] == '.' ) + i = 0; + i--; + } + + filename[128] = '\0'; + alt_filename[128] = '\0'; + + strncpy( filename, fname, 128 ); + strncpy( alt_filename, fname, 128 ); + + if ( i >= 0 ) + { + strncpy( filename + strlen( filename ), ".ttf", 4 ); + strncpy( alt_filename + strlen( alt_filename ), ".ttc", 4 ); + } + + i = strlen( filename ); + fname = filename; + + while ( i >= 0 ) + if ( filename[i] == '/' || filename[i] == '\\' ) + { + fname = filename + i + 1; + i = -1; + } + else + i--; + + printf( "%s: ", fname ); + + /* Load face */ + error = FT_New_Face( library, filename, 0, &face ); + if (error) Panic( "Could not create face object" ); + + num_glyphs = face->num_glyphs; + + error = FT_Set_Char_Size( face, ptsize << 6, 0, 0, 0 ); + if (error) Panic( "Could not set character size" ); + + error = FT_Load_Glyph( face, + glyph_index, + load_unscaled ? FT_LOAD_NO_SCALE + : FT_LOAD_DEFAULT ); + if ( error == 0 ) + printf( "OK.\n" ); + else + printf( "Fail with error 0x%04x\n", error ); + + FT_Done_Face( face ); + } + + FT_Done_FreeType(library); + exit( 0 ); /* for safety reasons */ + + return 0; /* never reached */ + } + + +/* End */ diff --git a/demos/src/ftview.c b/demos/src/ftview.c new file mode 100644 index 000000000..74ebde00b --- /dev/null +++ b/demos/src/ftview.c @@ -0,0 +1,615 @@ +/****************************************************************************/ +/* */ +/* The FreeType project -- a free and portable quality TrueType renderer. */ +/* */ +/* Copyright 1996-1999 by */ +/* D. Turner, R.Wilhelm, and W. Lemberg */ +/* */ +/* */ +/* FTView - a simple font viewer. */ +/* */ +/* This is a new version using the MiGS graphics subsystem for */ +/* blitting and display. */ +/* */ +/* Press F1 when running this program to have a list of key-bindings */ +/* */ +/****************************************************************************/ + +#include "freetype.h" +#include "ftoutln.h" +#include "common.h" + +#include +#include +#include + +#include "graph.h" +#include "grfont.h" + +#define DIM_X 500 +#define DIM_Y 400 + +#define CENTER_X (bit.width/2) +#define CENTER_Y (bit.rows/2) + +#define MAXPTSIZE 500 /* dtp */ + + + char Header[128]; + char* new_header = 0; + + FT_Library library; /* the FreeType library */ + FT_Face face; /* the font face */ + FT_Size size; /* the font size */ + FT_GlyphSlot glyph; /* the glyph slot */ + + FT_Error error; /* error returned by FreeType ? */ + + grSurface* surface; /* current display surface */ + grBitmap bit; /* current display bitmap */ + + int num_glyphs; /* number of glyphs */ + int ptsize; /* current point size */ + + int hinted = 1; /* is glyph hinting active ? */ + int gray_render = 1; /* is anti-aliasing active ? */ + int use_sbits = 1; /* do we use embedded bitmaps ? */ + int low_prec = 1; /* force low precision */ + int Num; /* current first glyph index */ + + int res = 96; + + int Fail; + unsigned char autorun; + + int graph_init = 0; + + + /* PanicZ */ + static void PanicZ( const char* message ) + { + fprintf( stderr, "%s\n error = 0x%04x\n", message, error ); + exit(1); + } + + + /* Clears the Bit bitmap/pixmap */ + static void Clear_Display( void ) + { + long size = (long)bit.pitch * bit.rows; + memset( bit.buffer, 0, size ); + } + + + /* Initialize the display bitmap named Bit */ + static int Init_Display() + { + grInitDevices(); + + bit.mode = gr_pixel_mode_gray; + bit.width = DIM_X; + bit.rows = DIM_Y; + bit.grays = 128; + + surface = grNewSurface( 0, &bit ); + if (!surface) + PanicZ( "could not allocate display surface\n" ); + + graph_init = 1; + return 0; + } + + +#define MAX_BUFFER 65000 + +#define FLOOR(x) ((x) & -64) +#define CEIL(x) (((x)+63) & -64) +#define TRUNC(x) ((x) >> 6) + + static + char bit_buffer[ MAX_BUFFER ]; + + /* Render a single glyph */ + static FT_Error Render_Glyph( int x_offset, + int y_offset ) + { + /* first, render the glyph into an intermediate buffer */ + FT_Bitmap bit2; + grBitmap bit3; + int width, height, pitch, size; + int left, right, top, bottom; + + left = FLOOR( glyph->metrics.horiBearingX ); + right = CEIL( glyph->metrics.horiBearingX + glyph->metrics.width ); + width = TRUNC(right - left); + + top = CEIL( glyph->metrics.horiBearingY ); + bottom = FLOOR( glyph->metrics.horiBearingY - glyph->metrics.height ); + height = TRUNC( top - bottom ); + + if ( glyph->format == ft_glyph_format_outline ) + { + pitch = ( gray_render ? (width+3) & -4 : (width+7) >> 3 ); + size = pitch*height; + + if (size > MAX_BUFFER) + return FT_Err_Out_Of_Memory; + + bit2.width = width; + bit2.rows = height; + bit2.pitch = pitch; + bit2.pixel_mode = gray_render ? ft_pixel_mode_grays : ft_pixel_mode_mono; + bit2.buffer = bit_buffer; + + bit3.rows = bit2.rows; + bit3.width = bit2.width; + bit3.pitch = bit2.pitch; + bit3.mode = gray_render ? bit.mode : gr_pixel_mode_mono; + bit3.buffer = bit_buffer; + bit3.grays = 128; + + FT_Translate_Outline( &glyph->outline, -left, -bottom ); + memset( bit_buffer, 0, size ); + + if (low_prec) + glyph->outline.high_precision = 0; + + FT_Get_Outline_Bitmap( library, &glyph->outline, &bit2 ); + } + else + { + bit3.rows = glyph->bitmap.rows; + bit3.width = glyph->bitmap.width; + bit3.pitch = glyph->bitmap.pitch; + bit3.mode = gr_pixel_mode_mono; + bit3.buffer = glyph->bitmap.buffer; + bit3.grays = 0; + } + + /* Then, blit the image to the target surface */ + grBlitGlyphToBitmap( &bit, + &bit3, + x_offset + TRUNC(left), + y_offset - TRUNC(top), + (grColor)127L ); + return 0; + } + + + static FT_Error Reset_Scale( int pointSize ) + { + FT_Error error; + + error = FT_Set_Char_Size( face, pointSize << 6, + pointSize << 6, + res, + res ); + if ( error ) + { + } + return FT_Err_Ok; + } + + + static FT_Error LoadChar( int idx, int hint ) + { + int flags; + + flags = FT_LOAD_DEFAULT; + + if ( !hint ) + flags |= FT_LOAD_NO_HINTING; + + if ( !use_sbits ) + flags |= FT_LOAD_NO_BITMAP; + + return FT_Load_Glyph( face, idx, flags ); + } + + + + static FT_Error Render_All( int first_glyph, int ptsize ) + { + FT_F26Dot6 start_x, start_y, step_x, step_y, x, y; + int i; + + FT_Error error; + + + start_x = 4; + start_y = 16 + ptsize ; + + step_x = size->metrics.x_ppem + 4; + step_y = size->metrics.y_ppem + 10; + + x = start_x; + y = start_y; + + i = first_glyph; + + while ( i < num_glyphs ) + { + if ( !(error = LoadChar( i, hinted )) ) + { + Render_Glyph( x, y ); + + x += ( glyph->metrics.horiAdvance >> 6 ) + 1; + + if ( x + size->metrics.x_ppem > bit.width ) + { + x = start_x; + y += step_y; + + if ( y >= bit.rows ) + return FT_Err_Ok; + } + } + else + Fail++; + + i++; + } + + return FT_Err_Ok; + } + + + static void Help( ) + { + grEvent dummy_event; + + Clear_Display(); + grGotoxy( 0, 0 ); + grSetMargin( 2, 1 ); + grGotobitmap( &bit ); + + grWriteln("FreeType Glyph Viewer - part of the FreeType test suite" ); + grLn(); + grWriteln("This program is used to display all glyphs from one or" ); + grWriteln("several font files, with the FreeType library."); + grLn(); + grWriteln("Use the following keys :"); + grLn(); + grWriteln(" F1 or ? : display this help screen" ); + grWriteln(" a : toggle anti-aliasing" ); + grWriteln(" h : toggle outline hinting" ); + grWriteln(" b : toggle embedded bitmaps" ); + grWriteln(" l : toggle low precision rendering" ); + grLn(); + grWriteln(" Up : increase pointsize by 1 unit" ); + grWriteln(" Down : decrease pointsize by 1 unit" ); + grWriteln(" Page Up : increase pointsize by 10 units" ); + grWriteln(" Page Down : decrease pointsize by 10 units" ); + grLn(); + grWriteln(" Right : increment first glyph index" ); + grWriteln(" Left : decrement first glyph index" ); + grLn(); + grWriteln(" F5 : decrement first glyph index by 10" ); + grWriteln(" F6 : increment first glyph index by 10" ); + grWriteln(" F7 : decrement first glyph index by 100"); + grWriteln(" F8 : increment first glyph index by 100"); + grWriteln(" F9 : decrement first glyph index by 1000"); + grWriteln(" F10 : increment first glyph index by 1000"); + grLn(); + grWriteln("press any key to exit this help screen"); + + grRefreshSurface( surface ); + grListenSurface( surface, gr_event_key, &dummy_event ); + } + + + + static int Process_Event( grEvent* event ) + { + int i; + + switch ( event->key ) + { + case grKeyEsc: /* ESC or q */ + case grKEY('q'): + return 0; + + case grKEY('a'): + gray_render = !gray_render; + new_header = ( gray_render + ? "anti-aliasing is now on" + : "anti-aliasing is now off" ); + return 1; + + case grKEY('b'): + use_sbits = !use_sbits; + new_header = ( use_sbits + ? "embedded bitmaps are now used when available" + : "embedded bitmaps are now ignored" ); + return 1; + + case grKEY('n'): + case grKEY('p'): + return (int)event->key; + + case grKEY('l'): + low_prec = !low_prec; + new_header = ( low_prec + ? "rendering precision is now forced to low" + : "rendering precision is now normal" ); + break; + + case grKEY('h'): + hinted = !hinted; + new_header = ( hinted + ? "glyph hinting is now active" + : "glyph hinting is now ignored" ); + break; + + case grKeyF1: + case grKEY('?'): + Help(); + return 1; + +#if 0 + case grKeyF3: i = 16; goto Do_Rotate; + case grKeyF4: i = -16; goto Do_Rotate; + case grKeyF5: i = 1; goto Do_Rotate; + case grKeyF6: i = -1; goto Do_Rotate; +#endif + + case grKeyPageUp: i = 10; goto Do_Scale; + case grKeyPageDown: i = -10; goto Do_Scale; + case grKeyUp: i = 1; goto Do_Scale; + case grKeyDown: i = -1; goto Do_Scale; + + case grKeyLeft: i = -1; goto Do_Glyph; + case grKeyRight: i = 1; goto Do_Glyph; + case grKeyF7: i = -10; goto Do_Glyph; + case grKeyF8: i = 10; goto Do_Glyph; + case grKeyF9: i = -100; goto Do_Glyph; + case grKeyF10: i = 100; goto Do_Glyph; + case grKeyF11: i = -1000; goto Do_Glyph; + case grKeyF12: i = 1000; goto Do_Glyph; + default: + ; + } + return 1; + +#if 0 + Do_Rotate: + Rotation = (Rotation + i) & 1023; + return 1; +#endif + + Do_Scale: + ptsize += i; + if (ptsize < 1) ptsize = 1; + if (ptsize > MAXPTSIZE) ptsize = MAXPTSIZE; + return 1; + + Do_Glyph: + Num += i; + if (Num < 0) Num = 0; + if (Num >= num_glyphs) Num = num_glyphs-1; + return 1; + } + + + + static void usage( char* execname ) + { + fprintf( stderr, "\n" ); + fprintf( stderr, "ftview: simple glyph viewer -- part of the FreeType project\n" ); + fprintf( stderr, "-----------------------------------------------------------\n" ); + fprintf( stderr, "\n" ); + fprintf( stderr, "Usage: %s [options below] ppem fontname[.ttf|.ttc] ...\n", + execname ); + fprintf( stderr, "\n" ); + fprintf( stderr, " -r R use resolution R dpi (default: 72 dpi)\n" ); + fprintf( stderr, " -f index specify first glyph index to display\n" ); + fprintf( stderr, "\n" ); + + exit( 1 ); + } + + + int main( int argc, char** argv ) + { + int i, old_ptsize, orig_ptsize, file; + int first_glyph = 0; + int XisSetup = 0; + char filename[128 + 4]; + char alt_filename[128 + 4]; + char* execname; + int option; + int file_loaded; + + FT_Error error; + grEvent event; + + execname = ft_basename( argv[0] ); + + while ( 1 ) + { + option = getopt( argc, argv, "f:r:" ); + + if ( option == -1 ) + break; + + switch ( option ) + { + case 'f': + first_glyph = atoi( optarg ); + break; + + case 'r': + res = atoi( optarg ); + if ( res < 1 ) + usage( execname ); + break; + + default: + usage( execname ); + break; + } + } + + argc -= optind; + argv += optind; + + if ( argc <= 1 ) + usage( execname ); + + if ( sscanf( argv[0], "%d", &orig_ptsize ) != 1 ) + orig_ptsize = 64; + + file = 1; + + /* Initialize engine */ + error = FT_Init_FreeType( &library ); + if (error) PanicZ( "Could not initialise FreeType library" ); + +/* FT_Set_Raster_Palette( library, 17, palette_17 ); */ + + NewFile: + ptsize = orig_ptsize; + hinted = 1; + file_loaded = 0; + + i = strlen( argv[file] ); + while ( i > 0 && argv[file][i] != '\\' && argv[file][i] != '/' ) + { + if ( argv[file][i] == '.' ) + i = 0; + i--; + } + + filename[128] = '\0'; + alt_filename[128] = '\0'; + + strncpy( filename, argv[file], 128 ); + strncpy( alt_filename, argv[file], 128 ); + + if ( i >= 0 ) + { + strncpy( filename + strlen( filename ), ".ttf", 4 ); + strncpy( alt_filename + strlen( alt_filename ), ".ttc", 4 ); + } + + /* Load face */ + + error = FT_New_Face( library, filename, 0, &face ); + if (error) goto Display_Font; + + file_loaded++; + + error = Reset_Scale( ptsize ); + if (error) goto Display_Font; + + num_glyphs = face->num_glyphs; + glyph = face->glyph; + size = face->size; + + Display_Font: + /* initialise graphics if needed */ + if ( !XisSetup ) + { + XisSetup = 1; + Init_Display(); + } + + grSetTitle( surface, "FreeType Glyph Viewer - press F1 for help" ); + old_ptsize = ptsize; + + if ( file_loaded >= 1 ) + { + Fail = 0; + Num = first_glyph; + + if ( Num >= num_glyphs ) + Num = num_glyphs-1; + + if ( Num < 0 ) + Num = 0; + } + + for ( ;; ) + { + int key; + + Clear_Display(); + + if ( file_loaded >= 1 ) + { + Render_All( Num, ptsize ); + + sprintf( Header, "%s %s (file %s)", + face->family_name, + face->style_name, + ft_basename( filename ) ); + + if (!new_header) + new_header = Header; + + grWriteCellString( &bit, 0, 0, new_header, (grColor)127L ); + new_header = 0; + + sprintf( Header, "at %d points, first glyph = %d", + ptsize, + Num ); + } + else + { + sprintf( Header, "%s : is not a font file or could not be opened", + ft_basename(filename) ); + } + + grWriteCellString( &bit, 0, 8, Header, (grColor)127L ); + grRefreshSurface( surface ); + + grListenSurface( surface, 0, &event ); + if ( !( key = Process_Event( &event ) ) ) + goto Fin; + + if ( key == 'n' ) + { + if (file_loaded >= 1) + FT_Done_Face( face ); + + if ( file < argc - 1 ) + file++; + + goto NewFile; + } + + if ( key == 'p' ) + { + if (file_loaded >= 1) + FT_Done_Face( face ); + + if ( file > 1 ) + file--; + + goto NewFile; + } + + if ( ptsize != old_ptsize ) + { + if ( Reset_Scale( ptsize ) ) + PanicZ( "Could not resize font." ); + + old_ptsize = ptsize; + } + } + + Fin: +#if 0 + grDoneSurface(surface); + grDone(); +#endif + printf( "Execution completed successfully.\n" ); + printf( "Fails = %d\n", Fail ); + + exit( 0 ); /* for safety reasons */ + return 0; /* never reached */ +} + + +/* End */ + diff --git a/demos/src/t1dump.c b/demos/src/t1dump.c new file mode 100644 index 000000000..b349ebfda --- /dev/null +++ b/demos/src/t1dump.c @@ -0,0 +1,1031 @@ +/****************************************************************************/ +/* */ +/* t1dump.c 1.0 */ +/* */ +/* Copyright 1999 - The FreeType Project http://www.freetype.org */ +/* */ +/* T1Dump is a very simply Type 1 font dumper. It can be used to */ +/* write the following information to the standard ouput, or any */ +/* given file: */ +/* */ +/* - a description of the font file (including name, properties, etc..) */ +/* - the decrypted private dictionary, 'as is', i.e. in binary form */ +/* - the stream of tokens from the font file (useful to debug the */ +/* Type1 driver or to look at the font's internal structure..) */ +/* - the charstring commands of a given subroutine */ +/* - the charstring commands of a given glyph */ +/* - the encoding */ +/* - the glyph names */ +/* */ + +#include +#include + +#include "freetype.h" +#include +#include +#include +#include + +FT_Library library; /* root library object */ +FT_Face face; /* truetype face */ +T1_Face t1_face; +FT_Error error; +FILE* target; + + void Panic( const char* message ) + { + fprintf( stderr, "%s\n error code = 0x%04x\n", message, error ); + exit(1); + } + + +/**************************************************************************/ +/**************************************************************************/ +/**************************************************************************/ +/********** *********/ +/********** *********/ +/********** DUMP FONT INFORMATION *********/ +/********** *********/ +/********** *********/ +/**************************************************************************/ +/**************************************************************************/ +/**************************************************************************/ + + + static + T1_Error Dump_Font_Info( void ) + { + T1_FontInfo* info = &t1_face->font_info; + T1_Private* priv = &t1_face->private_dict; + T1_Int n; + + fprintf( target, "Font Name : %s\n", t1_face->font_name ); + + fprintf( target, "Version : %s\n", info->version ); + fprintf( target, "Full Name : %s\n", info->full_name ); + fprintf( target, "Family : %s\n", info->family_name ); + fprintf( target, "Weight : %s\n", info->weight ); + fprintf( target, "Italic angle : %ld\n", info->italic_angle ); + + fprintf( target, "Fixed pitch : %s\n", + info->is_fixed_pitch ? "yes" : "no" ); + + fprintf( target, "Underline : pos %d, thickness %d\n", + info->underline_position, + info->underline_thickness ); + + fprintf( target, "Unique ID : %d\n", priv->unique_id ); + fprintf( target, "lenIV : %d\n", priv->lenIV ); + + fprintf( target, "blues : [" ); + for ( n = 0; n < priv->num_blues; n++ ) + fprintf( target, " %d", priv->blue_values[n] ); + fprintf( target, " ]\n" ); + + fprintf( target, "other blues : [" ); + for ( n = 0; n < priv->num_other_blues; n++ ) + fprintf( target, " %d", priv->other_blues[n] ); + fprintf( target, " ]\n" ); + + fprintf( target, "family blues : [" ); + for ( n = 0; n < priv->num_family_blues; n++ ) + fprintf( target, " %d", priv->family_blues[n] ); + fprintf( target, " ]\n" ); + + fprintf( target, "family other : [" ); + for ( n = 0; n < priv->num_family_other_blues; n++ ) + fprintf( target, " %d", priv->family_other_blues[n] ); + fprintf( target, " ]\n" ); + + fprintf( target, "Blue scale : %f\n", priv->blue_scale*1.0/65536.0 ); + fprintf( target, "Blue shift : %d\n", priv->blue_shift ); + fprintf( target, "Blue fuzz : %d\n", priv->blue_fuzz ); + + fprintf( target, "Std width : %d\n", priv->standard_width ); + fprintf( target, "Std height : %d\n", priv->standard_height ); + fprintf( target, "Force bold : %s\n", priv->force_bold ? "yes" : "no" ); + fprintf( target, "Round stem : %s\n", priv->round_stem_up ? "yes" : "no" ); + + fprintf( target, "Stem snap W : [" ); + for ( n = 0; n < priv->num_snap_widths; n++ ) + fprintf( target, " %d", priv->stem_snap_widths[n] ); + fprintf( target, " ]\n" ); + + fprintf( target, "Stem snap H : [" ); + for ( n = 0; n < priv->num_snap_heights; n++ ) + fprintf( target, " %d", priv->stem_snap_heights[n] ); + fprintf( target, " ]\n" ); + + fprintf( target, "Language : %ld\n", priv->language_group ); + fprintf( target, "Password : %ld\n", priv->password ); + fprintf( target, "Min feature : [ %d %d ]\n", + priv->min_feature[0], + priv->min_feature[1] ); + + fprintf( target, "Font BBOX : [ %ld %ld %ld %ld ]\n", + t1_face->font_bbox.xMin, + t1_face->font_bbox.yMin, + t1_face->font_bbox.xMax, + t1_face->font_bbox.yMax ); + + fprintf( target, "Font matrix : [ %f %f %f %f ]\n", + 1.0*t1_face->font_matrix.xx/65536000.0, + 1.0*t1_face->font_matrix.xy/65536000.0, + 1.0*t1_face->font_matrix.yx/65536000.0, + 1.0*t1_face->font_matrix.yy/65536000.0 ); +#if 0 + fprintf( target, + fprintf( target, + fprintf( target, + fprintf( target, + fprintf( target, + fprintf( target, +#endif + fprintf( target, "Num glyphs : %d\n", t1_face->num_glyphs ); + fprintf( target, "Num subrs : %d\n", t1_face->num_subrs ); + + return 0; + } + + + +/**************************************************************************/ +/**************************************************************************/ +/**************************************************************************/ +/********** *********/ +/********** *********/ +/********** DUMP PRIVATE DICT IN RAW FORM *********/ +/********** *********/ +/********** *********/ +/**************************************************************************/ +/**************************************************************************/ +/**************************************************************************/ + + + static + T1_Error parse_int( T1_Tokenizer tokzer, + T1_Long* result ) + { + T1_Bool sign = 0; + T1_Long sum = 0; + T1_Token* token = &tokzer->token; + T1_Byte* base = tokzer->base + token->start; + T1_Byte* limit = base + token->len; + + 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: + *result = 0; + return T1_Err_Syntax_Error; + } + + + + + + static + T1_Error Dump_Private_Dict( const char* filename ) + { + struct FT_StreamRec_ stream_rec; + FT_Stream stream = &stream_rec; + T1_Error error; + T1_Tokenizer tokenizer; + + error = FT_New_Stream( filename, stream ); + if (error) return error; + + stream->memory = library->memory; + + error = New_Tokenizer( stream, &tokenizer ); + if (error) goto Exit; + + /* go directly to the Private dictionary */ + error = Open_PrivateDict( tokenizer ); + if (error) + Panic( "Could not open private dictionary !!" ); + + /* Write it to the target file */ + fwrite( tokenizer->base, tokenizer->limit, 1, target ); + + Exit: + if (stream->close) + stream->close(stream); + + return error; + } + + + +/**************************************************************************/ +/**************************************************************************/ +/**************************************************************************/ +/********** *********/ +/********** *********/ +/********** DUMP TYPE 1 TOKEN STREAM *********/ +/********** *********/ +/********** *********/ +/**************************************************************************/ +/**************************************************************************/ +/**************************************************************************/ + + + static + T1_Error Dump_Type1_Tokens( const char* filename ) + { + struct FT_StreamRec_ stream_rec; + FT_Stream stream = &stream_rec; + + T1_Error error; + T1_Tokenizer tokenizer; + + error = FT_New_Stream( filename, stream ); + if (error) return error; + + stream->memory = library->memory; + + error = New_Tokenizer( stream, &tokenizer ); + if (error) goto Exit; + + /* Dump the first segment of the Type1 font */ + do + { + T1_Token* token; + T1_String temp_string[128]; + T1_Int len; + + error = Read_Token( tokenizer ); + if (error) { error = 0; break; } + + /* dump the token */ + token = &tokenizer->token; + len = token->len; + if (len > 127) len = 127; + + strncpy( temp_string, + (T1_String*)(tokenizer->base + token->start), + len ); + temp_string[len] = '\0'; + + fprintf( target, "%s\n", temp_string ); + + /* Exit the loop when we encounter a "currentfile" token */ + if ( token->kind == tok_keyword && + token->kind2 == key_currentfile ) + break; + + } while (1); + + error = Open_PrivateDict( tokenizer ); + if (error) + Panic( "** could not open private dictionary **\n" ); + else + { + T1_Int num = 0; + T1_Bool last_num = 0; + + do + { + T1_Token* token; + T1_String temp_string[128]; + T1_Int len; + + error = Read_Token( tokenizer ); + if (error) { error = 0; break; } + + /* dump the token */ + token = &tokenizer->token; + len = token->len; + if (len > 127) len = 127; + + strncpy( temp_string, + (T1_String*)(tokenizer->base + token->start), + len ); + temp_string[len] = '\0'; + + /* detect "RD" uses */ + if ( token->kind == tok_keyword && + ( token->kind2 == key_RD || + token->kind2 == key_RD_alternate ) && + last_num ) + { + fprintf( target, "%s [%d binary bytes] ", temp_string, num ); + tokenizer->cursor += num; + } + else + { + fprintf( target, "%s\n", temp_string ); + + /* exit dump when we encounter a 'closefile' */ + if ( token->kind == tok_keyword && + token->kind2 == key_closefile ) + break; + + /* record numerical value if any */ + if ( token->kind == tok_number ) + { + T1_Long sum; + + if ( !parse_int( tokenizer, &sum ) ) + { + num = sum; + last_num = 1; + } + else + last_num = 0; + } + else + last_num = 0; + } + + } while (1); + } + + Exit: + if (stream->close) + stream->close(stream); + return error; + } + + +/**************************************************************************/ +/**************************************************************************/ +/**************************************************************************/ +/********** *********/ +/********** *********/ +/********** DUMP CHARACTER ENCODING *********/ +/********** *********/ +/********** *********/ +/**************************************************************************/ +/**************************************************************************/ +/**************************************************************************/ + + + static + void Dump_Encoding( void ) + { + T1_Encoding* encode = &t1_face->encoding; + int n; + + fprintf( target, "characters count = %d\n", encode->num_chars ); + + fprintf( target, "first code = %d, last code = %d\n", + encode->code_first, encode->code_last ); + + for ( n = 0; n < encode->num_chars; n++ ) + { + int code = (int)encode->char_index[n]; + + if (code || n == 0) + fprintf( target, "%3d %s\n", n, t1_face->glyph_names[code] ); + } + } + + +/**************************************************************************/ +/**************************************************************************/ +/**************************************************************************/ +/********** *********/ +/********** *********/ +/********** DUMP SUBROUTINES AND GLYPH CHARSTRINGS *********/ +/********** *********/ +/********** *********/ +/**************************************************************************/ +/**************************************************************************/ +/**************************************************************************/ + + + static + void Dump_CharStrings( T1_Byte* base, + T1_Int len ) + { + T1_Byte* cur = base; + T1_Byte* limit = base + len; + T1_String temp_name[128]; + T1_String* string; + + T1_Int x = 0; + + while ( cur < limit ) + { + switch (*cur++) + { + case 1: string = "hstem"; break; + + case 3: string = "vstem"; break; + case 4: string = "vmoveto"; break; + case 5: string = "rlineto"; break; + case 6: string = "hlineto"; break; + case 7: string = "vlineto"; break; + case 8: string = "rrcurveto"; break; + case 9: string = "closepath"; break; + case 10: string = "callsubr"; break; + case 11: string = "return"; break; + + case 13: string = "hsbw"; break; + case 14: string = "endchar"; break; + + case 21: string = "rmoveto"; break; + case 22: string = "hmoveto"; break; + + case 30: string = "vhcurveto"; break; + case 31: string = "hvcurveto"; break; + + case 12: + { + if (cur > limit) + Panic( "invalid charstrings stream\n" ); + + switch (*cur++) + { + case 0: string = "dotsection"; break; + case 1: string = "vstem3"; break; + case 2: string = "hstem3"; break; + case 6: string = "seac"; break; + case 7: string = "sbw"; break; + case 12: string = "div"; break; + case 16: string = "callothersubr"; break; + case 17: string = "pop"; break; + case 33: string = "setcurrentpoint"; break; + + default: + sprintf( temp_name, "escape(12)+unknown(%d)", cur[1] ); + string = temp_name; + } + } + break; + + case 255: /* four bytes integer */ + { + T1_Long sum; + + if (cur+4 > limit) + Panic( "invalid charstrings stream\n" ); + + sum = ((long)cur[0] << 24) | + ((long)cur[1] << 16) | + ((long)cur[2] << 8) | + cur[3]; + sprintf( temp_name, "%ld ", sum ); + string = temp_name; + cur += 4; + } + break; + + default: + if (cur[-1] >= 32) + { + if (cur[-1] < 247) + { + sprintf( temp_name, "%ld", (long)cur[-1] - 139 ); + } + else if (cur[-1] < 251) + { + cur++; + sprintf( temp_name, "%ld", + ((long)(cur[-2]-247) << 8) + cur[-1] + 108 ); + } + else + { + cur++; + sprintf( temp_name, "%ld", + -((long)(cur[-2]-251) << 8) - cur[-1] - 108 ); + } + string = temp_name; + } + else + { + sprintf( temp_name, "unknown(%d)", cur[-1] ); + string = temp_name; + } + } + + /* now print the charstring command */ + { + int len = strlen(string)+1; + + if ( x+len > 60 ) + { + x = 0; + fprintf( target, "\n" ); + } + else + fprintf( target, " " ); + + fprintf( target, "%s", string ); + x += len; + } + } + } + + + + static + void Dump_Glyph( int glyph_index ) + { + fprintf( target, "glyph name: %s\n", t1_face->glyph_names[glyph_index] ); + Dump_CharStrings( t1_face->charstrings [glyph_index], + t1_face->charstrings_len [glyph_index] ); + } + + static + void Dump_Subrs( int subrs_index ) + { + Dump_CharStrings( t1_face->subrs [ subrs_index ], + t1_face->subrs_len[ subrs_index ] ); + } + + + +/**************************************************************************/ +/**************************************************************************/ +/**************************************************************************/ +/********** *********/ +/********** *********/ +/********** EXECUTE GLYPH CHARSTRINGS *********/ +/********** *********/ +/********** *********/ +/**************************************************************************/ +/**************************************************************************/ +/**************************************************************************/ + + + static + T1_Error operator_endchar( T1_Builder* builder ) + { + (void)builder; + fprintf( target, "endchar\n" ); + return 0; + } + + + static + T1_Error operator_sbw( T1_Builder* builder, + T1_Pos sbx, + T1_Pos sby, + T1_Pos wx, + T1_Pos wy ) + { + (void)builder; + fprintf( target, "set bearing [%ld,%ld] width [%ld,%ld]\n", + sbx, sby, wx, wy ); + return 0; + } + +#if 0 + static + T1_Error operator_seac( T1_Builder* builder, + T1_Pos asb, + T1_Pos adx, + T1_Pos ady, + T1_Int bchar, + T1_Int achar ) + { + (void)builder; + fprintf( target, "accented char: %ld [%ld,%ld] b=%d, a=%d\n", + asb, adx, ady, bchar, achar ); + return 0; + } +#endif + + static + T1_Error operator_closepath( T1_Builder* builder ) + { + (void)builder; + fprintf( target, "closepath\n" ); + return 0; + } + + + static + T1_Error operator_rlineto( T1_Builder* builder, + T1_Pos dx, + T1_Pos dy ) + { + (void)builder; + fprintf( target, "%ld %ld rlineto\n", dx, dy ); + return 0; + } + + + static + T1_Error operator_rmoveto( T1_Builder* builder, + T1_Pos dx, + T1_Pos dy ) + { + (void)builder; + fprintf( target, "%ld %ld rmoveto\n", dx, dy ); + return 0; + } + + + static + T1_Error operator_rrcurveto( T1_Builder* builder, + T1_Pos dx1, + T1_Pos dy1, + T1_Pos dx2, + T1_Pos dy2, + T1_Pos dx3, + T1_Pos dy3 ) + { + (void)builder; + fprintf( target, "%ld %ld %ld %ld %ld %ld rrcurveto\n", + dx1, dy1, dx2, dy2, dx3, dy3 ); + return 0; + } + + + static + T1_Error operator_dotsection( T1_Builder* builder ) + { + (void)builder; + fprintf( target, "dotsection\n" ); + return 0; + } + + + static + T1_Error operator_stem( T1_Builder* builder, + T1_Pos pos, + T1_Pos width, + T1_Bool vertical ) + { + (void)builder; + fprintf( target, "%ld %ld %s\n", pos, width, + vertical ? "vstem" : "hstem" ); + return 0; + } + + + static + T1_Error operator_stem3( T1_Builder* builder, + T1_Pos pos0, + T1_Pos width0, + T1_Pos pos1, + T1_Pos width1, + T1_Pos pos2, + T1_Pos width2, + T1_Bool vertical ) + { + (void)builder; + fprintf( target, "%ld %ld %ld %ld %ld %ld %s\n", + pos0, width0, pos1, width1, pos2, width2, + vertical ? "vstem3" : "hstem3" ); + return 0; + } + + +#if 0 + static + T1_Error operator_flex( T1_Builder* builder, + T1_Pos threshold, + T1_Pos end_x, + T1_Pos end_y ) + { + (void)builder; + fprintf( target, "%ld %ld %ld flex\n", threshold, end_x, end_y ); + return 0; + } +#endif + + static + T1_Error operator_changehints( T1_Builder* builder ) + { + (void)builder; + fprintf( target, "-- change hints --\n" ); + return 0; + } + + + static + T1_Error Execute_CharString( int glyph_index ) + { + static const T1_Builder_Funcs builds = + { + operator_endchar, + operator_sbw, + operator_closepath, + operator_rlineto, + operator_rmoveto, + operator_rrcurveto, + }; + + static const T1_Hinter_Funcs hints = + { + operator_dotsection, + operator_changehints, + operator_stem, + operator_stem3, + }; + + T1_Decoder decoder; + T1_Error error; + + T1_Init_Decoder( &decoder, &hints ); + T1_Init_Builder( &decoder.builder, t1_face, 0, 0, &builds ); + + error = T1_Parse_CharStrings( &decoder, + t1_face->charstrings [glyph_index], + t1_face->charstrings_len[glyph_index], + t1_face->num_subrs, + t1_face->subrs, + t1_face->subrs_len ); + return error; + } + + + + + + + + +/**************************************************************************/ +/**************************************************************************/ +/**************************************************************************/ +/********** *********/ +/********** *********/ +/********** DEBUG FONT LOADING *********/ +/********** *********/ +/********** *********/ +/**************************************************************************/ +/**************************************************************************/ +/**************************************************************************/ + + static + T1_Error Debug_Type1_Font( const char* filename ) + { + struct FT_StreamRec_ stream_rec; + T1_FaceRec t1facerec; + T1_Tokenizer tokenizer; + T1_Parser parser; + T1_Error error; + FT_Stream stream = &stream_rec; + + error = FT_New_Stream( filename, stream ); + if (error) goto Exit; + + stream->memory = library->memory; + + /* create an empty face record */ + memset( &t1facerec, 0, sizeof(t1facerec) ); + t1facerec.root.memory = library->memory; + t1facerec.root.stream = stream; + + t1_face = &t1facerec; + + /* open the tokenizer, this will also check the font format */ + error = New_Tokenizer( stream, &tokenizer ); + if (error) goto Fail; + + /* Now, load the font program into the face object */ + Init_T1_Parser( &parser, t1_face, tokenizer ); + + /* force token dump */ + parser.dump_tokens = 1; + + error = Parse_T1_FontProgram( &parser ); + + Done_Tokenizer( tokenizer ); + + Fail: + if (stream->close) + stream->close( stream ); + Exit: + return error; + } + +/**************************************************************************/ +/**************************************************************************/ +/**************************************************************************/ +/********** *********/ +/********** *********/ +/********** MAIN PROGRAM *********/ +/********** *********/ +/********** *********/ +/**************************************************************************/ +/**************************************************************************/ +/**************************************************************************/ + + + static + void Usage() + { + fprintf( stderr, "t1dump - a simple Type 1 font dumper\n" ); + fprintf( stderr, "(c) The FreeType project - www.freetype.org\n" ); + fprintf( stderr, "-------------------------------------------\n\n" ); + + fprintf( stderr, "usage : t1dump [options] fontfile(.pfb|.pfa)\n\n" ); + + fprintf( stderr, " options\n" ); + fprintf( stderr, " -o filename : dumps to a specific file\n" ); + fprintf( stderr, " -g index : dump glyph charstring\n" ); + fprintf( stderr, " -s index : dump subrs charstring\n" ); + fprintf( stderr, " -x index : execute glyph charstring\n" ); + fprintf( stderr, " -e : dump encoding\n" ); + fprintf( stderr, " -t : dumps the Type 1 token stream\n" ); + fprintf( stderr, " -d : debug font loading\n" ); + fprintf( stderr, " -p : dumps private dictionary 'as is'\n\n" ); + + exit(1); + } + + +typedef enum Request_ +{ + req_dump_info, + req_dump_private, + req_dump_tokens, + req_dump_encoding, + req_dump_glyph, + req_dump_subr, + req_load_font, + req_execute_glyph, + req_debug_font + +} Request; + + +static char* file_name; +static int glyph_index; +static Request request = req_dump_info; + +static FT_Driver t1_driver; + + int main( int argc, char** argv ) + { + char valid; + + + /* Check number of arguments */ + if ( argc < 2 ) Usage(); + + /* Check options */ + target = stdout; + + argv++; + while (argv[0][0] == '-') + { + valid = 0; + switch (argv[0][1]) + { + case 'p': + request = req_dump_private; + valid = 1; + break; + + case 't': + request = req_dump_tokens; + valid = 1; + break; + + case 'e': + request = req_dump_encoding; + valid = 1; + break; + + case 'd': + request = req_debug_font; + valid = 1; + break; + + case 'o': + if (argc < 2) Usage(); + target = fopen( argv[1], "w" ); + if (!target) + Panic( "Could not open/create destination file" ); + argv++; + argc--; + valid = 1; + break; + + case 'g': + case 's': + case 'x': + if (argc < 2) Usage(); + if ( sscanf( argv[1], "%d", &glyph_index ) != 1 ) + Usage(); + + switch (argv[0][1]) + { + case 'g': request = req_dump_glyph; break; + case 's': request = req_dump_subr; break; + case 'x': request = req_execute_glyph; break; + } + argv++; + argc--; + valid = 1; + break; + + default: + ; + } + + if (valid) + { + argv++; + argc--; + if (argc < 2) Usage(); + } + else + break; + } + + /* Get file name */ + file_name = argv[0]; + + /* Instead of calling FT_Init_FreeType, we set up our own system */ + /* object and library. This is reserved for FreeType 2 wizards !! */ + + /* Init library, read face object, get driver, create size */ + error = FT_Init_FreeType( &library ); + if (error) Panic( "could not initialise FreeType library" ); + + t1_driver = FT_Get_Driver( library, "type1" ); + if (!t1_driver) Panic( "no Type1 driver in current FreeType lib" ); + + error = FT_New_Face( library, file_name, 0, &face ); + if (error) Panic( "could not find/open/create font file" ); + + if (face->driver != t1_driver) + Panic( "font format is not Type 1 !" ); + + switch (request) + { + case req_dump_private: + error = Dump_Private_Dict(file_name); + break; + + case req_dump_tokens: + error = Dump_Type1_Tokens(file_name); + break; + + case req_debug_font: + error = Debug_Type1_Font(file_name); + break; + + default: + error = FT_New_Face( library, file_name, 0, &face ); + if (error) Panic( "could not load Type 1 font" ); + + t1_face = (T1_Face)face; + + /* check glyph index, it is 0 by default */ + if ( glyph_index < 0 || glyph_index >= t1_face->num_glyphs ) + Panic( "invalid glyph index\n" ); + + switch (request) + { + case req_dump_glyph: + Dump_Glyph( glyph_index ); + break; + + case req_dump_subr: + Dump_Subrs( glyph_index ); + break; + + case req_execute_glyph: + Execute_CharString( glyph_index ); + break; + + case req_dump_encoding: + Dump_Encoding(); + break; + + default: + Dump_Font_Info(); + } + } + + if (error) Panic( "could not dump Type 1 font" ); + + FT_Done_FreeType( library ); + return 0; + } diff --git a/demos/src/ttdebug.c b/demos/src/ttdebug.c new file mode 100644 index 000000000..b885dda77 --- /dev/null +++ b/demos/src/ttdebug.c @@ -0,0 +1,1247 @@ +#include +#include + +#ifdef UNIX +#ifndef HAVE_POSIX_TERMIOS +#include +#include +#else +#ifndef HAVE_TCGETATTR +#define HAVE_TCGETATTR +#endif /* HAVE_TCGETATTR */ +#ifndef HAVE_TCSETATTR +#define HAVE_TCSETATTR +#endif /* HAVE_TCSETATTR */ +#include +#endif /* HAVE_POSIX_TERMIOS */ +#endif + +/* Define the `getch()' function. On Unix systems, it is an alias */ +/* for `getchar()', and the debugger front end must ensure that the */ +/* `stdin' file descriptor is not in line-by-line input mode. */ +#ifndef UNIX +#include +#else +#define getch getchar +#endif + + +#include "freetype.h" +#include "ttobjs.h" +#include "ttdriver.h" +#include "ttinterp.h" + + +FT_Library library; /* root library object */ +FT_Memory memory; /* system object */ +TT_Driver driver; /* truetype driver */ +TT_Face face; /* truetype face */ +TT_Size size; /* truetype size */ +TT_GlyphSlot glyph; /* truetype glyph slot */ +TT_ExecContext exec; /* truetype execution context */ +TT_Error error; + +TT_CodeRange_Tag debug_coderange = tt_coderange_glyph; + + typedef FT_Byte ByteStr[2]; + typedef FT_Byte WordStr[4]; + typedef FT_Byte LongStr[8]; + typedef FT_Byte DebugStr[128]; + + static DebugStr tempStr; + +#undef PACK +#define PACK( x, y ) ((x << 4) | y) + + static const TT_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_String* OpStr[256] = { + "SVTCA y", /* Set vectors to coordinate axis y */ + "SVTCA x", /* Set vectors to coordinate axis x */ + "SPvTCA y", /* Set Proj. vec. to coord. axis y */ + "SPvTCA x", /* Set Proj. vec. to coord. axis x */ + "SFvTCA y", /* Set Free. vec. to coord. axis y */ + "SFvTCA x", /* Set Free. vec. to coord. axis x */ + "SPvTL //", /* Set Proj. vec. parallel to segment */ + "SPvTL +", /* Set Proj. vec. normal to segment */ + "SFvTL //", /* Set Free. vec. parallel to segment */ + "SFvTL +", /* Set Free. vec. normal to segment */ + "SPvFS", /* Set Proj. vec. from stack */ + "SFvFS", /* Set Free. vec. from stack */ + "GPV", /* Get projection vector */ + "GFV", /* Get freedom vector */ + "SFvTPv", /* Set free. vec. to proj. vec. */ + "ISECT", /* compute intersection */ + + "SRP0", /* Set reference point 0 */ + "SRP1", /* Set reference point 1 */ + "SRP2", /* Set reference point 2 */ + "SZP0", /* Set Zone Pointer 0 */ + "SZP1", /* Set Zone Pointer 1 */ + "SZP2", /* Set Zone Pointer 2 */ + "SZPS", /* Set all zone pointers */ + "SLOOP", /* Set loop counter */ + "RTG", /* Round to Grid */ + "RTHG", /* Round to Half-Grid */ + "SMD", /* Set Minimum Distance */ + "ELSE", /* Else */ + "JMPR", /* Jump Relative */ + "SCvTCi", /* Set CVT */ + "SSwCi", /* */ + "SSW", /* */ + + "DUP", + "POP", + "CLEAR", + "SWAP", + "DEPTH", + "CINDEX", + "MINDEX", + "AlignPTS", + "INS_$28", + "UTP", + "LOOPCALL", + "CALL", + "FDEF", + "ENDF", + "MDAP[-]", + "MDAP[r]", + + "IUP[y]", + "IUP[x]", + "SHP[0]", + "SHP[1]", + "SHC[0]", + "SHC[1]", + "SHZ[0]", + "SHZ[1]", + "SHPIX", + "IP", + "MSIRP[0]", + "MSIRP[1]", + "AlignRP", + "RTDG", + "MIAP[-]", + "MIAP[r]", + + "NPushB", + "NPushW", + "WS", + "RS", + "WCvtP", + "RCvt", + "GC[0]", + "GC[1]", + "SCFS", + "MD[0]", + "MD[1]", + "MPPEM", + "MPS", + "FlipON", + "FlipOFF", + "DEBUG", + + "LT", + "LTEQ", + "GT", + "GTEQ", + "EQ", + "NEQ", + "ODD", + "EVEN", + "IF", + "EIF", + "AND", + "OR", + "NOT", + "DeltaP1", + "SDB", + "SDS", + + "ADD", + "SUB", + "DIV", + "MUL", + "ABS", + "NEG", + "FLOOR", + "CEILING", + "ROUND[G]", + "ROUND[B]", + "ROUND[W]", + "ROUND[?]", + "NROUND[G]", + "NROUND[B]", + "NROUND[W]", + "NROUND[?]", + + "WCvtF", + "DeltaP2", + "DeltaP3", + "DeltaC1", + "DeltaC2", + "DeltaC3", + "SROUND", + "S45Round", + "JROT", + "JROF", + "ROFF", + "INS_$7B", + "RUTG", + "RDTG", + "SANGW", + "AA", + + "FlipPT", + "FlipRgON", + "FlipRgOFF", + "INS_$83", + "INS_$84", + "ScanCTRL", + "SDPVTL[0]", + "SDPVTL[1]", + "GetINFO", + "IDEF", + "ROLL", + "MAX", + "MIN", + "ScanTYPE", + "IntCTRL", + "INS_$8F", + + "INS_$90", + "INS_$91", + "INS_$92", + "INS_$93", + "INS_$94", + "INS_$95", + "INS_$96", + "INS_$97", + "INS_$98", + "INS_$99", + "INS_$9A", + "INS_$9B", + "INS_$9C", + "INS_$9D", + "INS_$9E", + "INS_$9F", + + "INS_$A0", + "INS_$A1", + "INS_$A2", + "INS_$A3", + "INS_$A4", + "INS_$A5", + "INS_$A6", + "INS_$A7", + "INS_$A8", + "INS_$A9", + "INS_$AA", + "INS_$AB", + "INS_$AC", + "INS_$AD", + "INS_$AE", + "INS_$AF", + + "PushB[0]", + "PushB[1]", + "PushB[2]", + "PushB[3]", + "PushB[4]", + "PushB[5]", + "PushB[6]", + "PushB[7]", + "PushW[0]", + "PushW[1]", + "PushW[2]", + "PushW[3]", + "PushW[4]", + "PushW[5]", + "PushW[6]", + "PushW[7]", + + "MDRP[G]", + "MDRP[B]", + "MDRP[W]", + "MDRP[?]", + "MDRP[rG]", + "MDRP[rB]", + "MDRP[rW]", + "MDRP[r?]", + "MDRP[mG]", + "MDRP[mB]", + "MDRP[mW]", + "MDRP[m?]", + "MDRP[mrG]", + "MDRP[mrB]", + "MDRP[mrW]", + "MDRP[mr?]", + "MDRP[pG]", + "MDRP[pB]", + + "MDRP[pW]", + "MDRP[p?]", + "MDRP[prG]", + "MDRP[prB]", + "MDRP[prW]", + "MDRP[pr?]", + "MDRP[pmG]", + "MDRP[pmB]", + "MDRP[pmW]", + "MDRP[pm?]", + "MDRP[pmrG]", + "MDRP[pmrB]", + "MDRP[pmrW]", + "MDRP[pmr?]", + + "MIRP[G]", + "MIRP[B]", + "MIRP[W]", + "MIRP[?]", + "MIRP[rG]", + "MIRP[rB]", + "MIRP[rW]", + "MIRP[r?]", + "MIRP[mG]", + "MIRP[mB]", + "MIRP[mW]", + "MIRP[m?]", + "MIRP[mrG]", + "MIRP[mrB]", + "MIRP[mrW]", + "MIRP[mr?]", + "MIRP[pG]", + "MIRP[pB]", + + "MIRP[pW]", + "MIRP[p?]", + "MIRP[prG]", + "MIRP[prB]", + "MIRP[prW]", + "MIRP[pr?]", + "MIRP[pmG]", + "MIRP[pmB]", + "MIRP[pmW]", + "MIRP[pm?]", + "MIRP[pmrG]", + "MIRP[pmrB]", + "MIRP[pmrW]", + "MIRP[pmr?]" + }; + + +/********************************************************************* + * + * Init_Keyboard : set the input file descriptor to char-by-char + * mode on Unix.. + * + *********************************************************************/ + +#ifdef UNIX + + struct termios old_termio; + + static + void Init_Keyboard( void ) + { + struct termios termio; + +#ifndef HAVE_TCGETATTR + ioctl( 0, TCGETS, &old_termio ); +#else + tcgetattr( 0, &old_termio ); +#endif + + termio = old_termio; + +/* termio.c_lflag &= ~(ICANON+ECHO+ECHOE+ECHOK+ECHONL+ECHOKE); */ + termio.c_lflag &= ~(ICANON+ECHO+ECHOE+ECHOK+ECHONL); + +#ifndef HAVE_TCSETATTR + ioctl( 0, TCSETS, &termio ); +#else + tcsetattr( 0, TCSANOW, &termio ); +#endif + } + + static + void Reset_Keyboard( void ) + { +#ifndef HAVE_TCSETATTR + ioctl( 0, TCSETS, &old_termio ); +#else + tcsetattr( 0, TCSANOW, &old_termio ); +#endif + + } + +#else + + static + void Init_Keyboard( void ) + { + } + + static + void Reset_Keyboard( void ) + { + } + +#endif + + + void Panic( const char* message ) + { + fprintf( stderr, "%s\n error code = 0x%04x\n", message, error ); + Reset_Keyboard(); + exit(1); + } + + +/****************************************************************** + * + * Function : Calc_Length + * + * Description : Computes the length in bytes of current opcode. + * + *****************************************************************/ + +#define CUR (*exc) + + + static void Calc_Length( TT_ExecContext exc ) + { + CUR.opcode = CUR.code[CUR.IP]; + + switch ( CUR.opcode ) + { + case 0x40: + if ( CUR.IP + 1 >= CUR.codeSize ) + Panic( "code range overflow !!" ); + + CUR.length = CUR.code[CUR.IP + 1] + 2; + break; + + case 0x41: + if ( CUR.IP + 1 >= CUR.codeSize ) + Panic( "code range overflow !!" ); + + CUR.length = CUR.code[CUR.IP + 1] * 2 + 2; + break; + + case 0xB0: + case 0xB1: + case 0xB2: + case 0xB3: + case 0xB4: + case 0xB5: + case 0xB6: + case 0xB7: + CUR.length = CUR.opcode - 0xB0 + 2; + break; + + case 0xB8: + case 0xB9: + case 0xBA: + case 0xBB: + case 0xBC: + case 0xBD: + case 0xBE: + case 0xBF: + CUR.length = (CUR.opcode - 0xB8) * 2 + 3; + break; + + default: + CUR.length = 1; + break; + } + + /* make sure result is in range */ + + if ( CUR.IP + CUR.length > CUR.codeSize ) + Panic( "code range overflow !!" ); + } + + + /* Disassemble the current line */ + /* */ + const FT_String* Cur_U_Line( TT_ExecContext exec ) + { + FT_String s[32]; + FT_Int op, i, n; + + op = exec->code[ exec->IP ]; + + sprintf( tempStr, "%04lx: %02hx %s", exec->IP, op, OpStr[op] ); + + if ( op == 0x40 ) + { + n = exec->code[ exec->IP+1 ]; + sprintf( s, "(%d)", n ); + strncat( tempStr, s, 8 ); + + if ( n > 20 ) n = 20; /* limit output */ + + for ( i = 0; i < n; i++ ) + { + sprintf( s, " $%02hx", exec->code[ exec->IP+i+2 ] ); + strncat( tempStr, s, 8 ); + } + } + else if ( op == 0x41 ) + { + n = exec->code[ exec->IP+1 ]; + sprintf( s, "(%d)", n ); + strncat( tempStr, s, 8 ); + + if (n > 20) n = 20; /* limit output */ + + for ( i = 0; i < n; i++ ) + { + sprintf( s, " $%02hx%02hx", exec->code[ exec->IP+i*2+2 ], + exec->code[ exec->IP+i*2+3 ] ); + strncat( tempStr, s, 8 ); + } + } + else if ( (op & 0xF8) == 0xB0 ) + { + n = op-0xB0; + + for ( i=0; i <= n; i++ ) + { + sprintf( s, " $%02hx", exec->code[ exec->IP+i+1 ] ); + strncat( tempStr, s, 8 ); + } + } + else if ( (op & 0xF8) == 0xB8 ) + { + n = op-0xB8; + + for ( i = 0; i <= n; i++ ) + { + sprintf( s, " $%02hx%02hx", exec->code[ exec->IP+i*2+1 ], + exec->code[ exec->IP+i*2+2 ] ); + strncat( tempStr, s, 8 ); + } + } + + return (FT_String*)tempStr; + } + + + static + TT_Error RunIns( TT_ExecContext exc ) + { + FT_Int A, diff, key; + FT_Long next_IP; + FT_Char ch, oldch, *temp; + + TT_Error error = 0; + + TT_GlyphZone save; + TT_GlyphZone pts; + + const FT_String* round_str[8] = + { + "to half-grid", + "to grid", + "to double grid", + "down to grid", + "up to grid", + "off", + "super", + "super 45" + }; + + /* only debug the requested code range */ + if (exc->curRange != (TT_Int)debug_coderange) + return TT_RunIns(exc); + + exc->pts.n_points = exc->zp0.n_points; + exc->pts.n_contours = exc->zp0.n_contours; + + pts = exc->pts; + + + save.n_points = pts.n_points; + save.n_contours = pts.n_contours; + + save.org = (TT_Vector*)malloc( 2 * sizeof( TT_F26Dot6 ) * + save.n_points ); + save.cur = (TT_Vector*)malloc( 2 * sizeof( TT_F26Dot6 ) * + save.n_points ); + save.touch = (TT_Byte*)malloc( save.n_points ); + + exc->instruction_trap = 1; + + do + { + if ( CUR.IP < CUR.codeSize ) + { + Calc_Length( exc ); + + 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. */ + + /* Print the current line. We use a 80-columns console with the */ + /* following formatting: */ + /* */ + /* [loc]:[addr] [opcode] [disassemby] [a][b]|[c][d] */ + /* */ + + { + char temp[80]; + int n, col, pop; + int args = CUR.args; + + sprintf( temp, "%78c\n", ' ' ); + + /* first letter of location */ + switch ( CUR.curRange ) + { + case tt_coderange_glyph: + temp[0] = 'g'; + break; + case tt_coderange_cvt: + temp[0] = 'c'; + break; + default: + temp[0] = 'f'; + } + + /* current IP */ + sprintf( temp+1, "%04lx: %02x %-36.36s", + CUR.IP, + CUR.opcode, + Cur_U_Line(&CUR) ); + + strncpy( temp+46, " (", 2 ); + + args = CUR.top - 1; + pop = Pop_Push_Count[CUR.opcode] >> 4; + col = 48; + for ( n = 6; n > 0; n-- ) + { + if ( pop == 0 ) + temp[col-1] = (temp[col-1] == '(' ? ' ' : ')' ); + + if ( args < CUR.top && args >= 0 ) + sprintf( temp+col, "%04lx", CUR.stack[args] ); + else + sprintf( temp+col, " " ); + + temp[col+4] = ' '; + col += 5; + pop--; + args--; + } + temp[78] = '\n'; + temp[79] = '\0'; + printf( "%s", temp ); + } + + /* First, check for empty stack and overflow */ + if ( CUR.args < 0 ) + { + printf( "ERROR : Too Few Arguments\n" ); + 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 'case' */ + + if ( CUR.new_top > CUR.stackSize ) + { + printf( "ERROR : Stack overflow\n" ); + CUR.error = TT_Err_Stack_Overflow; + goto LErrorLabel_; + } + } + else + printf( "End of program reached.\n" ); + + key = 0; + do + { + /* read keyboard */ + + ch = getch(); + + switch ( ch ) + { + /* Help - show keybindings */ + case '?': + printf( "TTDebug Help\n\n" ); + printf( "? Show this page\n" ); + printf( "q Quit debugger\n" ); + printf( "n Skip to next instruction\n" ); + printf( "s Step into\n" ); + printf( "v Show vector info\n" ); + printf( "g Show graphics state\n" ); + printf( "p Show points zone\n\n" ); + break; + + /* Show vectors */ + case 'v': + printf( "freedom (%04hx,%04hx)\n", exc->GS.freeVector.x, + exc->GS.freeVector.y ); + printf( "projection (%04hx,%04hx)\n", exc->GS.projVector.x, + exc->GS.projVector.y ); + printf( "dual (%04hx,%04hx)\n\n", exc->GS.dualVector.x, + exc->GS.dualVector.y ); + break; + + /* Show graphics state */ + case 'g': + printf( "rounding %s\n", round_str[exc->GS.round_state] ); + printf( "min dist %04lx\n", exc->GS.minimum_distance ); + printf( "cvt_cutin %04lx\n", exc->GS.control_value_cutin ); + break; + + /* Show points table */ + case 'p': + for ( A = 0; A < exc->pts.n_points; A++ ) + { + printf( "%02hx ", A ); + printf( "%08lx,%08lx - ", pts.org[A].x, pts.org[A].y ); + printf( "%08lx,%08lx\n", pts.cur[A].x, pts.cur[A].y ); + } + printf(( "\n" )); + break; + + default: + key = 1; + } + } while ( !key ); + + MEM_Copy( save.org, pts.org, pts.n_points * sizeof ( TT_Vector ) ); + MEM_Copy( save.cur, pts.cur, pts.n_points * sizeof ( TT_Vector ) ); + MEM_Copy( save.touch, pts.touch, pts.n_points ); + + /* a return indicate the last command */ + if (ch == '\r') + ch = oldch; + + switch ( ch ) + { + /* Quit debugger */ + case 'q': + goto LErrorLabel_; + + /* Step over */ + case 'n': + if ( exc->IP < exc->codeSize ) + { + /* `step over' is equivalent to `step into' except if */ + /* the current opcode is a CALL or LOOPCALL */ + if ( CUR.opcode != 0x2a && CUR.opcode != 0x2b ) + goto Step_into; + + /* otherwise, loop execution until we reach the next opcode */ + next_IP = CUR.IP + CUR.length; + while ( exc->IP != next_IP ) + { + if ( ( error = TT_RunIns( exc ) ) ) + goto LErrorLabel_; + } + } + oldch = ch; + break; + + /* Step into */ + case 's': + if ( exc->IP < exc->codeSize ) + + Step_into: + if ( ( error = TT_RunIns( exc ) ) ) + goto LErrorLabel_; + oldch = ch; + break; + + default: + printf( "unknown command. Press ? for help\n" ); + oldch = '\0'; + } + + for ( A = 0; A < pts.n_points; A++ ) + { + diff = 0; + if ( save.org[A].x != pts.org[A].x ) diff |= 1; + if ( save.org[A].y != pts.org[A].y ) diff |= 2; + if ( save.cur[A].x != pts.cur[A].x ) diff |= 4; + if ( save.cur[A].y != pts.cur[A].y ) diff |= 8; + if ( save.touch[A] != pts.touch[A] ) diff |= 16; + + if ( diff ) + { + printf( "%02hx ", A ); + + if ( diff & 16 ) temp = "(%01hx)"; else temp = " %01hx "; + printf( temp, save.touch[A] & 7 ); + + if ( diff & 1 ) temp = "(%08lx)"; else temp = " %08lx "; + printf( temp, save.org[A].x ); + + if ( diff & 2 ) temp = "(%08lx)"; else temp = " %08lx "; + printf( temp, save.org[A].y ); + + if ( diff & 4 ) temp = "(%08lx)"; else temp = " %08lx "; + printf( temp, save.cur[A].x ); + + if ( diff & 8 ) temp = "(%08lx)"; else temp = " %08lx "; + printf( temp, save.cur[A].y ); + + printf( "\n" ); + + printf( "%02hx ", A ); + + if ( diff & 16 ) temp = "[%01hx]"; else temp = " %01hx "; + printf( temp, pts.touch[A] & 7 ); + + if ( diff & 1 ) temp = "[%08lx]"; else temp = " %08lx "; + printf( temp, pts.org[A].x ); + + if ( diff & 2 ) temp = "[%08lx]"; else temp = " %08lx "; + printf( temp, pts.org[A].y ); + + if ( diff & 4 ) temp = "[%08lx]"; else temp = " %08lx "; + printf( temp, pts.cur[A].x ); + + if ( diff & 8 ) temp = "[%08lx]"; else temp = " %08lx "; + printf( temp, pts.cur[A].y ); + + printf( "\n\n" ); + } + } + } while ( TRUE ); + + LErrorLabel_: + + if (error) + Panic( "error during execution" ); + return error; + } + + + + + + static + void Usage() + { + fprintf( stderr, "ttdebug - a simply TrueType font debugger\n" ); + fprintf( stderr, "(c) The FreeType project - www.freetype.org\n" ); + fprintf( stderr, "-------------------------------------------\n\n" ); + + fprintf( stderr, "usage : ttdebug [options] glyph size fontfile[.ttf]\n\n" ); + + fprintf( stderr, " glyph - glyph index within the font file. Can be negative to query \n" ); + fprintf( stderr, " the debugging of the font 'cvt' program\n\n" ); + + fprintf( stderr, " size - size of glyph in pixels\n\n" ); + + fprintf( stderr, " fontfile - a valid TrueType file.\n\n" ); + + fprintf( stderr, " valid options are:\n\n" ); + fprintf( stderr, " -d : Dump mode. Shows the glyph program and exit immediately\n" ); + fprintf( stderr, " -n : Non-interactive mode. Dumps the execution trace and exit\n" ); + + exit(1); + } + + +int dump_mode; +int non_interactive_mode; +char* file_name; +int glyph_index; +int glyph_size; + + int main( int argc, char** argv ) + { + char valid; + + /* Check number of arguments */ + if ( argc < 4 ) Usage(); + + /* Check options */ + dump_mode = 0; + non_interactive_mode = 0; + + argv++; + while (argv[0][0] == '-') + { + valid = 0; + switch (argv[0][1]) + { + case 'd': + dump_mode = 1; + valid = 1; + break; + + case 'n': + non_interactive_mode = 1; + valid = 1; + break; + + default: + ; + } + + if (valid) + { + argv++; + argc--; + if (argc < 4) Usage(); + } + else + break; + } + + /* Get Glyph index */ + if ( sscanf( argv[0], "%d", &glyph_index ) != 1 ) + { + printf( "invalid glyph index = %s\n", argv[1] ); + Usage(); + } + + /* Get Glyph size */ + if ( sscanf( argv[1], "%d", &glyph_size ) != 1 ) + { + printf( "invalid glyph size = %s\n", argv[1] ); + Usage(); + } + + /* Get file name */ + file_name = argv[2]; + + Init_Keyboard(); + + /* Init library, read face object, get driver, create size */ + error = FT_Init_FreeType( &library ); + if (error) Panic( "could not initialise FreeType library" ); + + memory = library->memory; + + FT_Set_Debug_Hook( library, + FT_DEBUG_HOOK_TRUETYPE, + (FT_DebugHook_Func)RunIns ); + + error = FT_New_Face( library, file_name, 0, (FT_Face*)&face ); + if (error) Panic( "could not open font resource" ); + + /* find driver and check format */ + driver = (TT_Driver)face->root.driver; + if (driver->root.interface.init_face != tt_driver_interface.init_face) + { + error = FT_Err_Invalid_File_Format; + Panic( "This is not a TrueType font" ); + } + + size = (TT_Size)face->root.size; + + if (glyph_index < 0) + { + exec = TT_New_Context( face ); + size->debug = 1; + size->context = exec; + + error = FT_Set_Char_Size( (FT_Face)face, glyph_size << 6, glyph_size << 6, 72, 72 ); + if (error) Panic( "could not set character sizes" ); + } + else + { + error = FT_Set_Char_Size( (FT_Face)face, glyph_size << 6, glyph_size << 6, 72, 72 ); + if (error) Panic( "could not set character sizes" ); + + glyph = (TT_GlyphSlot)face->root.glyph; + + /* Now load glyph */ + error = FT_Load_Glyph( (FT_Face)face, glyph_index, FT_LOAD_DEFAULT ); + if (error) Panic( "could not load glyph" ); + } + + Reset_Keyboard(); + return 0; + } diff --git a/docs/BUILD b/docs/BUILD new file mode 100644 index 000000000..34ba3e524 --- /dev/null +++ b/docs/BUILD @@ -0,0 +1,375 @@ + The FreeType Build System Internals + ----------------------------------- + +Introduction: + + This document describes the details of the FreeType build system. The + build system is a set of Makefiles and other configuration files used + to select, compile and link together the various FreeType components + according to the current platform, compiler and requested feature set. + + This document also explains how to use the build system to develop + third-party font drivers or extensions to the engine, without altering + the general FreeType hierarchy; + + +I. Portability issues : + + Given that the design of FreeType 2 is much more modular and flexible than + in previous versions, its build system is entirely based on GNU Make. There + are several reasons for this : + + - It is by far the most available make tool on the planet, and + has probably been ported to every development environment known + to homo programmaticus. + + - It provides useful features (like conditional defines, pattern + and wildcard matching) which are essential when implementing a + flexible configuration system, as described below + + Note that you do not need to have a unix-like shell (like "sh" or "csh") + on your system in order to build FreeType. + + + + +II. The library design : + + FreeType is made of several components, each with a specific role : + + - THE BASE LAYER: + It is used to implement generic font services as well as provide + the high-level API used by client applications. + + - ONE OR MORE FONT DRIVERS: + Each driver is a small component used to read and process a given + font format. Note that with FreeType 2, it is possible to add, + remove or upgrade a font driver at *runtime*. + + - ONE OR MORE RASTERS: + A raster is a module used to render a vectorial glyph outline into + a bitmap or an anti-aliased pixmap. They differ in their output + quality, speed and memory usage. + + - A LOW-LEVEL MODULE, CALLED "FTSYSTEM": + It is used to implement memory management and file i/o. Uses the + Ansi C Library by default, though some system-specific replacements + are provided in order to improve performance. + + - AN "INIT" LAYER: + A tiny module used to implement the library initialisation routine, + i.e. FT_Init_FreeType. It is in charge of registering the font drivers + and rasters selected at build time. + + - AN "OLD API" LAYER: + A simple layer used to link legacy applications using the FreeType + 1.x API. Note that it is binary backwards compatible, which means that + applications do not need to be recompiled, only re-linked to this + layer. + + For more details, please read the "FreeType Internals" Document. + + + The FreeType build system is in charge of the following tasks : + + - detect (or select) the current platform in order to select the + best version of the "ftsystem" module. By default, it will use + the pure-ANSI version. + + - determine which font drivers, and which rasters, should be + statically linked to the library at build time. These will always + be available after the library has been initialised through a call + to FT_Init_FreeType. + + - eventually compile other font drivers or rasters in order to later + link them dynamically to the library at runtime, through + FT_Add_Driver / FT_Upgrade_Driver.. + + - compile the "init" layer, putting code in the implementation of + the FT_Init_FreeType function to register each selected font driver + or raster to the library. + + + +III. General overview : + + The FreeType build system uses a hierarchy of included sub-Makefiles + to compile and link the library. + + Each included sub-Makefile is called a "rules" file, and has a very + specific purpose. The suffix for rules files is ".mk" as in : + + detect.mk + config.mk + rules.mk + etc... + + + Here's a simple diagram of the build hierarchy, which is then explained + with details : + + + + Makefile ( ./Makefile ) + + | + | + v + + Config Rules ( ./config//config.mk ) + + | + | + v + + Library Rules ( ./config/freetype.mk ) + + | | | + | | | + v v v + + Component(s) Rules ( ./src//rules.mk ) + + + + 1. The "root" Makefile : + + This file must be invoked from the "freetype" directory with GNU Make. + + a. Host platform auto-detection: + + When run for the first time, this Makefile will try to auto-detect + the current host platform, by running the rules file named + `./config/detect.mk'. If the host system cannot be detected, + it will default to the `ansi' system. + + It will then copy the rules file `./config//config.mk' to + the current directory and display the results of the auto-detection. + + You can, at any time, re-run the auto-detection routine by invoking + the root Makefile with the "setup" target, as in : + + % make setup + + Note also that it is possible to use a second argument to indicate + a specific compiler. For example, here are the lignes to be used + in order to configure a build with LCC, Visual C++ and Visual Age + on a Win32 machine + + > gmake setup lcc + > gmake setup visualc + > gmake setup visualage + + The list of compilers is platform-specific and should be contained + in `config//detect.mk'. + + If the detection results do not correspond to your platform or + settings, refer to chapter VI which describes the auto-detection + system in great details.. + + + b. Building the library: + + Once the host platform has been detected, you can run `make' once + again. The root Makefile will then detect the configuration rules + file in the current directory then include it. + + Note also that the root Makefile is responsible for defining, if it + is not already part of the current environment, the variable TOP, which + designates the top of the FreeType source hierarchy. + + When undefined, it defaults to `.' + + + 2. The Configuration file : + + The configuration rules file is used to set many important variables + before including/calling the library rules file (see below). + + These variables are mainly used to describe the host environment + and compilers. Indeed, this file defines, among others, the following: + + SEP The directory path separator. This can be `/',`\' or ':' + depending on the current platform. Note that all pathnames + are composed with $(SEP) in all rules file (except in + `include' statements which work well with '/' on all + platforms) + + CC The compiler to use + + CFLAGS The compiler flags used to compile a given source to an + object file. Usually contains flags for optimisation, + debugging and/or ansi-compliance + + I The flag to be used to indicate an additionnal include path + to the compiler. This defaults to `-I' for an "ansi" system, + but can be different for others (e.g. `/i=',`-J ', etc..) + + D The flag to be used to indicate a macro definition to the + compiler. This defaults to `-D' for an ANSI system. + + T The flag to be used to indicate a target object file to the + compiler. This defaults to `-o ' for an ANSI system. Note the + space after the `o'. + + O The object file extension to be used on the current platform. + Defaults to `o' for an ANSI system, but can be `obj', `coff' + or others.. There is no dot in the extension ! + + A The library file extension to be used on the current platform. + Defaults to 'a' for an ANSI system, but can be `lib', `so', + `dll' or others.. There is no dot in the extension ! + + + BUILD The directory where the build system should grab the + configuration header file `ftconfig.h' as well as the + system-specific implementation of `ftsystem'. + + OBJ The directory where all object files will be placed + + + 3. The Library Rules files : + + Once the variables defined in the configuration rules file, the + library rules file is included. This one contains all rules required + to build the library objects into OBJ + + Its structure works as follows: + + - provide rules to compile the low-level `ftsystem' module + + - include the rules files from each font driver or component + + - include the rules file for the "old api" layer + + - provide rules to compile the initialisation layer + + - provide additional targets like `clean', .. + + + Note that linking all objects files together into a library is not + performed in this file, though it might seem reasonable at first + glance. The reason for this is that not all linkers have a simple + syntax of the form: + + librarian archive_file object1 object2 .... + + hence, linking is performed through rules provided in the configuration + rules file, using the phony `library' target, which has been defined for + this very specific purpose. + + + 4. The Components Rules files : + + Each font driver has its own rules file, called `rules.mk' located + in its own directory. The library rules file includes these component + rules for each font driver. + + These rules must perform the following: + + - provide rules to compile the component, either into a single `large' + object, or into multiple small ones + + - for font drivers and rasters, update some variables, that are + initially defined in the library rules file, which indicate wether + the component must be registered in the library initialisation code + + + a. Component Compile Modes : + + There are two ways to compile a given component : + + i. Single-object compilation: + + In this mode, the component is compiled into a single object + file. This is performed easily by defining a single C file whose + sole purpose is to include all other component sources. For + example, the truetype driver is compiled as a single object + named `truetype.o'. + + + ii. Multiple objects compilation: + + In this mode, all source files for a single component are compiled + individually into an object file. + + Due to the way the FreeType source code is written, single mode + has the following advantages over multiple mode: + + - with many compilers, the resulting object code is smaller than + the concatenation of all individual objects from multiple mode. + this, because all functions internal to the component as a whole + are declared static, allowing more optimisation. It often also + compiles much faster. + + + - most importantly, the single object only contains the external + symbols it needs to be linked to the base layer (all extern that + are due to inter-source calls within the component are removed). + this can reduce tremendously the size of dynamic libraries on + some platforms + + Multiple mode is useful however to check some dependencies problems + that might not appear when compiling in single mode, so it has been + kept as a possibility. + + + b. Driver initialisation code : + + The source file `./src/base/ftinit.c' contains the implementation + of the FT_Init_FreeType function which must, among other things, + register all font drivers that are statically linked to the library. + + Controlling which drivers are registered at initialisation time is + performed by exploiting the state of the C-preprocessor in order to + build a linked list (a "chain") of driver interfaces. + + More precisely, each font driver interface file (like `ttdriver.h' + or `t1driver.h') has some special lines that look like this : + + + #ifdef FTINIT_DRIVER_CHAIN + + static + const FT_DriverChain ftinit__driver_chain = + { + FT_INIT_LAST_DRIVER_CHAIN, + &_driver_interface + }; + + #undef FT_INIT_LAST_DRIVER_CHAIN + #define FT_INIT_LAST_DRIVER_CHAIN &ftinit__driver_chain + + #endif + + As one can see, this code is strictly reserved for `ftinit.c' which + defines FTINIT_DRIVER_CHAIN before including all font driver header + files. + + When the C-processor parses these headers, it builds a linked list of + FT_DriverChain element. For exemple, the sequence : + + #define FTINIT_DRIVER_CHAIN + #include + #include + + Will really generate something like: + + static + *----> const FT_DriverChain ftinit_tt_driver_chain = + | { + | 0, + | &tt_driver_interface + | }; + | + | static + | const FT_DriverChain ftinit_t1_driver_chain = + | { + *------ &ftinit_tt_driver_chain, + &t1_driver_interface + }; + + with the FT_INIT_LAST_DRIVER_CHAIN set to "&ftinit_t1_driver_chain" + + Hence, the last included driver will be registered first in the library + diff --git a/docs/DESIGN b/docs/DESIGN new file mode 100644 index 000000000..b939362cf --- /dev/null +++ b/docs/DESIGN @@ -0,0 +1,216 @@ +The Design of FreeType 2.0 +========================== + +Introduction: + + This short document presents the design of version 2 of the FreeType + library. It is a must read for anyone willing to port, debug or hack + the FreeType sources. + + +I. Goals : + + FreeType 2 was designed to provide a unified and universal API to + manage (i.e. read) the content of font files. + + Its main features are : + + + - A FORMAT-INDEPENDENT HIGH-LEVEL API + + Used to open, read and manage font files. + + + - THE USE OF PLUGGABLE "FONT DRIVERS" + + Each font driver is used to support a given font format. For + example, the default build of FreeType 2 comes with drivers for the + TrueType and Type 1 font formats. + + Font drivers can also be added, removed or upgraded at *runtime*, + in order to support more font formats, or improve the current ones. + + Each font driver also provides its own "public interface" to client + applications who would like to use format-specific features. + + + - THE USE OF PLUGGABLE "RASTERS" + + A raster is a tiny module used to render a glyph image + into a bitmap or anti-aliased pixmap. Rasters differ in their + output quality (especially with regards to anti-aliasing), speed + and memory usage. + + An application can also provide its own raster if it needs to. + + + - HIGH PORTABILITY AND PERFORMANCE + + The FreeType source code is written in industry-standard ANSI C. + + Moreover, it abstracts memory management and i/o operations within + a single module, called "ftsystem". The FreeType build system tries + to auto-detect the host platform in order to select its most + efficient implementation. It defaults otherwise to using the + standard ANSI C Library. + + Note that, independently of the host platform and build, an + application is able to provide its own memory and i/o routines. + + This make FreeType suitable for use in any kind of environment, + from embedded to distributed systems. + + +II. Components Layout : + + FreeType 2 is made of distinct components which relate directly to the + design described previously: + + + 1. THE BASE LAYER: + + The base layer implements the high-level API, as well as provide + generic font services that can be used by each font driver. + + + 2. THE FONT DRIVERS: + + Each font driver can be registered in the base layer by providing + an "interface", which really is a table of function pointers. + + At build time, the set of default font drivers is selected. These + drivers are then compiled and statically linked to the library. + + They will then be available after the library initialisation. + + + 3. THE RASTERS: + + FreeType 2 provides the ability to hook various raster modules into + its base layer. This provides several advantages : + + - different systems mean different requirements, hence the need for + flexibility. + + - for now, FreeType 2 only supports glyph images stored in the + following formats : + + * bitmaps + * gray-level pixmaps + * monochrome vectorial outlines (using bezier control points) + + should a new "technology" come for glyph images, it is possible + to write a new raster for it, without altering the rest of the + engine. Some examples could be : + + * multi-colored vectorial outlines + * on-the-fly rendering of TeX's MetaFonts !! + + + + 4. THE SYSTEM MODULE "FTSYSTEM": + + The system module is used to implement basic memory and i/o management + services. By default, it uses the ANSI C library, but some replacements + are also provided (and automatically selected by the build system) when + available. + + As a simple example, the unix build uses memory-mapped files to read + font files, instead of the slow ANSI "fopen/fseek/fread". This results + in tremendous performance enhancements. + + Note that, even if the build system chooses an implementation for + "ftsystem" at compile time, an application is still able to provide + its own memory or i/o routines to the library at runtime. + + + + + 5. THE "INIT" LAYER: + + A tiny module used to implement the function FT_Init_FreeType. + + As its name suggests, it is responsible for initialising the library, + which really means the following : + + - bind the implementation of "ftsystem" that best matches the + host platform to the library. This choice can be overriden + later by client applications however. + + - register the set of default font drivers within the base layer. + these drivers are statically linked to the library. Other drivers + can be added at runtime later through FT_Add_Driver though.. + + - register the set of default rasters. Client applications are + able to add their own rasters at runtime though. + + The details regarding these operations is given in the document + named "FreeType Build Internals" + + + +III. Objects Layout : + + Even though it is written in ANSI C, the desing of FreeType 2 is object + oriented, as it's the best way to implement the flexible font format + support that we wanted. + + Indeed, the base layer defines a set of base classes that can be derived + by each font driver in order to support a given format. The base layer + also includes many book-keeping routines that need not be included in the + drivers. + + The base classes are the following: + + + 1. FACE OBJECTS: + + As in FreeType 1.x, a face object models the content of a given font + that isn't dependent on a given size, transformation or glyph index. + + This includes, for example, the font name, font style(s), available + charmaps and encodings, and all other kinds of data and tables that + help describe the font as a whole. + + + 2. SIZE OBJECTS: (previously known as INSTANCE OBJECTS in 1.x) + + A face object can have one or more associated size objects. A Size + object is used to stored the font data that is dependent on the current + character size or transform used to load glyphs. + + Typical data in a size object include scaled metrics, factors, and + various kind of control data related to grid-fitting. The size object + is changed each time the character size is modified. + + + 3. GLYPH SLOT OBJECTS: + + Each face object has one "glyph slot", which is a simple container + where individual glyph images can be loaded and processed. + + The glyph image can be stored in the following formats in the glyph + slot : + + - monochrome bitmaps + - gray-level pixmaps + - vectorial glyph outlines (defined with bezier control points) + + Note that a module, called the "raster" is provided to convert vector + outlines into either monochrome or anti-aliased bitmaps. The outline + is also directly accessible and can be walked or processed freely by + client applications. + + more glyph images formats can be defined, but they will require + a specific raster module if one wants to display them on a typical + display surface. + + 4. CHARMAP OBJECTS: + + A charmap is used to convert character codes, for a given encoding, + into glyph indices. A given face might contain several charmaps, for + example, most TrueType fonts contain both the "Windows Unicode" and + " + it is not rare to see TrueType fonts with both the + "Windows Unicode" and "Apple Roman" charmap + diff --git a/docs/essai b/docs/essai new file mode 100644 index 000000000..fca63380a --- /dev/null +++ b/docs/essai @@ -0,0 +1,173 @@ +Un apercu du layout des fichiers sources de FreeType 2: + + docs/ - documentation + html/ - documentation au format html + + txt/ - documentation au format texte + + + include/ - les headers publiques de la librairie, ce sont ceux + qui sont installes avec le paquet freetype-devel.rpm + + config/ - le repertoire de configuration. + ansi/ + ft_conf.h - fichier de configuration + ftsys.c - fichier implementation bas-niveau + + unix/ + + os2/ + + dos/ + + amiga/ + + debug/ + + + src/ - sources de la librairie + base/ - couche de base (services generiques + API) + + truetype/ - pilote truetype + options/ - options du pilote truetype + extend/ - extensions du pilote truetype + + type1/ - pilote type 1 + options/ - options du pilote type 1 + extend/ - extensions du pilote type 1 + + type2/ - pilote type 2 + + speedo/ - pilote speedo + + shared/ - sources partagees par plusieurs pilotes + + + tests/ - programmes de test + data/ - donnees des tests = fichiers de police => copies dans bin + test1/ - source du test numero 1 + test2/ - source du test numero 2 + test3/ - ... + ... + + obj/ - emplacement des fichiers objets compiles + librairie ? + bin/ - emplacement des executables (demos+tests) + + demos/ - programmes de demonstration + graph/ - sous-systeme graphique des programmes de demo + + + contrib/ - contributions de toutes sortes.. + + +============================================================================= +Quelques autres idees au hasard : + +- virer le controle des threads, on s'en tape magistralement + +- separer l'allocation memoire de l'acces disque (+flexible) + +- l'api de base doit permettre "d'ouvrir" un fichier de police se trouvant + deja en memoire.. + +- expliquer les differents types de dictionnaires : + + char_code -> glyph_index charmap (truetype) + char_code -> glyph_name encoding (type 1) + glyph_index -> glyph_name repertoire (...) + +- plusieurs "raster" possibles (le raster par defaut peut etre déterminé à la compilation, + sinon l'ajout se fait simplement en passant un pointeur d'interface..) + + +- l'api de base doit etre simplifiee. La plupart des developpeurs ne veulent + pas savoir ce qu'est une "size", un "glyph_slot", etc.., on conseille donc + d'en creer une par defaut, lors de l'appel de : + + ------------------- initialisation et lecture des polices ------------ + + FT_Init_FreeType( &library ); + + FT_Set_Memory_Manager( library, &mem_manager_rec ); + + FT_Set_IO_Manager( library, &io_manager_rec ); + + + FT_New_Face( library, file_pathname, face_index, &face ); + + FT_New_Memory_Face( library, first_byte, length, face_index, &face ); + + ou encore: + + FT_New_Face( library, &new_face_rec, &face ); + + avec new_face_rec :: + + face_index + + pathname + + memory_address + bytes_size + + + FT_Flush_Face( face ); // ferme le stream correspondant.. + + + ------------------------------------------ changement de taille ------ + + FT_Set_Size( face, &face_size_rec ); + + face_size_rec :: + char_height + char_width + horz_resolution + vert_resolution + + FT_Set_Pixel_Sizes( face, 64, 64 ); + + + ----------------------------------------- selection de la charmap ---- + + FT_Select_Charmap( face, ft_charmap_unicode ); + + FT_Select_Charmap_Index( face, index ); + + FT_List_Charmaps( face, buffer, max, first ); + + face->charmap => pointe vers la charmap actuelle.. + + + -------------------------------------- chargement des glyphes -------- + + FT_Load_Glyph( face, glyph_index ); + + FT_Load_Char( face, char_code ); + + FT_Transform_Glyph( face->glyph, &trans ); + + + ---------------------------------------------- rendu final ----------- + + FT_Get_Outline_Bitmap( library, face->glyph, &bit ); + + FT_Set_Raster( library, "default" ); + + FT_Set_Raster_Mode( library, major_mode, minor_mode ); + + + + +======================================================================================= + +Système de configuration automatique + + freetype2/ + Makefile + config/ + ansi/ + config.mk + + make setup => autodetection du système + copie de fichier include ??? + + make diff --git a/docs/glyph_conventions/bbox1.gif b/docs/glyph_conventions/bbox1.gif new file mode 100644 index 0000000000000000000000000000000000000000..b173caa02f0dd896e46c7dcfc274b90615c68e9c GIT binary patch literal 2791 zcmXAqc~sBYAI2|23Zs~eh6a5i*(!~aS{4sB~#sY z)u)h_08#)szyM$bFa?+c0sujPP(U~k0T2-oDG)he05Aj?1&m9T07rmR z!1;(IKmwow;DP`I0SN*X1TH`zKqNpaKrUb)U?gBFU@j0K5F`*P5H5&75Ro8KLF57h z0z(3$0^?G50!IR;0_P((0fK-+z@Y%3fS^F3z##+>A_ysj9AW@5f|x?gApwveNGK#6 ziU5iTiWG_*G5{HZj6%kx6GM(5r;ziJ(E-AMV!*Kguz;{YvA{6|7$OWQh8$ynF~XQ) z%rOC&AWSGG9E$*p2#XYp95a9!!i-|Zr72>LFsGRFkvIV&fD*uo0EmEyK#9N!1Oy@i zDS@0|KrkYh63ht!gdjpFA)JVSh=_=kh@3D$7$S@k#-(HkM}$+t`3NF_L_kHrMFEHc z5(O#>T!cV`NQ6{`T*N@cNW@gcTqHmwNF-DwToi#QB2lEG$VCQ3hD1h1#-+4HjzmsH z&PT8V!~kW0GXXFGF@Z9HGYA+&3{nO;!+>GLFlCrC0vJJzP)0Zt0TU4uDHAzkfHA}v zWsFN3#5iJ{GR{Y;1P}*Q+A3+8xPZ7or45jR=MZs7rL?4wI7S>(X|mElIYFFIX$sQe zxrn$(rH-XWIYXRLsk&5@bHq87p5}a!`QIB@G_sGpiM6uQ+X*vGvJ>u|lAWrty(0U{ z{j*b4O=C=Q5+4Npw9K`+BIj!Ph1u%^WhU%Os=TOfMYsRCS+P1w)4pm|$DzL-M(Y_g z)>J;-RT;O|W!?7`p&iCo4aUy3&{(GUG}-d#2XnbysSoL8v%IJ5 zdlutVyL@JvW=2zi;|ag9@4{bhFZ8@K?jM^cxaH2yk0lPb9xvUM<#$oB%z01~W(UMC zS@Zl^&XWqR8J}ThW8Y9^{GV-GR(R!g7F^qy_UN*H%A1Dh-PJ~`Z?$$c6&~(td3dYf z=bylQ)@ zZ>$mLQ`cSo@T#sx!ELW^eeLBJ;*WFh_h6j*%abxn&M$ps=WSIw(mkUf-cQR{ciX-x z>nd#gwGEShJTtj1snv8^qJN9$@al?Iqd9@$ZC3I5o>4)IZIvnmXWLzBJ?q?B5hmyy zueaZjFe>?#?efXvlI+&c>xgt()uLk)I)6=LL+~>6ULzzp;XI@%flc!S#P)DnuU|Td$jZJR$5Qv7D7ifN z%u$)z?2vfOEl(>n5!Gg96_bYDx4O#~ek|&3-1qVJ;G47qAuk*EzArw|=@NPOPqJ!x%QZ43QA(e-Z2yIM(ik<*%IjzzW@fijW_Zz4|*`GIN-q?#FtsM*R z$zFRGe_+FnMoBfh>6((&-c-tSep!BWU3Ay$w;ygy_qO_Y@2$MgbK}}0K0ULZ7b*An zEv^0DTW@_}sIRbPNUvX2lD6~sTZ`(ULw}E}^)T#hU6fhZHCZy;_Uf|CaDKDfww7p+{6X56bJG)d>YlY)uK08{>o1!>b6>I!)`tf{w_X9bceOarI;+Vp=fH+u)icyn!C+Wx{+aI) zS&Dxy?fB8e;k3J~>JOrm0yVPsltczwlDn@fYr^(Dt# z6pwX|i5k*Lxi$K>VnD$v$JWc*tBef-&u6*HBPgVx%mnFq&)Qp{UW`-}#bMt`eW);16nKkt)ooe1jJK7GdPRlH;kIgwn&8@F%rv{#%qvzOGtgjr= zsF|IzDkwy^y0f9>r+M1j)Xs1H$0|+m&-ZdxdoHf5r^onZEAIe@CVyWvmT* zXE*+GX;D*Uj%tRY!;LLBmiNfyc&c@xsX;aa{$_^#;oG}P0%o7P8RYI0W8>=Kr6@TR z7~(n2Ud8^XQB!7^xFzuSpj|6jOI3eCejh&Qdz49xoOLhuIjdXjX&SRaa>LGViCgeC zzHZiLk1)kPtHal#!`~m8zS%b~4rYCedL4JBXfBQL$kI;eOT;=ILvE|uS=eAxRdLm} zPM78`>!BwDcfjQAljF@_j{bS@uIz8wkK7%1lS?cYx~1*Qa!^1jpC*IqVT<>h&s)K}dmo+T!q zqCyP+weJpB^wB$WF!XG?gY0SkN>ReM{8wP&`CO3e1RT~g8PLAshfA7<-cEYoKOMmW_ zu}*vAFXd&`o^$KoZM?tDv{wGXFm50Fs;2F(X-5s<$bZ&V%}}FzxB7I{|Gse{x(#>Cc3puQt@m-yYeY-do?ky=&i*^Z}zQa N@R7&-F{8oC{{lNuh)e(g literal 0 HcmV?d00001 diff --git a/docs/glyph_conventions/bbox2.gif b/docs/glyph_conventions/bbox2.gif new file mode 100644 index 0000000000000000000000000000000000000000..507655657edad30db1480320e0a8ba01383f8f93 GIT binary patch literal 2468 zcmXAodsGidAI9f6mSkCEExB!)bfF?bv5}Qbx2-fKTW+h`>K(O8(QU2mf>N2J+a{9I zw5ZgmSZx=j3));#W3gQc8(p@r%=_zo=Z`sa&Ybg{=lgt~uQ}SdYUR#W&;^FU{|^R$ z0U!Yc0Ac_cfD#}85C(_=Bmn_{U_clk5>Nmr29yCR0SAC%z!~5Y2mk~If&n2FNR5?}}z1QJ33A%>7aC?Nt6VTc$+5)uFjhJ-;PAq9|PNExIOasWAooIx(308n5k z7!*?B4oVCqgHn##1Q-E^fJ6`=h!JE6N`wGH7$Js`LqAt^^k2bcgxfFuwQhzVo_N`e4Em>@=wBm@wG31NgtLII(e zP)4XE91xBPXM{^401=o7Mub$PNF*kb5h+LG1egLwfus;nh$& zSU@JA6bJ}}1!4k8L4Y7w5GIHe6bOn1Wr9kB{g(>TJyu;(_D3x2AuPwaI_GA<988*TU!$8EauQN@zKGUMy+Uf*Xq ztX)^O*YH%tw_m6~xjt?n=!5s5d)4KGDvP!?mK1c<#;aSNvMMd?YDiw@{kXC8a?hR9 zeQmnNh5oix%gmxoJcGVR)e{4`NyrqB=dF{sUwV9t`Z}j)diKuyP&DNGSI*CubZwe> zld$>P#KR`UXitZ?o&FV@(5r!upH?{yZ6G5D{F^V`^2j(cuWYctsb%GzkK2O#-w(DV z%(zotu842kvl)9wCe_*o1h^Sn)__`tj}G?S}55? zDZ436KeE8RGwsNnl*C=Ty3agpkH+akJDp$taX!g^YJrmaF@qJI9dQK}4`zP5(aXQX z!=UWpbl-2*qn%V|Qf^1$7Wdq)lP&?zyOMT9YIi4(Z!=6v*{u_>Gu3daW>;ueX>R(S zZ0#*Mp@B9|u3N;^!>&Jcre|x$HQG6UXFAE`MAjLvf*Cvi^ZkR9smb1jMmxNosi}VF z*H`ECrEf}ik7w|~Af0EqIZS#yXTS2^-n{%8ofp5#;xFb0MpfiE{1Ve_+!d1f4^qp| zT-f`f;EZz$El@W`PcGh$9X@Ym`OeAHvL({#g7V~myGu9$DK05(sO!To}cyDTGp9saB*7uS(O)=-Ib;j zbvo1bemoEpdo}0%%e13m!LJkSW8H34?%nqC@4L6^o?obnGTuH=obY$)(9xdpL9edp z`FI_x(0mjW60h%L%<}Wz1rG;L)-QdRKYn%Z+pHfw)}%cgGA_+}()Nwdn}1X9^(ljj?bSF{Oex4N zDnQ4)f49q=UcsviKmWngym6OkdqC5zwKn-wy70<}i|3nEM}KBI%L$HDoT?*HGk!W7 zd%n8n+`Z!(UY$y+A9ihwF?EYuZ)`We^uCT!>?dfeD!eoO?Pu!@#>T5B#H(FyrfV!T zEEB?KCC}70u<31zh>B zo*K2V_17uFEE{CE4}C3a4@q;}bgd+@s4T Y|KuAqiZJE!hNt6Jk5qg;K?$t>FQPEpsQ>@~ literal 0 HcmV?d00001 diff --git a/docs/glyph_conventions/body_comparison.gif b/docs/glyph_conventions/body_comparison.gif new file mode 100644 index 0000000000000000000000000000000000000000..c682e31c0a02559d27d03303a7114ae7748e04d9 GIT binary patch literal 2353 zcmXAodsG#~8pWrS1oIs}QS;Iuh$fmuD#${4oslqkj4Z_vK@oxRm|A9eP2w6MC^?D> zsU44qFo?W|kR-%MJj76xfB_$Yh=|H9Ai?0fhwl6_Yu1{z_S)b6?a!UKE&O1;%j;I? zFZBOI5fTUi!U$oCus|3PL5NU91R{VKLX09N5Cg;!;uLX#I3S6Tq(}-R0V#wOMM@wA z1|1Pg+J5JU(iL=XamA;KtOf-oQ)5l#sggaeU? zNJ^w25{N=XQKAG>^Mu0KI7-dW_28<)d zDdU21U=lG&nG{R{Q-~?blwb-BDKel81Oph16H$%?N5C=Sm~t#Q22KzsloP=TaE3Ue zoC(f=bHq92TyPFtA}%SHf=l2EaYeZjT!DcM2g*TkfI&ovN+cu#iIK!qVj(d|f+V4m z2uVOPBpH=VNCuK4$*JT*a*z^9Nu?B0f>cNH=kOHbeD1gB#Aqq$s zT4g8`U`FyO_uI*l<`~EYs<1uUx^;`&hitQZ2h&^NejXn%d*e> z5X?)Zisy6-i9M$5lW%5A+BYu6N*pHO4@YogQ# zo!oqE&fTvTWb}dZZ$3UUU7Z-c|ig$;@ z^q=0J?Nyh3GWUAZnpq(wa<7DJ$1$PW=!XaPz{q-S%}*N_>^${DgLYl7L)DO%H@o+2 zt?4H2-+8~N-|_L@FfWVxU8BZYHieDZ;(nN=d6qT!0&UZ2Ys!y|*|+vuPoQ5TD>M7{ zodNf$QG2ho{2n{+x>a+WZEa}tfrYK9%?BNN+M45?j+)Y?a?V7bZ${P6->%BIaC-A0yiT-C%CsC8-jQ84 zGrc3{hTYSS+-kSk&+_i93V)Vg7n1%=n%A2rx;~`4EHr<6ribuhj&;?AStc7S3OZ+2 zUhw#Hde__)al^0OUOnYCv$}t;9*66Xu5dKcd4D#|T36cJS9Jf!_s+)F?5XftOnsY; z-2FoR-WcX9i%Z*+F5diRD!-mt-(qoc z3ed4HJOYd7`7J;9O=|0xLE+XZBRXy+)fQFn((#L7EV=#0`|0b>Ee?-0FG}jJ@{b>B zoiy{SBbL6ymhXRX`=yc9nlBHSpI?<_(h&J%M-v&ATCmc8MbEMCf6g(vf9%9-`4i9j z4tbvMWp815|3R#~-Q?iiaJ7*oEFCbbaEY$h)ozIG4{HxN^SrP9>A~~Xwc^T_qK@Dw z&)H?nvT#@2gmk0%@vD4V+@6#M6izsPDe4XFpZ|5U>F>JZr|s{q+mzYg)420R|6dQH zZ3bSpz%lJWZ`--dfxeD{7Xz<4f3bnTyMELD9KUpDDjz6*aRh<_#(8%p)1RX1u4;!) zxp%*F$KfIOw0kD!lpjiZT%wO~wH@b6j7*G|RBQ_5aBj)p}u3mwAlI2YT~+ zfo(Hwuf!FE{yr_+I3(CU*r%z{bRTcY`8?upI% zQ9jPPGo2kC)n22|B-a(%_0Nk=ICFfxY3r~c7emu~+k;-k$GH`=#+@}tc%m-p^2UHf%ykf!|O>aC|$+>A$2nqOyZSY(_x z>0V!6+Tx3@K`HR2S-X>8(X)~*%k<|zwqAYbdQRcKz_11||rsrP8Reo}%E7-Bu)ZtN@ z@sY8s55B&nV7`O*^}{76ZmeuQQyqvGH^9c4geg zU2k34zhOescPZ0vZA%p9ab7UV>(p5f+f|Q}{Y4acdrI^XlhPDji{0Io7rZ~!1 zw&$9jTsZOEWtNA#No8J@$lODN9W1*qPh?ri_TH_|x6AkyeV%)i(V8yvH}UChSF`8O z7b}N*I8;m-nrpdej(6Cj`gq3|k*S^;VSbejwHJHxvkqiLZ1PYI4L$P5s*Ei=E7iRQ Is~O1tf2Pu-9{>OV literal 0 HcmV?d00001 diff --git a/docs/glyph_conventions/bravo_kerned.gif b/docs/glyph_conventions/bravo_kerned.gif new file mode 100644 index 0000000000000000000000000000000000000000..b71350c046a8c941205b88a29792fb9188cacc7c GIT binary patch literal 1279 zcmXAoduZ2X6voeF}2L`3Q?$wv>bY7 zX69{%hGz;xDkZ= zF2nza0Sq7j0gwR=Fn|Dvfea`>0E9sdBtQX_K@Bv(0i3}NJRkuihGdW;Q-WX!gNU3Y zFoGcjA|NuNAqEm4F_Iw#3ZO8Gp#&0<$QqP_Q&@_~RS7u2vQ}kf3gke`8jyhx z;vmatWspKR#Ij_wKtnmyvJ|r6!#UhC$C=Sc9LX~EOf-TcEPHjon*ZMp49MNNohUEJ zemmV&*}V18vVz$;uu*DgSD7 z{5f^=FRU$jZMnQW@}ntTe*JXU z_O|X*4|SIVgGw*iq|a-5R&9Rtz@E0_>xaxf`(^Qf(+$((Qm?*U+bfzn-r8sF#d+r| zPjnbRvdgt%n|5^B&GnN;-1+CB)(%wz%Q|iRd)Ddlx}~pgnz(4z$ps~6?^#l|>)fk* z{@PI1tzpE%{bQRRIeq#1Zwr3@qy0qF^sf(oeC_h@7mjZk|H(s#H_(LP^1yrdEoxYr zSI!k)Fzh^aw1w-YAF19qZSI-xTDLqgt!-w};?9G3agn;W?p5KL5FEYPTya>f4sc#!t*}!e4cj%4j)ib@g#JE z%kcjq00jt00Er+eqyPj!0#v{N24DhK-~a&-0#T3v126(pumA^e0$1?JlpqK~AtEmc zlt2?iN{|wzq$x#0NJt4aVI+pclvoo-5=cTxG)W|bWRy&kMRG_^$u)Uo?ov<+O%ZvU zKnRKum;e)DQcQseh=iz!fegrmtjK`^D1@RYfd*)Vrf7i<=!CB5kxh(27>W`3(SaD0 zAvggi;-s8{5g3V48G{*^iCLM01z3nhS%MANh)vmo9oUIo*&|DlgE*8U@^JzQs6a>p zNhC=ng&+u$pbCaC2$Qf1hX{y}h>C<5h>@6zg*b?lxQa(cMuH?%BJzlU4AdYjfhDq} zmckGW$xsc$7>vnSjl%>?$V5%T49v((&B7ea$z07NqisPJY7u$tKo051%QcvLs zj^wD0;SA2?tj^&AF65#v;RbHxrf%U5?&PlSku}JJJk%rdRRRjotW{Z=B2gsG8jyhx zq(IGRWsrg?ShHlaKtm`*vlO!7!zfHM$C=S^3fD|M6OEt<%}%%d+3deRaA$tc|B1mZ zv)fjkOSjhTeW7LB9#i&j-LUV)8@uM#lr~fj1899h7B{RI@^Z&MCvv;y*7X7@w1VC; z6`#Mg!zVii%z3nQb??4~=a#)zx3RSK_{}5tKhb^Yh8CkbZaT2zt)?xb>vL=WI=s1T zW%GBgKD4`L)0Z`6ZEQwyP0yjPRK4+RuQne(^1#{{u(aQWYwJ($nSIl`#cgV*p4@>A zV~R%Z+Io85vbH_TKi@UCa@~xQ%Igj`eP6Y7VZokr_x3OT^o!dIhIQ%r%w0`87jFM! zQKx&R&0I45hTNncPgU@iNjz=bqV}7q9i|xi&PB{2_Y30V@)} zK?Q~N)qTg*rpdY8CF7SI>Cms!^1D~HtQ*?@_(xsPKOV4o`L?1CQ>xpqdiv%Cqs!_1 z+!ntst0|qWt5!yy$RHlfnacs1xarp+~vnTm6c**2bI>Y8ms zi8hi{%G7kt!$umYNFfrgyT1DU)*tIx&$FKA{k%W#*ZZS~o?@t8R$RSv)jatBg8@JS z009C3f&qjC2m~kqCn6L<%S3UM6ZIELdSjzgRPIDz2=i4zc~08U{zMdB31X@JuhPLntdS5m|w zhC>pE@MoL=BLGPNNFabfFajY71QIA9P>euH0)+$)2pl7DlE5KB0D`~>f+Pq?P=KH? zf+7hD5;P!ajG#$^hAU(Uh!Kz^ApD64U=$!J04W4e2u2|!g+K}g6pB$ONuiL!0fl1} zPEt6e2tW}SMUWH$DGE>&Mo}b1L5cA@>&z+OiAn3JNeI2*Q|P&fmRm0NN0GA5AHu> zrsZf{mkyXW=g=caNbX%2dyNk`GZCH8m)^G} z?P8T{)Vi>qc)tjfe34T1va!H4SETITUDK{|+mi5@c)m(CXpuuN{7omD?J+LBeoiYO-!0FI5>MXNEf=VwTh7pQyYm93}a)d2V-@|BC&!U z`8F=p4zmnLgHJM0PZkrIQNUgx+4E88)S;| zk}R8ed5P+lubFh2!06d)UmV7Ziw0Wl$Wm%t-s?iW{6uL$iorx#jf%Zfd5VkZ$HH%J z0;HX>|5#teqjeKQ%+oWn!+}FG&n9>Z#!i!W8zu){=f@h$?_ixLKJ3>@?A~|LKQ85& zeeU_gmS3*rw0%Ho$9cT0x^EHdoba^%bj7;2@{8qJ16Q1;9_5NePd(mfN>4Rz(Nmay zvfa#i`l&dpbh=5{2PUp0#2%f7hAFE;&_9{&&!SR=U0Sz*eF~#r<-_t~{qR&&tjWdb8_By8YR8F0U`leQd6n6LL7)#->?I34d=&WyPfG^v*Dr1!ZWx48NFI!n-ptqj9Du^So7NG-{~i^P~qNy>n5d~ zSM1$EBP2gsqlPw=T%H|P$zE=s^?SWcHdi|T`?dF(yhhVf17i^iP3!^!_VTNg7jG#w zK8|Dlp?FT1B+|`SeYlElq3l%VYkE&fWPzzgc}? zI@b4e+T{0^=HrXgaUmP?_6VRYCnaX$Ij8gXinX?!QlCkPkIqB(aa)dzO%sb1h^*>@ zgpvD9qV5i9IX#PQXNj34uRFV2hJP^B_=L}GC7}n$1$i>0iOvb9i(=hHZE>Nob|)4t zR~~06m>j;UE%tm^VS2BUyNE$xZDqT}HEu3%f62v6f15)McON|6F&SuiWAxpDvZrn9 z3kovMmtGkwXfd|wh~vLMA1%DBtn4}<6E%`6lM~dZn7^tyZL@Zv^V+r(Au7=~`BCo} zUpfDrJ=hhy>6cOM3GsFlSeHBXW&z&|n`K|s; zzV*gvJ>7zrR@C{hZExi?th$VXL_0ZmpYyhS)k{WBM%inZO8!V$|A&^twi~NDikk&Z zmG`c8D>|ld<(yV>gQ-Ec*LvnBGu3sSaY>l7?WBdd5x=KW*CVQ%w_l!Czf&DyTEN1b z^iAx0(`MH4n0XUgOO{AqP}`r`7}p60hL$yc~uonJKHsR%Kv zyyNS;S&s_(+uyq0niH}y+gdjeIrl2x_1y2)7w0T{sg$CMKMO^_oy4B}`SifUj54uN zPfew*&$5-nliayNf7?8!xMnkxZ3T6Mb>rVNAJ3()t~NAr*{E+&>8>i zu}OjPU{E(&rR>XKX+TG7F@x&T){&h%J||ru8OiC`m|R<+Uz1xu&%FF^xx1=;r_|mU zS7UES**^!9-)BW;D-6$sG@iDLkF9-fuY%fjMvp01@}9c{9f_)br@-3YS^M(J@-%&; z_11BZEsvG$in97e>!nv0XQex4B(a-nKy@$w?30f-r=4X+4thuUM8w)=E|?8J{>XS1 zS(5r{=jb!?B~LqFEN0ac=FlOopXA{1;&Y)=9}Cll>A7;jV2MiC*tjs^^R6tU+H} zzIfLy4Nb*X-~V9r)t_D(uK)3}`oa7zgP^!2`oEy!nl(Xa$TsV|H79CrT9r+S{C58h z2xL65NS)%=-FYi2wy){P%TwF{?uzC8V@8T~aKg2H-8Xc# zW<dLr zI}V67{uso6GZU|SK?=U#p8GA!`|fXUCGrg}H%<7vTK`jNI3uZH=djv0?_spY3nkCh zp~v#By)9S|G^xgVw(an#oMp?7cXSqw>5Q_T*}IN-TuMf zsrG(xgn#x(c47PY(SZ6q<%UZia`^UUQ;e%6;PF(x?VPT~2*3Jd= z;D5F98p{O%C%zpz<{sFX{ZIPn{PJ|er@*h-aKh)>w`QG89~UU#as2zWHTu3WOxB`M zjo*6TpfR@EDna{q^C8{Um(43Rljcn2PI^4oRc{lx+B+vIqL16?Y4%rm{Vrn7&^<0^ z&YY3HcAMMbs9F6>&IJnrVYq*j(!G@@CO_M6}D*BOwXFSatZrG}*^}=6|f) zS>+q^`lEkdk$HfpaX&+Cw8;FI6wYTschR2MDgASMMB`@l<7DhYf5^oai+C?FG-SQw zy23*iisFb5acg#jE$edx`U7EK1h9w~;>vHopt*TRw8%n4ZGMF9V=I-WF!dg5W+UCj(hK+NrNy4xGTAxCzQ|)*5#}8mO!2&j5ouc*!=RZ4r{^Du>!5~!kItTbE z59X!nQH)DX-qxSOKbwYZb4bJbLk+GfnuYJ)b3+H^$VB(Lr=tN@-R`L<+tST9Ta6!C z8ydIIGrE~?mdq36u@!UpR1@FuR6q{Tao5^Y#d;}c*Zb+8Pb_RDq`2E+JYp}gczfRR zuZ(5vNXzKj5x-%7=C2M(0;ar!ei<7rGS}v2_Q__kcnQ7znXkE-!ratxi!52atbf*J zcd)ZY$6DPsv~a%j^ysu~Q<<25TiNyt*+ODB3#4rYikZ9T)3Q&QrmTrM)^zibU>0Su z=b_rk*?h;gBOYRor^t0Fs%&L_6{mYYlugvqj*DbA?GMAbMsJx~ZMjLyqc;z9+7JD> zYRa}hYwGC6yP@^tVqLN3jl}bzY?ZYGvPQmsCpn%*vN@X#EKTIRj@bp`y(T7kDO>Ua zpsv>rzV8_^k+5)+TD@JQ58*R^qco)VRSfm;s@+;8grOfikik$o} z3lWAA%>D06^Vj-oSyts4J@j@ZLZKn8Yzj8e{scIo{kNz!X%Zvh)-&k9D zX4c|Dcyeg5vVCD*gqUMV|83V#z9W`iTk2R3Ki;12$_vtpm{6f2?dsI( z_|(5?InGDR4!18-N>!A*Vf+z`>QEWOxti)gx;kj7I^?&S&z$NTRy7d;HJtRC$hw+n Ox+eC3$f{M~=>Gu0qW5nA literal 0 HcmV?d00001 diff --git a/docs/glyph_conventions/clipping.gif b/docs/glyph_conventions/clipping.gif new file mode 100644 index 0000000000000000000000000000000000000000..d28f701e3827a56f25b42adc1046bf61fdb76897 GIT binary patch literal 3041 zcmXAoc{tbE-^NdVEhaH7mXd19rzA_tIw@4b5z*vOq>Q92AEg?NGI`p_QaD0H%2wZ# zWqjixQYK}sD55^Ll>L_$v`snB*Ylh|&ULQqT-SZw@B4MXEun>x;qUXM62NEh{|5m; z0APRvfJ1;IfMWmx0198Wl&aTstIahPzJaTIVAag=bB zaRT53#0i8Gn8Y2&5XT6|*n~}hARrJh$N|V9$Pvgf2myo$LINR!Jb*lcJb^re7(k35 zCJ-}70i+000x5$6fC7R7fdZ3E3>kuqK*lCU2Z#rR2aM+c&mo>8JjZwlc!+pNc*uAj z@I2yq!t;#BfX9f(gvX4hfTxJ3gr|%b052e3AiTgNDe?^QjPQ(2#0d}v1OtXSfH{OY zf;omEzz|_bFl3kqm`9i=m}eLRj1k5JV}>cf6k$p*Wmo`MKv*DHU=lKzAN2$%^J2owpF z2$Tr|5CkL$L=c#yK>|YpBLZU+RRV|sB59SROpHT}Ba#M4z%z&#BobN@NQ_5}Cz50( zfijF3CXy5+!!wE)B@)LHqf9_dAQE+nC}W5*B6%(TI{E*0Ky%`r*a=tTXlYVRn#vV!&RU-qb7FwHnOuuoLQHkv!^y0 z-pYD(*~m+(HSv~Ob;{bmrrS!(-)l&>ij~tN1tRmTEioI;TNkdV6FJ_}ZXTSY(URx3 z>X_`%5l!n`ZV|+_j^?-&c`PnZ*<9pjFY?bx(=SQz>5K^;nLa}Wzqh$ByL6Md^m%;O z^_8JPn;+I{{#ZEb!S{N$llTYzsvYN*n?b&bzm2Bs|){ju@;wGR=UrJgqna)Z8^ zzTH%!y6ES1pF7^Gy-L3;+))h*|LotZX4LuL@eKCU5ofZSk|SiiM5w-tB*FUvxkzOd5nKBvvbiYdqgS)BT{A zd55z;*}vzcVvo_nGp34xjTd|>ilZZ}l?UF~Tajju4K^lTJ#pJTMLqF50|t5$+(OiQ zFL}g!^(OAm67?qe(gBureqQ;GnCJsf)%#LXUwuu!V)$`j-<9BQrGCfL9RsRKp(`#f z_li_5SspE?IDJQY)Vi0~(=RR@bH2E8b*0F)_16T^jWx?e{idnU6}&TY*Bkb@H6aVm zT;%K>n^T&Ot-8{!r`8+zN|=xp`qZn^d#XAMQ<#^#8QtsyNQ1Z{bz*2hK5C z+D{c~h~wzMMkG*#`!6uIxU*wB}Y>MeS6Ja(7Bv-RSD`JmBSrUw?dRJ(y=?7=P5*<>+65 zp&DMD$Ac#q$I2`2lCL=#Tc=lfx@d6Kt4HB2dauv5$b5aBt!-N(#Ei5DZkc*Wm|9?b zKKE9_WsNPkKjS}c#~OBP4PM%p=H-%hQM%b%>3;s}x)RGAJ1?Vm_^5fQU$3m@)**23 zM0>30Sjp z+NT#LwTwl*cHMmLw??H+Ce>LB-J^DAS$9NzyszCaovn6Y)(%{rkaxd5;;h_2mvz_c z_yt>ZtgIb&Nw*iS_(}V$udZ?YD`nmJMkfDVzbm^Y_<={9JXljy1i;Mrw$rmO@&|PBxtkG!2nl3MGt42o(V`5ha%+%@C6Q5AfAC}||Q-{$(7mYT-_w?|UmM_yms2cH~! zIdbJo{dJSiHFiG#e7x{OKJ0r)yoISkuijOanmsS%ryGPUDTt6$aGoOQHHMCh(-!FV zB+RM)CDI^4nU7k$xd#f0DDhQl(K{^3<=ue>dBVPCp_p;x|}^Xin2 zi`SV+Sv|0gL5jJxj(fEZ>)dd-By0gQU5|!bZz$%sZ3=Q)hd;z-ZbRlsP<2hoO+_? z_nWUAzBGv+&gQm?XC9PyF?xuj&y{?r_sGw@rdpVLOh%lI7RcD2_{+d$#%zAy`Koda zmaAy0e#EM1>Pv@00|WQ`x6QtZgDGb=SQduJHZFxLa>+767%p50o z`7G{UqHV34c8+`N7VA^~*7fsMt+kH}EsWX&Up#eESt{CEsvL7-l1@-jd%SdwhJ5Xt zl_&3I__#g_ziT%fb;4)wo1jdW&WJSI1T!z~9fdB6=Uz4zK9J30QWjm^f#Oo76My^9 zD_cG7-LR__qvlD!l(~BS9{$Co&*a_-iwtUOm-CPRQ7pavNo(>}G=$#$xohk2>&F|iE!Uo!uhV*=sO+R|QlRcs zv&wj@+cHj7LB`J8Mm=v@ezLtbKYz`^qQvM^ADmxR_3Aw-9?DDko?`U4x^+q6>cf|0 zr~50U;^6AGi;>5FvUt07w>WO;fw7YOuuBeKl{c!V9=0flYhOx;M=oXTV~C%2)Z$2ApVq0 z_aCCWw_KDBZ#Psd42WJi>)yxgxLu}k0W|${|J$?2*ZK5>M5ojbA2_hNQ;-`wKKxue zX0CCU?4d8WxsJ?fo7axKbnEw9xlnvx@5oH`;IX>n<0DspzSD1M_wDKB@zEQ0cLtrF Oe0yGMqB?03F#cble*32Y literal 0 HcmV?d00001 diff --git a/docs/glyph_conventions/down_flow.gif b/docs/glyph_conventions/down_flow.gif new file mode 100644 index 0000000000000000000000000000000000000000..83b2b7c358ebec160b896a28a44da8a1b333d5b4 GIT binary patch literal 2705 zcmXAoc{JBqAIER&pyerTlBUuv5h}_^tCUm z3l!U!>h1R?+tj0i(SAPNx0h%!V4;s9}s zI73_@2_Ok0i6KeICq@Dz!H^I`qXSF;BR~)c2*d<30tG>UAWRS=NDu-D!GthE1fhUX zOeiB%5Do~(gfqegkpPh}kr_mqfk%;D8dvmiUcKq z5=;rBL{JJS#gsBi1?7NpOgW=mPzg{8Q;AVY$jMNFsbExyAw&Rkz&H>b0uC{Uj6=Z@ z;0SZXI1-!yPB15o6TvCq6m!Zr6`TXkG3ShP!6m>Y%q7MpA*am+=7Mn{hOh%H0VV+< zK_EdaK_)>VAs`_vAtoUq5g-vP5hf8KQ6Nz)Q6^C#aUgLlaVBvgNkEdYBr!=6@&-u) zOM*#43{?qW0hqj1@-hjC1!VFD$iWMQ1!8hqa!7(;L6|&Qd7y$~L76-S`S5~c!I|8# z+^CSSkeFOuE-C~Tg2`WV21fpG2egOop`BQ(ApccVGs{c69icEu%c&yoT*TA6I2tlLx=VsZC;Wg)Z44%Qi6z3_D2i&GK*DYVQreEIac+I0Q6#v=E&s-KsH zXXe`Lw^tuC_84jO#N*NREYUEsq(pOPo!17(uiBp%zi*h~Tkn3n_u^Wl}YEeB7}dHV2>QfHeKF~M}fi^$0~o-YooxT|cB z;QlHJN0qjO%#57v5*P0~@8x>8sGy)Sw@rt>@|l*F_xsgDM<)bl>{hJxoNK*CFW$*- z#R0olznaa@enl+}I$p(YHWiv}an`z;(ApYzr0lTm^>jVun&R#nu7KK76LxwlW<<6H zWoL!@-klzIHc;8FJz1kzGdbmPXoss$xN7$NRDWe7n4;+I^~V14FYOCXZ8uQG@eig% zd8V8WtC-=Z+iB>M)^u3I+qZmIn3r=_3Ug&j?$flgpX;>6UAWw#@FtC=557(pp_Q6m z=eMfX`pHP2*RkB!of9wrzQiIkKh1byW-(f<3^$Z3D*-u%})D)-_*rBd_B z%?(j+c8qC__ls3<&F#6X7Bc!>Px-p|Dga{lxW@|s_H(0%1}|Fs5* zyYlRt$7Ed@T&JYBORL5{f6MBu>^KLmv?1{RgwikF5z!Az9Q;g8DtDi^-quv`c-7Ya z##*Nxs=a^ih;{Bw)=O==+z^;`KX}Kea-F`$DK}=mDe%2U;+xl%e%8JCQO0Bq``U5; zuYnpe!=}*Gs!uNhjmKYj9&4k!sK%h?RncSmU44IxM@X~YF*D!mE?$}6!xG1w(!P*O z=VaPTevSXm$N!p7VY5e9QfcmIhnpT(7kgwMdLNLTRybI)r@`vJUSfBbw4(C1{@?(Q z{9d?p7L2--zrI#%9Q;sv_usbz`sUvI5*m`!zBypuJy#{%PWG|gR-AsOv8MOyo*r5F z(=Vmwps@Z19p`6IU+VmC-n5e8^xeV3J+nqsjW$-9muEi3Cw9cf)5hnpg-7Z`t4CeI zf86u&3;Zp^=`q-LEvZexHRD6o`^7~!6<57AoS}85es@_`bkGEyHH}G4Ssn%U&eehD zs^^|P4au6OwD4G%@k`nrXW zl=K|;i^))H|7ccj)Zl-jeD~&WyBDlAME>EMV$LR;FECafzQm)^UbXbWt0_9}<5rqa zp04hpvMgtm%w^laj7iyhP?hl&6DNl_^`!VkuFJ>%vRb|EBI{j}7Fu&MdZpVybzJ4z z8*WMD&ZO8eQ)$P2QmDyB*)i+6sQoO0(_wh?IC z=BL(Rt-fN4wuP#m^Q5?01DlVUZQPWvE}qmG#P({nI{BY0E^e<`+F*VnOgr7FxMkcJ z^vQ&tSejN^bBHh9(L=r*1vyY^{azVoD$PLU6mD!w%t9I zwM<8I)o-dLWy?Qhw<>qU9jKgjGB}2fp<2zoitB1uRVLM4>HKMG;^Xdt829+V7`vnm zb&g#=E>cvX|znyc}NP1?~F!|u|Rd${a%jzE`@-r5hIjeN`>fMqR$h7Bq*q$?a zR&8UzTlV?bkIh`i9g7ZH)PYRm0BQ#nTb}r0Co7bCnTe+7j@#d%-fwGRKwWOR=At(JuouLmEMZa1Ha7{7W-WNlc>&E9GLvvjwD zV%u!pbeUU4&f@J(O3UIam2DDM)NOfSzG!FGO1!fL2REsoR>U`sut#lvek?@yOV6Sar zsNJr2B_ET0kLaK9H2PM3uSWE>om!Kcq8k5 T_0~ZetShR%Dhru80j&5h;(b(> literal 0 HcmV?d00001 diff --git a/docs/glyph_conventions/glyph_conventions.html b/docs/glyph_conventions/glyph_conventions.html new file mode 100644 index 000000000..54cccc1c3 --- /dev/null +++ b/docs/glyph_conventions/glyph_conventions.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/docs/glyph_conventions/grid_1.gif b/docs/glyph_conventions/grid_1.gif new file mode 100644 index 0000000000000000000000000000000000000000..31291a8004492e0fec4075cae773f1217612dd49 GIT binary patch literal 5837 zcmX9>bx;-E-(P(Uu#-~YL6^n?rNsb&B@A>GX%!_G5Gn5krQy;naN&~D_bwf-a4Drr z^Z@~30Y#J!MF|P_hwpp-ICEys%x6CJojFGXQkR#zhi>xUv;_SBf&l;n01^NJ0E7V$ z13(gh004pk2m>GzKmY)N0R#gO5K_vNCIshX8h5#f2 z0tg5rAclY>0s#mFBM^o_B!U140wV~9AS8kU2nr)8hM**Z0|*WyIELUPLI4N>BLs#J zzSPz&L>60EvSD4#GHy;UI}a01m-8 zgy9g0BLI%TID+8_iK76H!Z?cID2d|$j>9;P;W&vC08YR-f#C$Xkv2}kIEmpT`8Rd| zCIE~8NCE^15GFv307(J@2nZ%1jDSc20SE*p5R5=b0tE;ZCQyt(NdgB5942s#z)6At z2m&Suj3CI31`#AokQhOdf2#z*B!F$SYNJdf2$LYT(SVKMNeCt(Y$L6WkVph35p2WR z4MRy3CQ)p|g$?l}4wE>x!FYoxNx&q5ZJ=*}k|a!$*v3id_m=;g0jabQCJiXo(WLi5ayNXST(j zevrK7Vu=XAkbg2c&{8tin4sdbgI}w3TDeF?k)pV^Stp&^O9Q{kjs-T6_BXrP{<}YK_aw;F(2XNxZ2LKH zYJ5Q0PRRR97c7t&w)Bslrc)y)tKC@+pT$#DQ#$k%ozcgLR&PZD)qZIAOYOQtp9WtU z&h2e^F1MF^eQru2uP)`3p2~WuUX(=`%e3U)>eA!rB>FQkynuv6S_@$6=g#uvup`E#OX&i>IBDL>aqh0GV8dK%+V0bDzb(zNfN z9eqJv$<9vOEXx$KqcHUEh0z`PhBK2^mRaH9RvH6YX=&^v{}2JrFX`9w`)=i2>C~Dq z#kVQE$YzFZpJcLn7IU!bZQ2n&dxQ-CEvR*Lo4WQ+UDE1W-PM?!(vR%%PNR5fvB{Tx z{*tq0U+IS23AWx1-9^*0WAI&z^2UC)CA!tV!gSD(&fZ}l!m5rAb>Vv*wOc3Qjpeh4 z1vOpqQ{U_Mt*RANE%{p+HpG1iwyQYCzJonp50f}z-yFGX-r7n%cfM8XNW-b7!!<{x zWB60rjoSaj>+`+Y9dISJU2tsLu1$>_`SqWsXx^_*9XXAeUtQP9?RFn-8Nv(QuDYQM zJuZ$j&L*Y-NZvca{}z z-_t=(c0OrZzwzbQ83E%A`B<6-JA&%(79#&BzuZtP>S@tfPU!M)R>Hh~Zj`1{nEAIT z3n_)E^9M622|+S0PiN`|hgN2b=l4+OUXv%+rrta-sGL*1Cbw!AIp6DkuTApW*i^^O zy;ZYicMhL-O52pbIC0)iKqWLQ_Rb$yreKxFqJw0W%4&Os;3Ve1n&i5^+*LsS@&5Vg z-^K4EQEMifCEp)%(1UUk{?z__Rb+|T|DHX^Qg&24soqYr_dBaS$k8NHE9O-QRqedT2|LxP?|!>6SPerZ0fzBB1QS3I&nON-TnZdG=5Am9@H_8cflL` zH}!$trx^U38a08L63nS?I=@WAB(4;k$WTjMrNm)2#>h@+U1f$X#KnnwN$Q zJC?{xS__AUW|+U1tx@+%w8vQCdAI;Rsl(^H;E#|)+lC17!l+`O-ri|`MHW)VBDypB%u_)tna*JiL zWBI%1deVW*z9iS>gOro|1?E!gRFl<&R_cPTo=qFCWL}wJUH`|s(6dm{Oiz9Xe#PTg zM$bW3+b^hSE8nk72P?C$X86BOkYx~wP6P&S?ees9NG-d}+I~XoR#wC)UW&0wW@~h z`px(3S!_zbC_Lb|MXSW)>6q7vm={rNif7IoI9qt0KPMzNUX34f5>frN^MTj+hqV4~ z9XD8Vv!Km^jxP_3b&PCO&q*2xjV=^2b@L7`u!Yt*Z~GK1Ok9Et`>zWW;j)R6b`LOO zuwxOg4i!Xr_E#i-l%N;*JrTD(SRwU1d4Jg(-D`&FHe}DR3!NoeJF7*V5}ncNsVJsm z$~D~zo#(W3+Z2b*=3GP~J-YoSWDJ(1m!PMI7rhaFllC+)gXGxv zL)md@r%cXVy|?x$qxf9@T&2xJq1?RGV-m%~=T8*a8H{+JTxu3LY3HH)@}{yKPu+!Y zMNW@()FcGe--s=q+2b{RTPlU8R7vHrd$6qOAMeBd-*L#ta?fpu&8h;GU*CdYd1quBO73kuv)7Xnec!Sea z3EK(9g?R<9*;1y4$Do+KUcI7^jQKs;`R)g;I`v%?XUxw<+Iv0Zp3ID%i|qNXSNi*U z^K-cA6v!I>^yE$9NxZnvMN{G=TBQ;dt1BZsU1Iw~&SEv%<7Y*;y~uPWO-i&POa7FF zTuDT!$({GUp+)*OxkTZf{GV4m#V52drhx)qAs!L@r61zQadsKM(3TsPu-9 zgOk5d*NlES*74z#n6RMW9OG>}e-?@LiX}Z$5w`TdxwLgtfKffO4 z<6Y_QTb&TCOlUyVyYSWTCw=~+pDCzs~)1Ivz}zSnUv@5)79m%0;) zAoaV2w`ic(w*c=1++CPQwXv9|deM7doR@5zt&Et@Ax)o6JicB&KAL6Rl^=YsF8f~R z@zay{yQS}U+s#iu&d;FCZ?cFo(?Au{_f-?~7uWQ^%=EUf^taOY(RMSt(Cn`s=Of4C z^Tf^T0f+D7xB$ws;AzW%hk*gE90AY80)52MJ zLVL<02bUwb7?DDp=pKczR*e82D^$EMa-TRlAr{5Q>3tAFh5JxNTGUBKlyYAbHwzVj zxQm;EJBowVJ_c(tytOzTAShUQAzFhs<`QSrso#;ep3<&Qn3sYU)AmPN#?dKOu?Q{pX-h0T5!=;_QWavIt>UQS zamP91obJZ0zlsawWuUCMc`^_^1u@P|2$_^IvSKO8EsWedH)MJko-ucAc&XOj4D5~B za|OoP-}F9nhNHM7)@S-eFCq4Ke7RMWZ%f?BHia@PFt;T#Upyi7Zk+zp_~ItvH+^?r zu@Wl!!U}2HOtH{Lo{-wRCa`bPL!KafSokfI*2|kbsF1vimZ(Mxek4xkWZslZPu6=% zKjL=!drPz-?b0-F-20Y*#;0*h!Xj^J2#0@o^+eqI)3}ztga(@OrdI2RoiDagUTjrN zwG&G!XT+~E{;lI=>{CqTH%M)5acO6yRxTzU&`RZBN#&#@=hIR}4Nm_P&v0Oconoi` z;z{M=OWMJHA+wSeuA&g7&`(#!UI-dws7(4?q9lrGr8!$=XvAk|?MPE=&5-9yyFQt6 zOEKdBr(NxGhzUEyv_I2KF{?u}%Y%_g>aD~~Sv%YYK0=Kj7OE8~LW`E;k=KW6J!pFEu$)wS;LfPp-66sP{rrZki+9XpTC`)!F zHd2Dc=ua2L(x@0K#ej7dW6>vBi3Zq<-;502oK()7l6a4TeoI$ICX+KUV)A|(hOu_U zCbdS6$)_r zt?aOvfSVG(M(uTJ*)CeyGX{B;ocS&i`Fr{um$|Z^SSP6W@LVY`u(d9T!>~GbT!ogh zIy?0umRG}ilas96(xIYGW#emk4whKJSaYDP;|B}splz@eo*m2&a;P-h{cpTe9Jt81GoB! ze`RH4^yl7v>VF+F-yLIPwX%Lk zm2G5Nu~J13@v>DiH&deOgJIRkRMpe+spcA}Iy_x- zNaw|qgzEhRZ=ze@fJPPEN2_?H-h4Hzm0YXbYosM5St5P3?(D9T#+!9AN^w#Wl?3aJ zz(6TsQ~No%R!NGjvKFqMTe~f|YF`Mul3lH}THiKRE4r(8>p70p_wLLyN<; z)fy|;-wtUBNNmt-Z^>$J_H}O&Uu(S_R9vc@kZT)X(q21FZM(tOnqs7PC%2_0u}zWP zmd7Yf)@j#QY&d9Ce@dz?Hn`Cux7^?QZG+p}dzIz3?$&ngZT`Z+9w6f!yav^iNx$7w2KhQX;@Q$zzT9|&jv*Q4X38VMhs_Hk9C)(#$ z+dnJU?$&L66LL#v?LB|ndoGVE&J+LDDYqW>cz;Bv;fGPPjBVY?;JV|+opL&zH;!~T zl!)Z({8y+`c`dkEaQ)>+>ok3x_Z&%GQPXYkN=^GnC!_tpGodA_GhNzR6?bKeGIw>M zi7yr2wnIskUv{N`r5tHU&3}HSaU!?Fr0SBvd7-J;(}tnCbIKiG2iiWhcH~R;{Kr*R z)9A3(wqr~CYbWC-9hatOwlbbNy-rwL}$`a}| ztFYh`#y)RL8{M;{J&qbxFl+Za2b{5t9qhWAmxAx?*3<3Fv(z&B*q^`NU&v1s7oI0d zjS0NUZ$8oGhO_h848nO+zhIix>-#+%lY~-{BTB!Kaesg&E3-W2xV2?qZTRtNZpRP& zgPpn;$7MCRT?aoV4W^!X#zM~-*&F54~&kUbUuIZr^waUGtj}C zRssPx6^`1eL`mycd76JMSlw;rdTVe%q-S!}mTQZK?+0DrAC09MS;~U-yhp*g5y6Ap zy^rdK)4I-xjJ)8Made-0^}6R1xf~kEmHdgAvAgW!Fn#;6=eXvkTn@_$tu8q!qJ+I&|XJJ9=GyX(fJc7)S|ISc;hyNiUqh7{-{NkxyR zZ>RaI<=@*f(ir*55qYef{>*d_;`+f}%uf3%byz8Rl=F|>xh1b{y(82Q4%6|&9jswl zXS+H6C$>YjCjzWwvNiU^S#gfp_v$KC@zYEOG3xJz80ZRV^(t7FN literal 0 HcmV?d00001 diff --git a/docs/glyph_conventions/objects_diagram.gif b/docs/glyph_conventions/objects_diagram.gif new file mode 100644 index 0000000000000000000000000000000000000000..c8e1843bafd8bfbce5b6cac0597b78ac8215f4c4 GIT binary patch literal 4418 zcmXAoc{Ek)|Ht=jM3W{ID%qw(NEu3l$gmR-~AZ-XCp5OGVjQVV%rhi_rfc6oLo{0uT&A zFbcs01Oo_xAOwXF0zv?UK@f&Q7y)4b!XXGpA)J740Fe+xq7X?yB!DOgqELt;APR7l zAb>)EfB^U-3864Vzz~382!>G@CSVxA2m~W2j1VvaU<`sW6vhY`127K3I11wgj02d2 zU=oE%0ww`WK`@2F6aiC!;|>NW3&h5 z2!FbZIT(*O>5fS>>&IJ7vB0EPmL;3Ufl6yPYp2~G-} z;Q@&PlHfSz7zGpxD1xKT5d{DRfZ)7DmN)$04#@nu|LlYs7w4B-NT(wEc@Wobnni0x zPGcCa=!FcO%G{2#dC=f{s-A8|@hgyReg~;yUr6 zjm>)VKrM(TbKg$?);yg=nq_-+aTn`S-h~E-JvQCNrfm9P`=gTHax2Aa?kY;9{cMLW z!m?w*$t?61)t>q5sH|nQ$IOH#li&JNga3MoRcVIvP@@$$zj5^A?`G!YRs|24+C#Q2 z8pmpUPnucTv(q(L`K#r&%{6|8sSB?LjLpC;CZBw??ke~AJvcu(u%+e}`YFlJX>z=> zrdPP{^p#&aZ_kc~AAAZ%=6_3M>-_%NV;HbrT!rb%qtu!ml>B}3P_X+(9qYgqOOn zzZ%|JnH0!Pc3QEs%(!&K@w59;1v4>E_W?)B|MGs%FQ!8~t3P;F-!3jnZ5>x(h2EVL zkc@dPvj0Jfb>yg|vt#b^B{beri8mqnP9Mvcel3y}UVhVaJQ&%uf3j52&qw-U@LIoU zVEqLy(~2hxC&$a5SNiZ*Hm#YIME%E2UGg%k;ud0jPCikPt-)tDVW%nH^X>7T)AiyN zbC~XQ9UdDgT~|^iE$937uZ5sJ^O4!$%M;uE{W2=YoE$~n{C{_ zdF%I=dloyKn*{7jzc&kcmJT%?2$NCBZi#iCYg1B+o@308U-!-#3?C4DLrCL_5Sq#0puyI>ON5fyew1BALFCV+}>5E9}i5u{PmgM{A@(aD{Dmj&8gOar9o_}5PJM&W;OM57tDynch z`@~ZER*p|v=Zd}D*tS_ee5bi_x-s8c$jsfsyd>CX^jXsH_2{QSp~BgkQYu03Mw94) zNv=ZM7tFVkA?I@5ZPtAJqFrxBBk_6G!X}&i=?3jkrBab46_q@P6S0n;XyH4?;q$w8 zRqD?MZdrcTC01N8<9{=kxzW7$rS&7;u(mrk{8HjiwqUoT9c=&moy}-g+CCBL5-qyF zL$c-M!}wT_S0i6%i(1aKe~Z4iHUH3Nq*ZRQP_%J{6kDS6>f~^}2OVrArxjcu1 zDp*|ETTbuJT;k_BSW19Nw97Kp$L(bHdFtkF ziwKP_6_dW3cEWz!?O=LzfvkNPxka63KH`0IHN{c&sO*un+w7aOuw=)`#kX=3jXirC z8V|f^opv19Dm?gv@w(uBtkXlGkE*BDU#W1ry0xt8Ex!;j@Ux4FV$#KGE{}B7Sns~A zR^5KQY4nBGLiyEfpSV1ljvirbjFj03s)^QVMcp};!*-6|F^M#6)t3kw95+7xCf~4` zmwnsuoMoU^x`EHNq?{`wU(dviyz^%5=;86YBhM6i?l$;oTLexwl-s;gI#{M$@3&pK&fYK7Das z)psACb$H0$4WeKBo3FXv?v-;%&R$tsrix_4P`S#)lL+6nd#I7n@9VLzSNgM?l}Zj+>`D{Y z{P$VeHsi6zDIYNlq4KK?@ylOsIRr&Miqm%?ek4!7T%%5gr`I?xqjJ~#q!}MVREnKL zq+IL!3#R2SBx$beAKHE}?BcJJ5l#E9Oj&*L9?E}QWh@kB zm$g?`L05eXApO|d*eI<(Xwp5i=0`Ci+G($Q&pqy+H77FFtA4QiePD6S z+_7J$r~JUer_4P=Htn^yokiV-4|b2azBcO{&8kJeWC=(PcRHvwstHcIO@lzb!e#yxQfPZ}vt#UzEAve%o)9eGlt5={cnUmzk2H6@vwk?WUx zZH}M6%nEaLSWxKvED~jZyfQ#JAWUCuvqtRD^$dG2;c)-uE~|GY$3yvi_w*T!Y5P_x z1fsMHj>Sjt&F{7Osw7 z;fiG+j_ZCL*YGngH9VT@giVSeZE#o2UySHSo>tu4N9`<G(O$R`|G3fk4L_T;CE z3mL;37{1Od*1XVmjVmFHFaG(GyjZ`}2mYx2wGnhi7|k*02)DyOZYqbWgA^k|lxu@m zB|KiuJHBzhKd#8j7m*;boH)XlL@5dK>zIB|4s;54dbC&l$$_x25Ux0>n*r;&tv)F# z59|`}mbjm#a7}Bs6f&N08<+-(bB9TI9gfs?Ox<*Cza-5Fu^|mZ)xRfO_6N^D#<@JA zNeAO~kA23&7(o$b`GqiZbbT5FVux=pdvB?l?-%sb3)jG+2r#tFyh&R%iA+Ak39rK}X++Qxjr zWnQD1J}tpalL+Wqz^|pr-*4TcxQSU)lkrMBVaJQWGB@d;t|3bOjC@x7%xJQWk>=D5 zH5**HOu-_yjq%JomUr0Z=hCGie!n*?Y45fN^jr;UB);}BBe9pcF7Sb*lxFzlGxOSh z+T)g!uJZ9Y+sr-verkGWe>idTW14jKCeK&PDS;8$=Hs}=g3d6*;-FbNhNgXPi;IZJ zE#ppg+>j}xoF_^%=^n+T>N0Twt5cDANogi8LW18e_2ji|PPZ`AJ8b5uJ`rMAn}0pX zMJL@)y*S5o07KgowkDj1_lK%Tx|l~AY!`vM9wqYA85*>L0j0u21H5L-M^3vX%m@_D z?{jg9%M4fKvsVohA`xx*@@XB~}< zOmp`h4=oxf$QQHC6HzV_9FNX;T-X$unZ)CdIj}ltsVzjJ$pGtZdXeD3y*8eLURv2h zv)rd#WrG(OpH|{Wd`vs(hel}%H=p?=Pex{yrKiobADx%HEe_v`)9Lv>YE&MR>1aV>)XKNtWc01zMm zAQ(VMfIxr(fMNh80SW;Q0FD8i1ULi)00agI5)cqj08kj9NI*eA13+VdCIJmON&sR2 zk^sWrk^n;hi2#To06{PWArS;3C_qpQK}iIK2o4Y&LvRwoAwmFzzz~8&2#8Psp)iCZ z5egzSKxho1NrZ+RcL>A~NFosawh1s4kSKsC0#F1)5fVipiUJhHP?SVbh~fanF%&0J z9HIn32@EAjlz=D&PzpmS5~UzY1C+*4nnY>HnHYr_3P}{g-=hNz2P6(4jsP6NaD>DW zh@${UF&rgv6yi9*aSX>v9EUgoa00^#5+@)|0i42cio_|1(*UP2oF;J^a#F-0hC>pE z@OPX5BLGPNNFabfFajY71QIA9P>euH0)+$)2pl7DlE5KB0D`~>f+Pq?P=KH?f+7hD z5;P!ajG#$^h8!{k#0W?d5dKC4Fba?qfD{5K1fvj=LLh|#3dJatq)>qbQQ1AVmX;#wePkXvm>WL5zYV1>tY(0HXm(14tu)Mlc#7X#~KsuBF$hV{Yya}v|JwnX-}mpGIJJTE%PXS)AhSMrgTP^%mIqnS!nYqZNYgLN zZoDg`=-S^>meYK1-|0PT_m%(M%91oAZCcB7Una`S5jRv7^IoT_dQA4WR^*?FRu*3O z3;nmCBS)Wgct-8|`M0?y_S{JZmE^l3MuqFZi%RM4v@YWr>L*C^y@L^0f) z+8s*6>~8Fq8EH+hH86f{#hi-ETg(m+Rgs^eJ=BKTs{U11Ly7`7*}J@CHw>1>ZQHf? zMvX_(3roGgfQM?|rz*>=-?!a7{(AOwZPg z&rOBf#{UZVx%?~KR=BA~D;A;lsV14O@{Zfx+R9y!dS;8R^WG4T8S^Z&0enMR*yr;R z@!_g*OZ&aW>v%o}uTUkPy&)m>O}$Zfha4S@qFtIy?yPu*3^Pt;CnUQbsn2zYI!c6D zMjzYCn-U{IN_;dup)G;MnI|wz+{7{8LwCO}S6+w{B_dN34UAm&J39YWJ({Ye-X)%P zfhTugx(`!`nX&)Ngj33qRjJ&}5dK_d*0a}<ArF1->#$KmnwUhFY~B=FX3#94`I@?)g$anvo+&+MYFZj)YR<5 z`6lVPN8c#uUsAO+dTIRekA*3@ij~z(_~W$>%0=Z+lg=&klzJr6u&OT8S;1fGeeEf? zp45&gW0ySZ7-jB1`&zqganP{oaSWMhYg_Rmi1 z#-5h-9l5z@(7r_4w(eSQT6lhStMJ1#_PGLSslJvc+P?iL`(Vjr+mWKQqb40zVP7Vc zj4bX!mv-?lcju zcX}Fklww_19OyN^tf#C$qge*Z7R?9^v#EtprF+e*E(C0@kbc~EFFqZadOwy_(Q%d}*P;M|UE!=S2v)n_+cdCM1VENR|& zRz(#c86ev?xvLDJ5r zqxYZ>1^t}rh3sZ|36T;12G#uOQdH#OC0^WSSbuDjmgkN>trBaK|=baghGUfe0q zmfy1LPdBtvQoP;gnY#nOzobE`dGo#}D|$geR&D#3NWtkX6Z*NVnt-O6JTbvZgZ3n| zXvu;cZpXttof6^&=KMP91Mkf%$Rhbq3Izdm^^DW9k--5x z_+n+IqIdqo`tsS})o0`9(|dapxSSqji)I%6>Df|E?GY@mOqj8~|HJISZNdDS*O!dc zgl#^^wpZ(Pm3$kK=y<~)pIsVNc)jYV+4EU;`0Ga5>jF!K@5~boXu)${-VtveMXQ8= zs-%70k_Kx^7Q<#5N4$l1+6Ay(#8zO)am6mv!;rS-pykg zFH@FV1DJB`H8UTz1g!qPrTJ~MK*_kR%ggS2?p&!`IckTeUdr*t-G^K?luFm3I7na>Air?Cj#Q^TXL;(kPvY^E||> z7L-G)yrxar#?lAfj@<7ko*p7TU$a`6J|t*u!B?x^z1yG9Gbh@rU)>+;U-!2IZ;?Y? zz~i6YTGmFj9e%TZdh8h0P z*y)tH3;D--=j;|L?W6ncocjB=7gsiD7+(&QFdV7da`2y_l1uT=YKx`2eOlB8FGeM% zeH!vo`||CQyIkjq`&0j_9?4Cc=ce|gx;&2cxp!qS;^$}<_djA!tXD+}*7uBSw`aWL z(|nxk^vlm$!mnd@%eN3$^GV06weHO--_uG(Z{TpTH#ybods}*9kf-RPOt*ZfZ{ zB<`f*I?tqK`9Yh|tTPUuRAAB%s^M@8PMw=>Kg`d~^~6<~G%4J3ajIQZvzO@WSlg?; zV(}jm7QH4gOE>6Q+`_LWUl|x>cm3(0)8%-c8w2@)uhv=hho9qWkv!Do8y|GDmohjw zCgRM0yQ<1ZV#L^^^Ojt`d*-5FXSem{+X3giti||_7qSh@tNafXSXsLV4)SO}N#Kk5 z8laVXJJ8#Sja=nu%TryUT-9%}DLnoln0Q+X&q#qeQ=oYv`7nYcf1e zafMN4S9E*axOaKF>z@eSoTn$fB)ok|)Kln2^nSf)Nyg!Zz(-D4c;jAly=&rzh`^Tp zcOxtczUqr7Tt8W^mmGTg*}99LcS%g^y0JVhwe=53wkW4p@4NHq4!h^J5trLqZ*xkB zu|~oJ-4OMN$73?zv~WYX`*>uXWJK55?MvNJs+AYrRK4t~L;QL?ZwUlHu&^;GvIx2U zEo9KkX3gg)I!WYhOVsn0XaoJw6iIV2)yU&LLESAeU#mm&s;_;hj7P{ z6F=@4f4Y^WQy72r_Bf$35x@7C&M_BzeJSU^EQ2g~?JWxv43pz+)e@GSw3}31M3axi zaR>Q$v3oAa=7!$#YhoLFoMVe8ZuO46WJ!cruw$8tuku&{HEuGylN42w{LmX>Xp*>E z!2X1@0eMLtYTErA6?@)j;5B%IMw1N7&WSW-%k<4-3HsV@!=?$_#?uvc#Tqj+-o3x~x+Wo_FlJ^s zAxq+3O<{&ubH*{|eU!zLgJN3Nf&3?5^y;Df$x{Z!Mk~1?VGB)o?U0u#B zvdHA`i*K^b%HNeGbSHUJZC2~z<*mE352$A&R@vfy*^*@J-r8)LzHHeSN4U7a@&5rM CPU8mv literal 0 HcmV?d00001 diff --git a/docs/glyph_conventions/points_conic.gif b/docs/glyph_conventions/points_conic.gif new file mode 100644 index 0000000000000000000000000000000000000000..b9bd20023de5c0c156416abbfc8d2596cac04729 GIT binary patch literal 1764 zcmXAoeNfj`7RHZcic*d{CYDQ!10+)hI$w*3$BrC z;s&@8+#ok(P0UGfLQdoy9fSmwK$3xELNb($BnQcb zEu==NNg9wwNQ2Ulm7*je2_=y;P7n%E0VxKG3B^z`QXCW)ilgGBBq%AAL?uZnP)aC; zN|Dl_v``wACS^bwp$sZR78ylC5h@}lA`lu-18D}D3C&P5(i}7wnxp2VC1@$ML@h}x z&`M~9T9MYEwa^;1CT&0)p$%$77Hv&J6KWzSb`S>802u~`3B%AZG8_yShNIzRBp4}- zL?g*4FiIGOMv>8Av@jZtCS$-DVGJ5WR)Y))LuiPcRRTePR;#Qs5fjAFYJdfvxFC)e zEejG!K@zQGtw2c$QfQ@M4NqE-M$55fl#C#QmbxWMB#6*@dEFoU`wmQT-p-wvulO9Q9T*Mpwpf?(`}%ImmEEvJ=e?S@${1JdAaZ8%#VGw6h-R01(DxJ zzqoplZAG>B=(qLp>che3aaq02H)ZQ@wmy;evF+WsjTLoCIBoKk$}NvjZ||tCSp_?) zrUfi*df{gEj`0sBbfx`#qh{~0*?ARdYeVWYp1yh3BdDwE(%zap_lEM)-fM-S^_c+` z+F?#c{WRxzMcGd`<_vno^PS4+^V&1>r?K|BA{SL;(L`*-peO%n+j$JG@ykqy|yrUg^rs&CmVN=h1 z`^5I%7aPNK{9kH48TgMG(Y2w;vod$N&#j;E-_Vq29}R2zeEjfQw&1O2c4vPfXYy6+ z7pGrcnYu2>emG$HHvV2(NJvfa{w0S_x$lomzn&Ml@N4_klnsp$od-U-bu4V*wl_K_ zrQDN#UOS!&No$Mt8Pe1ln>8%@XinztiC(#nul;u1mkU-k2Ca^d=x8_*pQp8fpw zNk@}5MjneuN>9i5-1J-H^0vgKEzYXD*xa1+*@%;?vXi~zzKi@{eqDQE>W1_W4-Mr# z%Y(`ry&WZ27OioVHm&~3p<6!gb(FQmJ=b^ghtxHFr)t{w^d(%dB?Ojy`Qw@1wH3ci zoUpDctYgiks)7Eu_x|gFi$|gU&DJ|%iR+}q!fz5k=bgFcOjF<&kGci@XZA-On?IU6 zd|gIg`cp%@i%QF;eK_XC#DiP^T31`ta-x20(iB@m`=!Th=dZiF`MeeDXehcc$0dK? zcca^H=U@E(nFB9fjCwYp@bX}v^Tk*GG}Hg(>(a@@VPBL4aQrp1v*f*X!c zJv;GA?*GMd1vD5uD5fOH!Z*4wP*Igz1TxTNAzyXx$Nd)%QTz4 z@dF?K(5M+#H!gFm*z50p=e<`Sc&^M|jNvz6NKa+_xp_-w6uZ6oMdkC$+6zXUiuvt8blStu_Eory dz4NK7f0oObbKeY^acBF;#H_&&M~{Tp{tr^*i=zMl literal 0 HcmV?d00001 diff --git a/docs/glyph_conventions/points_conic2.gif b/docs/glyph_conventions/points_conic2.gif new file mode 100644 index 0000000000000000000000000000000000000000..9617a7b1a67e276876501a4c567deab7fae327e2 GIT binary patch literal 2158 zcmXAoc~}qF8pq#@n=F};JN6|UNmTaAzO|fW?_|PbO`|xLB&4B{tlj98rBtFKM`i7F z%fxVLu~U{DYg9-ymP)4H`E~F4<2>hi&hvbq@B96HUnlBlXS?7f+<;WRN`gYr0Gff8pwXZN$N(iEHb?>^APFEL zKnNp55`u&Rp^Q*TC=w2YGr}d|NCXhUh>%1eQ9u+UN)m-c1JR6VNi-VV5o81~BajJ{0`c!j=0{k}kaP0SBwgR% zf6=u><9M%|Q3L+bvT(=QV`Jk+&1)25H`s#4JN!G&Rr;A19JPoTRk3ch&(srBC-oR2 z&z6r)F}vht^>$6l_=D|MM6a>*uPEBhpI(bS-{1P_`L!9vPp@a3e10*gaf`05YmSYH z+iudv^)EKyRqnP*hbV^%#|X|4hZ>T^=?^vk#^h-ie#}dF##JGjj`56UI+Twq3ijJU;}@CwI!I zey2|O{@!i!+^n@_ZwgLatQcNfTV46;`k^ToFVuan`CR_|;{)qWb@g>?=LI#o=M?|z z83)gT-&_XN#07U8YjMxbw7L5Nw{`;~53lajHt)&iE&&!t0=kDSDc)gmG`VF+Gv4knSl^D>qPgoPW!_0Sb}25|V_mF7hJC=3@bswR%h#7?HvQ;V zQJ)jF$IjY&MOOaYW-$p*jYdqnP`_|}$+05uW8}cMR`l4C$!XvF$JU=|v1+-SBYl14 zT=DGKxITb4B2-6!(TC{HzS;ll?vDo5G&Uo*3rL$uGBk2wR! z6?V)pzcKOoPhVHd zC+lyoBWGqUD@p1RnweHmoZao5Nu&4O-%Kj1dsDhHwkUaLBHquMn%u7KaHo^2ui9_3 zzimCOBEsiF*N=WLf3>e1zAL#TB<`2|BM0(FfB%p??fA1nc;b7&Hl{# z)Q_8tNb8fvd4CwCIRpg<&(8=f8?&nJ#O5EUnUO8#U1}9j8En?_u(6Z#Wz*>XZijSH zSmDE7R`jF&=!rUJ=+<7RN8WI3ozT&HOI4fBpDKUxDv#cKz>PeAeP^rFwFAC$ONV@K zZ8B(L`P~b?Red_|%bnxX=Kc?}huT<+_akB!>|E^H)bUHY#p0RgqP+aKoXek@y4b97 zSm9BNlU0$+b~>iKdRY3i&3bPi&z?*w78Frg=5ur%ZVPI zGsCOwhKx0uwj-fg+giImNtS0!T>Sgqx{T!oaflN zpG&Ugpuv+OV!W>sf0JdGub5m)a~}}Xy)3rX#NOXNgwU$?m2*Y}&T5n2KK;-Cq=b6= zz4AA2c4xYL>$$--xm)I->m_Cpk(jlFhnU)GnTM$L_3_}?AJY&b0)iB{PIWgW7BJ*X*AYQn1qxk zyC#qVsVK;Upb%X7s>3|Sk5ufW1Cy&xhM)}nqN4btj{ z8Nm!PLzX*6f)O$zhfNS1kOOfBoC(g5GvXXL7n~#K#3gVkxI`|AE8t3Sg9N%N$&2EcAbVed`XtH60_$Rq1#60U0li@T{G}cZbawoO|-_m9wQUe-<1#v(7WP zD9R1fG;;8!>MO_~}MRc~{1e%h14`L66a{aW`+4 zUEVOvZQqs55x&>2WIY!)rSl&zw70peAM@hEMcEHpvtu?=xp2<0z3De`Q_ZHl&vK_^ zuiL%gclyDSNS~p^rHj3X@=BruV%ke`s9|^g;&m_i1 z=C;Iclhrxhd2#D{yYm-kd-N2{p6Gu*uEUm8nz3`j-o&&&*W~o9{)4}JLeYZOFUA)p zo#}O3^Fh^x($tVD_xSg^FU?6we{3teKL4Xf=XWh?{@%U3s6T#t`G#%73sSxq9sKBO zzI%hms13s#eKBE${aVr550hrPW?z2xaBtiF#8TU%BYj$G1qOFY;f-ha$>$=s@@ zrz>X0eKK~AE%ogQ5er}0oOL0}oS0tpllL;8nz@q`r@tTN6FZ}8f7{AOd)<7F(Q6g? z1E+@%U3{f+02?auWj-vdFY4S zj^+9nF*{0c>>B6vx1^Nm9`|pz{PFXe|Gw1_c1YAEMU>Y)?w+1pxqe>1XTm;jXDmK2 zsV_Zkt8?tM^zWBedS#SEH#GdKc9uQrU|>kY{XJKcoxBG;?LXctU6ne%b6sQ5Hyc() s6{_E=@lFe8Eef^I+A^wGsj_X?-nx}J=Jd{A&S*LA^w%xyi6 literal 0 HcmV?d00001 diff --git a/docs/glyph_conventions/points_segment.gif b/docs/glyph_conventions/points_segment.gif new file mode 100644 index 0000000000000000000000000000000000000000..e14053d70fc61c71843d99560cec10b21ede485a GIT binary patch literal 1548 zcmXAodu-2F7{=cU#^w(uYOZ6BYcV5CY8RX9vAJya(l#xfyK=G%tHvf|b(_+1Xh{{- zs_NUWQ}iu09cf&D$|yyTn!2?vWvNV~#JlfrJAa&<fCF#{j=+hh1cD$0B7R9g z1*AZf0;NzXQc9EtrBP{8T9g50P#IE2lm%r`SyEOMgJM)nibXk44wWP2#B-+vm5>tg z+XU1=8bmA53bi7wL~GC*wI;1a8_))|A#Frk&=$2NZACL^M$M#Iv;*x>JJL?PiM5~> z(jxxR0S%A=F$#=AqsS;R8jMDx$!IYKj6q|_7%>)%MPtcWF${*$Fc}u(z&JFHj1wFHvtOaY)TC!FwgJrZ#mc=@-4y_~W z#3N$`t&kP*BLZX~24MxPkQK2K*1#HB6Ki1uY>*AH5w^e<*%Dh}24-X?W?={HkR7oT zk2VXk5R3S+13DlF;uJWAPLWgMG&qe;lhfi1ID^iRGvX{bi_Vg>;usvGV{$Ccfph2_ zIVWC&oS+kOBK|4?3Xs<-uS}v)6nPEsz>7xFsCF=z$7R8d6f;YS{3X|v9 zGb#?nk*Ds7il7L2ug=dK{FT=OF-}J=|Vd(CXt^McTx_-K4#<}f7 zW6$OEJh11BxQ`QhMHKeyS(-Va>BW?``E)ruWPen}nf&a@NyFvxr8fNN*p6Ap1Dge{ zH*VkXlHCzO`87ie<~}X2@ReniA6fdMHseKIc4hJE+YKg#$9x-kbWw)^We)@M?)tV2 zn0Mpsq5W0oQ-{TM99wwce(499^&>hg9{8{m$3Oml-_@eLtfE8;>l6B5!-d*eMF)cGp4=>s>-_fkqTioCtuD=;dcNq$ zi@LvW`*!>>BzIB$sDj(AY3b7Qudckx;P7Ri1dL7{+qmPF(q*qd-V_;I@?n$CASYb??%~;YF=7;u5o(w2qkYroNmsEH`n}!bppE;(OSb z)a8*&PNgSJv4=v|-pHG?d*sh0bE~$++{>!k{?oJjRXdh7?p2+-JTR(y=jv`$owjz+ zgX;A4Bg^+h%^VYUYr*GXXPPG`54x5$JSD0vWu%WxzMr{u(i+OVpB?-aWl>uFgY-;Z z^JmV16ZJiF<7sFjgxB`>_->-{QdW(H+*uUf42YdOKg}-DG|7;Cm-W z)ei2zyurJ^`3D1XADOdVDpRIxh%9=UcBnS$;BoJX+<4_eHlvvhGpI< m9b2}w@8RIsknSbni)#M461l3+v#T>Un?}#Br8Q~@L;eM(N*qA| literal 0 HcmV?d00001 diff --git a/docs/glyph_conventions/twlewis1.gif b/docs/glyph_conventions/twlewis1.gif new file mode 100644 index 0000000000000000000000000000000000000000..3b2d4bacd263a42356e2f1955db9986efd037e61 GIT binary patch literal 1762 zcmXAodr;O@8pj`BO`&l%T?G-fG!K^hrj_|(Xym0qJ&2!J)wmOlO7I)9uwGiT;I-{<@JK2!MQ zH^;<`?J^7=!Jh{K6aWDOUu31SNqa1IbV_B^gN$lB48Ga*_h1Kq-_IBqd0R zQYtA)YLFVGR#KBRAPq{Rq#=upB$T8iksA@92Bm>C1I}VOCe)-fksCXp0cC&;1H;fTWf&O_hNI!ia54gn zKqHh9WF#1gMk*u8XfPU$Rz{OCUIu4GrEq_1G8Z(|q1o)=+VO|3Uvj@1zdo|A-yH{RY_p zX8jeMwxJ~v0hhe1H;?xEF)1P=?`)>-UfT2V#bM=piS?dd^&tAPbI1<=)rsva^gz$t z=Nl3;S|{XmH841}Pkl^cKc)u_|rvr&;hN908B&-UzE?3FUQ?rLG& zh3x5N+GUF0Z*8n8Yl$uMw0GUGHvGip($g8^*b49BMWxm2ee=@ZEvcxAh)8!l85R2T z?e1%KljGi;SE8M_YM+k$pmS~0fyD!cuK%s*>BWly1@?34VdG}0tVJg=Y^`U|_Qa2~ z`lYPOELw7XQ?JP{H+|A~_TQT}`z$`(lsquuPScjb$uHNgoEGW0yy4p?ExRMlkP~5P zFE&noG0L&er!lxXprUzoV7X7+`sWf`=0@KO@W=S!u~)8)k3HrUzQ8{vw|QD~K+%x( zT@NMC4GsG5;fRcL4xX{gO#EfXd>5ANT<4kM<@{h|4f<@W>*z6W#>#rdlP|}dl>|%M_%Kd`t_t{*|+cA&&R}O-8|4Cjn>DBH#7rv9}nYe4f zdnZU-HV0n{sda7Hn}0A@`4uSN(v~mB`?uab zerdAZb)s%|ysPNi;sTd$NN9DPype3bS9~+w!#Cz`T3r>5|-X6`rNzDchf&Jy_SCCiy@cJ zr+WL{KX)bR?y^}&zaM^M(k(B)mP3I%KaD!GGG<<0^04;Q2Vbqu-a7MwKK0hT>IF3) zVogAtb9B{_|9NI4*-u9F3k@&Yb8~6UlY`-9DUp@SXFLs_Rw+&YB;tvOUQs7WjVG-+xXn*WvMzeWL6ire4inTH!o-ZuqKn znSOmr!~T&f#Fez>c-8AWR@A1wrF%b|IJmtf`&4xwXTa8lwzl6U)V>kam});0xVGuI z{JPV1>%#YM9)4!*Pct9A|H7T94u{u~h4af3#)p@_?ecs3JLs7MJ*J+u`L=EF2+6Va Tt2o|OTXTwRHW>Fi8A59j literal 0 HcmV?d00001 diff --git a/docs/glyph_conventions/twlewis2.gif b/docs/glyph_conventions/twlewis2.gif new file mode 100644 index 0000000000000000000000000000000000000000..46d06ce07a5b565fd669b958c5bcd42015f5d07c GIT binary patch literal 1277 zcmXAoZII7Z6vq!KyK1KgS;kZ0pfQ+eJT#kH(b}^Vna*JUc`Bo^I?bpSX&QPMmS{MJ zCN#5==*YAh9Xp;{ZD>@3km0U|3d@UL(9^y;{r+`d+_`h_%y+)$`}y86R5pCr%vS*6 zZ}@*PfB{5y1IT~|7(f8TKn4^b0Ky;!5}*LepavS?0M6hB9*_VMLo!H_DM2uVK}22> z7{L$%5fB;C5CaL27|D{R9VkAKdq)ck0K@Q|hZsb7;C^03Y6xqZSOkos}A01f01VRu5 zSU|D6*m{ zh7u^Tk|~7>sIZEuges`As;P!LsI$7MhbGX(noLtaY~j_WDQEeDJ(_gs{|ZiS*x-#1#+Ne4amR; zagb%SGDsmDVp+0TprIUUSqjJaCwV8+EG%Wrx3@vc+qR-yLlJ+Nuv z#QP!FDOXW7XTsL6hj#0AWq(2K<)cGezi|DIb4S)Uta@N=zp2M|e|l=$ge?^xR(x4C zYGc8?&fO|b6rb2ovUA0V8tzfHwtK6K&rF_Q`*C^ed3&!_tnFL53Yr=Q)ckq5blA+J z?YfVvue;P()4uN?T?Y66v3A7R!F?9KzvDTRL-W^7Uhu``cZQE&bYc0tt4DW6&tJc( znmh1#13lDb zx$^M6wBpg1if1gY9&q*&E&1W}^w}+E>Tz0A;jG@dx?TTNE?X#t4NLBAxW@qyh<8{74<=FKaIUT@yAx~!5*q2yoOt!I@0 literal 0 HcmV?d00001 diff --git a/docs/glyph_conventions/up_flow.gif b/docs/glyph_conventions/up_flow.gif new file mode 100644 index 0000000000000000000000000000000000000000..04f0b5a2f1ac429cc8e76a97c271d45e8ed0a3c2 GIT binary patch literal 2648 zcmXAoc~}p~AIC?_CbX-Z+bXJY6*-a+euOmDwpdfE6j@O+QXwMN>e!A=jnbj(+eH(( zGNm?0N{4b(*qV|vVJSq3%-|}dEasTH==U?|*9HE6FaQhy z2_OIv1IPfB00Dq7Knx%W2mk~F!T^zg0zfgK3{VL;02~9(0GB`jATSUN2&q&85(CMA zlzox_L%<-A5CRA>gbYFn5r7Co#2}K807x(-3=#<`fD}W@AeE2<$T8#$atQ^10z<)| zkVK2rvXBf&f8`AVW|h1Q5aqF@z){01=D`LqsA95XFcxL?z+?af~=a zTp|IGz(_D8q;g^;F_H{P**7}C1TX?5fq+0vAR|x`1PH>Dkm`X;a>_Y@F2aE&BA>a^m$T*Z70gf<7 zj3dbj-~@BRIFXzJPBEv9Q^`5t9COY%ms|iYFc*vqsie&%=8|zK`>+En024q82n56e zG6AJPKp-p-6G#dI1i^wZL8PESP%J1DR0<9R$AUA#r4T>}ECdrmDjOsu7Lo}m`>F)6 z1Wef~Wtk+z5;A22l;9=85-}w$B_v6(ButsCGEhmeq)eHDa(KzH>cJt7+2b+1n!;I$#9>O#)_Q_j~ywXKi3H=K8?d)GgQpAz|_8cIeO zb{Whh!o7$Y*Gx7P& z?f*GsH`y<*u{P_cG+U=#CLU3_>w^E9D)e7BuJU|x@5J6NhZb{x)!Akmn_NPR58B)0 zChqV_s7^@BPJ=JpJwd+1N|5Nni_O_@pZ+P z2>&>ZAibk=lFXa2+iJTBTG1QAG}PTRLZ*jW{`S|L))P-6=6`H^a(L0VlQY~`tD}2i zWTl&8z3Pm3U6=k3q+7;P-A32u=qePF8R@W1ZDXu+&+dk}jYr*E<6{Fay2P#5aetWL z%tO)>YwxI~C)GR(NnY2QoxM5aK;iM$@I&ABC=>;{Op&JYotC{q!+BEnkr4~yhwUC| zRNCfo%;+EYEh)QZjoT8Zm*;RIUD24rlFn8o=fq#_aWl7kFnp}zar2jL-i2=*)}Fr5 zZ2Dr?BQ@*EF;{v9MV$5CALCN0W^O#SsoZr^Zb5m%pDhK8 ztGb&*rzTndtFUv@niku9&!fG#yEUi%(wC2~+AjmuDIHf*FIjh-j7fX;W<_VbRm;9* zGZH(lw)uISu#2vW^D2t97;1gCJYl4oQ?$cR)f4xRHl9$`UjC!YF~|K=4u2rk{k z!(;h!^^W@shS~6H7oWWy4TEy0e!RSO@N3?<>9W(A4EHkP+PvfYllg~y&d2kI2g~Oc zJPP#ul)q~DY+IAC2W!+_!*_KRb>9eS*;nxRn8&4KXNRTbm^_{2t8V;gU-}#0XJ4H6 z1-rru{{_f=! z)qm%$zJF+;$-1cTh4^sQRp)bKZLH_lPe&_l^Lje>>lA*BeE)-H_hl1Lv*+Bv)2Qc5 zSG#i0bsKv-$Io1T$J6bz#^H{H)iWa-{yca-{qCCymRAGcR`_acUFBaeD)k#aW&e}9 z)c&Uf7InpREZ3Q@7-U~jGP1BEaC*36$Y#rHT8$k+bE*~J`Bq%h>FEewl!)K{Q81eP zFeE75`tA#Zpi=z_HSTL1b&CETH9lEAD&Wx*?TZ#}V~5V39+;{-;#+^3G@iH~9ICXr9w8pt}ZZz3^is6NGk2siEucN2p>bGV{ylzTaj7s6a z!(pWxV9Gbw(abyaYRSf=SqRy-RvuZSGJdyouEH=+ft zNZlcJY1Giq70aCLPMc&p+OJsAYF1gMYL@S@#EvGn#LLLnQZQu{Cuyc_r#`O^G|QSdD#C&$@AFG5cB<^ zl_?9(9dCO2V%ov|rKtfKnZ2Omb`Vud9Tm_PF|^UrPxE%#r!=?u9@#5ixya$`w0cv! zXSSIJCv;{+MV*K+4=q0YAS_dVm3zb$-FWi}~*Bv%hNU`4|2+qil4>teYdl)`hO=4)xAi zzG<88GP7w#^Uj^?_u(EL=xDU)r~H(IPE)Ygj}>FTY&zqPSga3J>9`~jWY2P|+i*KfG}r)^%^sG7lT7G^zn NA|vu5R8)Z3e*pn~Kkonl literal 0 HcmV?d00001 diff --git a/docs/internals/Image1.gif b/docs/internals/Image1.gif new file mode 100644 index 0000000000000000000000000000000000000000..0725ca481c9e610d3fe88fe0757d1f153873abfd GIT binary patch literal 3939 zcmeH|_dgqo0>xGB+o`pxl$bH9wWYLIQ@i$v#Fj<|v1f;oA_P$@NMh8eO=+*K+^kwniPx&q>xemO1-iyB=V@@?~Ea^)T)xdlnXe{kd zmjV;6nl+UTW+~cNpAnPtvcRdS(p>cd<=JMj`eEGe<~llk&-LG_caTZ-_$p3~>+&qg*f=5R;tG|-{)VqF>1qR6T%XlI4~ z%6D$0t7CU#zSrV}`M66l>gV#O8jpZNeI$w52k|M2x_xvYvaS)fk#Xn#?(uV;`Piz9 zsCnO0?L6~$dFAQuPxq9nO=9wDJc_Cf@9P3-cr7!fw*it<)M8*ZPZDj^kpI7yDJ_f_J6I#Ha?tI8%N1FJIaQTpW9=cr3>S{Bf&1$zsfjh3%R<9KIkzXaa7;#2zMbiLHKv~9OahAoU3 zxpWkDTW=YW&eCDknJ6qUBEetT%)FCYbkr+_L5-zKk;f}$MBWCwpI2Fg&gx$$(Y&2M z=eh5rn}!7Vjz&gHnN2;{)_)kR4SHPj`_*5HdA+w>(Qv%K*0OPYu-UJ6a=4>&^f}~1 zeRh^rO=kC}_X$v8_K<>b;>9ywH!N~~bLpzi9wPOyLuZRFF9IYCE<|u&w*5<;&+yfk zjr&vW*Vct)awawV)USaucz3~u=bAVD#Lg^G=9{|v3_rvbbrid8LJY+PD&i%wCC>>B zG^Pc8@Zq_dFE~7@ws82t1I#t`)}3_EAH5oCK0b9OM7RD*J$H)bPM%N}s`2RgrW!|z zD|Se+Px059HQ+TvKr2sMj8%`n_}No(O!RI(D=6s^C6^yf2j6&;mZ-2JB_MIfxj|&e zH@(8^W8o&MUqIL_GbR3<3qZ_7V{0@0o860wI-^zI@%Q$5X z9CD^D$IHn)xB^d9&(#`@Q}307ykMAwcl9a#eMlFLa3*_WQd}ktzXt)}!>lDAg6^V+ zDtLnSM0%O5qv@@a1~uXzS<{`lC!<|6t#qSlyWsqRtUl9h^x@2QWNk;qZE%*g_(FZr z!I?_5tcgx6Q6aLrc8w(HCsgda2vzUf z!k>k6yCmC)Ybt0dMv;Sk`6HNP^H;*#Y-VO);`qsh?^XW!LlmN4igXh3m-;KV;yBO2 z^oC&CbAIj<*?STs_sx}n$Q{28B{-$~I6Jcza!?Lt&-UCKlWiUBQw#fg1;`V?;`DOv~X>b3Z*_-Qc8W+?Oxb-DDhO?t2Nr+nAwW|1>?QR))DTKDU_xfJI zTUBCXD)RofE3ipyte0YHiNlZ+eEPu_!f^FNxStqMf zdfjcQBS?3|*iS)uYC7g-sQIV&`u9rm)g~=HKp+=ST3TI^kgo`cOhukSg3Q9-1zv~J zS3;lLhOYYta&}A`r-lc+ADQw}pi?^-ww|GrML_aDd%nolE^zbXX|r%oBl zDz|HK3$RK_?Tc?2#ar!^h#xJRHYnqK3)|rePu|@`YLM&lRsOlkh%nMCVKGR;>jH}su!W_vc|((O|NetM_lxFh9cVo-&yGSPJ+S;74(Ve4{slfqdnBx}>%hp4uCwoUAl`=` zS9_K1*&0YlofvVuIOPouPi^YmZvC80U?p}jkGPbH7NEBU>EwH|mfx-)GFo2len;r% z1gISepYPbG>$v@D89n;(=;R=WD<+lohs#PzwcLOW;myn-Nf|HCDVb6t9URvt2{OTsx4CDyH(Hims0knrfylJgwHQf{?Cq(`iRt zEZ!|#2&6CSNK3#Gg`W1X4O9{oK?9JHB`u&3PKkjVLb#!}WB>XTpM-b{Z~FjFQTh?dxCRb5Svp;RFUd`9wMx;`r9N&N%^d z69#*^hqqXcel41ED+%V6hr3|vFyIW$9!p*OlsraHq4Pl=4iHSk@eKoMg^D(Hduc4) zG|gpbzO!=(XZk8HtYhzXk8{GfV*35O)M1fyGa3wvif>6GE@!1r7+~E=i9<>G2L(syfzAPlkK9V2e=81zc%1{ z-89@+XPxbrL9a9@*&65lrH_i?p;#+W_qeDNVsSMc~*sI%zclaLVRHg!iV>}S66>z(}Hde9@F=gRLQPEauy RteEFvG2cV$Q>Qp?{Tr(iJT(9S literal 0 HcmV?d00001 diff --git a/docs/internals/Image2.gif b/docs/internals/Image2.gif new file mode 100644 index 0000000000000000000000000000000000000000..d95e09caf75a62f78bbd406f30a89947d9a6b577 GIT binary patch literal 2190 zcmeH``!^E`0LSNCp?MTS-pON*2kK>=sd$$A%^=D|vLIR5Ax;oGtH-&8xAr zdDCOeY+jRC$s@A~$;DVy+|&IxZr>k1zkfdGeBC|W?CnCx0CgED0I;?tQ2+n|zxTVq z|FVG5hU|admcRJx6DJh50Wu1D9`w@JsS4^A7ddniD{Z$itkB~*xhrF@?Uj!l>l1*i zea<+&szKu(yg5AZ&#HO~kFevyo5G$!p*sMA`JmSXFYPV1#{%_Xj7ol)2i_vjVb!cJ z|4a$&kb?$^UmcKuQr3AlGf49*gCJp#=ltnbT@A8V&K(*pjD)x7_rw{!Cq@Y4I(z(= zF14pHsYSYiI!@b3#eT+mk z9fl7ZWY|d6ZInbeKe1wU&{U7W_+`pmu{U2DSl+qIr>IpYekG4b&`DOg-g0_u_=TNb zZF|zSrKz!pe8VNU-Nx$Yw>5}?Vms+Nb&}O>nY=Za6xNJOnohx?Zrp*5Q1%-W$?%)rc5 zn=pDDL|4O{;;85Ai$-(~)}(|68BwZ6D!~Z|?!2ItzbVjYH~hf6K*jZc*X$Tr3ks~C zn{Tb9vDxNy>_F_8#Snfu)4G(Kp?8Nk@zxWA?-j(4-T$rHj(Z6nXHs zDU`ZF!>2UkEb27TroU2{?Yy;JIfIAS(nP}(nda{kvCzg@OzK3#XEfemO?)m)4>_Sx za7VA1-VJt&&9CLQWN&41ne#8_2%C#s8m>azr?yR9teuRYu+9|ojwZ3OYZys$#5;Vy z6I}TjbFiQlBz^OBODI7FzBJu{WekM89Y$2N2OVDtUZOwnnS{o0;>>TZT%7gUpSH59 z@(M*@e7#$Z>iVNNN#)TAfZQND^+|R#UCJOJvto9cWVKvo>jQ&Nn+`0L%C}OO9gO}E z_40A~@28G!%~jYa#2Ve}Xaof5YgTy)X(JiJce>T>1FGJV#|}T`=61U3 z15df#pXz3JTczGxrsLpkTB#(Qfv_&OP#ZsD+|WmDo)mg`r2d|SSFR!?9zW84J@V)a0kQIF-`)0Dho!PGc5k~TX<%W+_X#8PY)w2DUl7(zHCuLow0*&ssD4xegQ{Mu?c}=2Nf~E-RVztwYb#)Jh*m~JR*WQnsCrJh!iGnRQ`$aWKvJO!8 ndmXsN(|foFys}9h8kuYIgVmNL@8X#nYbA9MjMoo*&TDT&MZJ{!ie4lEA&wEC0I zA0=w0&&c%Q#UNT-x;Bu3#`R0CQoz<6mZ@|EciHW#5M+P#d7%RET#H+dI9~KH^%B_K zWJ9xpt41LuDIK6iQte9O^^n=rd-n{9V^bO@f+}ss_`m>pk`3H%nlf*IdI%~Bt2pOn z%q(%}LNEXvUP=2sEAZ#4o4;dSyE>Q?qEl*(EgEY!Q@^mYvGQFTCzw5)n`^EEPnEk2 zq8U||C={2Et@){3zn?6&n=N%DH8=lW?n40_hx1_L_|f9=Y@_3r!`=yg$6mFFHjCc5 zuH=i0w8p@V{*AKo<2&s^z4LS!V^1UgQ+NEy?D9~-!o62L--zaUHnf(#86LyDGjkS> zo4we$o7~n`CVvk_SfNda(`FGo!42PZd4Kj68hAa)=6|UNJS4*?^Fm*vnDVc1r0{hd z--)<48M2rtoiXi_qS4xH0#*(?_?~u7*I%5;bPKa$sp~IX;B{LD`8J#Ss3kkA!!ML4 z(ELTgnj0KU;SiD+su)RzS7y)Si2xeRCsWH*f#qXnVJl=94_7!m ze|VCv2xzY zN63KOE9b%E*ea;04A#p@bie6&+0I%?YS>WqXrum35o6~NTa(XH}+EZIwf)1cxsHLevU^R{4P9if^2#=eHsSH4limjP1j9d$FK~+74&NlXOf%$Ni;Z zLEEs2vR&S`E#s;A*4XMl7%C!j__)e7c3f@eNA0@N=5$=nsTg~sFE99Djg7gQ_`5Sr ze|GonRj;P6UdQ0pxo?8}HHnP|ju9stW!2}@odihT>3C;U-ATTUkEiRb$o%8}YRW$^ zN=^fw(*!iC%WeWS;`Z{RSF+wE4H@bI+Sm?Mwit4D|d|7fS93vze(hara5OhbK$*6xyls)Ez4&R#njBM|NaqT zMQ39^Gdc-?-AzguXfJ%G-9uSqV(JP= z_C13n5zZpDlErbO7i*+H7XKz=iJP%x`jL3s+GswD@;XkqujFzpFyz++NM^B?7n%Jz zzSqW0JtVk&;U?=pUNNM3O-^lsLHPol)lQutW! zEDs8R(g;%WTkOD`&qG+hR9*Yc-dHiAEszDs`ewx)Xwt*##@g~+Y8mHa<<5FnZGt?UiiDQSh(61w+tr`JXR?|`dKFrOuA7qOk7{zx%wGPXb+YS(M*<7UDD#npqd-j^JjugbL7WHqJIm>L&<|G?2n8`PwAz8pv%$7`6ZZhf%;_w6{QogVU6HDj>cbfsG#I#_O+W8!{ zy6~#OtJ9t<^5&+UH%dk%&8u|lw}b8_D4q!nc5K}g3?E~oBpju-Tq@!3UTXYyS3s}j z*QA@?ZHX${>UW^(3h%wEFP*lBC-JfNq%$1(dponlOJCJI40XHnw5p=}!{vD+u%TTo zTR9@|<5NJiz2S>t_bMB4myFc;ms2NH*-*U*Z}_L|g@XY^z8?KUOGaGFD;&Hap6+PPgZp$i)PW!Oz``x9HF!i3 zyZ@1DM^U*%9R=Hh%w;yD^8DGx3?{_ZsWTID!Bt)H7l`^&#i323aO!yBtpIA{4;or6BMLvRctrkgD*q#}&)Rj-wRr&7IziBXB$LW*F-^VQDdtNyY=AYQ*T_g4C zL*G*ZYYyd?ZUq?27+0bq$VGCeHtkcc(vg1m_Y7_Onr`0;>B9p;_92zveP2dpJ!>;DXkmm^+l(jf4{9XiE-OV;(;g3E3E2=B(T~KS@`T59SS8OelWScF( zTK7?;e}I)Yud*s7)RCXD-+4h;g?6#L11#1T_XjQ?%l;@_l0i0Gb95o5tx@{2%NK6H z@bB`dBiIeIfX8b7URM;UoIzcE_NxJ!1MJ^@MvNK1u(v6@E^VJ4qj%I-kP`kPyA74# zpWlh7h)!cZSpM{I@XaRWH8&B5MT6a(NTx<2z)7*T4gU&v= zeeF62yLM+wgX`f>`pHjU3_*=%XV0c~lztyRgXH}CY1f}%Y*RWd(jLA3m7!lBu5?Y^ zINUwzC*a}(cd#WZo4B=t@l#j%CYGq>ppbkzwX-rE)hRwh`LGWMQD&u&J9J~9h*03$ zXx0PILpHTta5TR#*x{ECb)Lj5AV#`kcf|G9zLV5I>6$KjodIHW0#Q zUc>_*aH8!RIHsjc=hnXNEdGI>Y`n#c*Ro)A6pM4bD1xI*-!aHISuaZ6C3Hc-cMXoz zEJ6A?!{kdNY=n_oU#%?mBTEV9{7NB2&O}wtBu6dh;^G&Vj=@=G@u0qFTTaNV)hh|5 zCxkxhazcz1U5LZRi_+>qC6ru>RYe`Xlu9NzQB0#AHoOe5A1bs$$9?&e$32bV_J? z20A@PJEe*6Sg_g3awA=9B}OY0WUZvS08i0lx2%U~@sKmbAjx;J;^864BheJUz#tE6 zg=h5fET%4nEU?zYOmTAbH~)-{dZ}eAR~Dt$PXjY=z(Pj}DTNTbXU!6*>_MrrVwsj)ZWr{Z+f!;EbDp7_4vomS@|ef{7=UZ~QXZ$^3caSQSkBW`3}>*_CwTfECuWzB7>EN~axibICKLD_6ki>8m{kYBM%<2|ZR#&;79qb$P z29YhGdWUs>=4#|0XYKTj0%U?{eS9iIYk^v0l+h`ydkV0NQrlQf-L`h((9hbLwn(y0 z{)WYkK(kI7LOHgO*Eo@{8(}oC0@!DC6fugh>{Y9qM6xPo13JhNjh=CV?@ZkPhn%Cq zogU^|@GkK2JeR8GDexx7|6;i~at4JFD{3HXWGZH5p%Wi|mKQHK!N+G$)AG4P)oDq_yT7lWy2!q=%ap+6VH2fg~B|;Z7lnmiWxWwpD@L6ZfKm1zE=x@Nm*;} z5#eiJK8ga(Hltc0D1-qnljJa>_Zk6oy}Xe~z`K{MnwHlu5%m+xHM%W@^~->6yFH+&ME2XI(PxIICgramHDh$6Z#)E|N`r zOW7kKXM0}X=ihjq&kyh4-|yG!0|M)*0-YpixoD|0G=I)k?}Wxb<$n4E1~6wLj3u1`j%8 zxi*_F0;x8`_U0hXmkp{fU*b!tdcFI75GILOKvH0cMvxXLDW0^uL@K$FY@B26Z$9Gh zG8A}~dl6n&#`YEdB=o>58jE2SJkPF~nWv1{NG#YYp{DxZB&X!HdVF7LVfBC~%^v(& zFRO962q(5FqsJD8%os=b_Krwj@ahTYxozJ!f7|j2c&jdk)E>+;TG<<&O*w}6ng(P* z)HDOlef8#{RcQYiPh5<<40oHyqfIl?aSXfS zw)pkVSZ5e#sfB1*Fr}X}Kxc=YX! z@gjq$2UI?GBJzDPr$Z*)qm$l-uysXe zL~3ulH!i+doR=Cv4zpcx47al!LR1P&h5YcE89IyHrz!@`zt0jllwQerH;$1jF0- z{cwJB?^w3E=6xlpA(eo!2bA@af!mTl8js~pExXzNp;SMx;oI2i(JI+)FS+SiS4We~ zy%CiUy)U!(8U6c=`aS0E`Qfj0pM?R}J+Jc)T~x>U=0_jiwzjY8Q&gq(vhA+=sDlE9}s4g#lXFT)! zFqwF@EZ9S^X}OTsa6a6d{2 z$aEQbSC1&!9PoMAGwXPb+TZkPRsL1b$2=j@%Ew3ThDrT=FaaR0bM%c7PIvPfKeK49 zKpQwlThZhy1*du=Pd=<*qj2d!@p0P^qlAa*b`ixAgE_R`ck*C@&p&WALC&kA@KH-A zZVVcnvu18?zkV%8TLBHX%Us(uilsS0pK6?pVf|qea*jwf>EX9&$8WNgq9}&;HhWnY z1E)`wBJLYG<@tp{uFS|=gNIek_FygJrShUyhQO@7yagpe^7xF780l-uVO8matLEv0 zPD};NHxa;x_l-{>Mn0(GDLO$=r=7yM=D|m+oL&iv?qr?0z*WE@py9KHHwS*(|JfG9 zy5WOK!{Vh+2u0g7QmrO3tip;lCqOvR|7qz}IS6M}7K717+K$R0TJnU2p@#!=yYbi+^zkaG&kB)B* z=L;2O)q3N}Xs#Z!8-#-D_4m4iJcDLBq_s!ovleNQiggt_(l?s93{u_kmXuJAUlMgz z)ffSisb4NpM;KxK1p?K+@VG4Fx}|2*7B*2MFEVA@O9agIj0GsDS5qCbCFhTyRywB+ zxh__Wl^l%LMxKiPVOi_bHXES~V&wc-<4PZ@Of?gwknE!a8k^qD<=SDZ=)#`IO!Vm1 za0^j~Vl~};vwAcm0YKESHK3D1)!No`Ef%?3qEIdy)UR3Vd!b`^a6YGsJUe&7{uzT z^@kipwpMZpSmUj0FWT;XcUAV%7O;kA>T8+y1I~!#ocaMN##X~XdlcbYm!_s^Z@df# zvMt+b0cX_lXGzl+X^^AO{Jy+T_T95r6uVZi9CHNRZu^;K_ww=|h^9qX%$2=+p=jgDTP%VWIFotCtCncM_06U_Xrb-V!C1jH643y; zVpQ`73H!Wn@6r$9D0*L=a*eG>WQbzfar8C$B)P)68hrh6aPg9wo7l~%`?j}kH5+iO z`Xv~_?G@QWEFBClb+_8}+JrWD%87KwX7d)9@(p}%N5;uMA@u4v?ts&nW(%ryk&$AVV^A^#xS}&gKAZJHMTpMv?Lm<_l6knSeB*t@Ob6 z?INs;38JKlb*D>rKy>knjWwGd@K9ysfXX!t-yA?Io_}aZVQxtWdCybfTT-`9vAD_b zIC!S^`{_H+52o)G1J%gWcY%icjy@j#j8w%cP4V|Z0_u?V+nJ@j=EtGs4kl%6cF7m5 zP06Svh#3x(Mz0V+HfRs1jKt(w{#L8rl07JI!T2CRp|ca`(6Tgv4V0kkShe>~kK9@I zOKJ!yoaeBM+OlQR(-JsEp$^o{|B-p6G0uEwXB2 zoGzn}k2+Q~me*b!&f8u*dR`yA8dY;~(lR7a`Mp_#I%9O^($PLKYpQHv;t=8)P3Nd@t*|=U|~<9$KiALVo(cXu+v`lt6i)U#4z7?prVg{`{jBcKW<*bHDOvFi(!##=mpLDG!NYCm50gIAB{Cz$( zfRLw)s<&X?#R0zWRB*BS@r`=1LHd5XrOHKE-%3KXCP5@(8W>TQ7`VdyxR;w*%tuhw zvW77`zIIqc&NaSccU$;|`fTy{%$C2gQ+taJ&83=2iQ}RpdM!?y)|EBi5jU zoEQ~pU8sunC#!IA-}B~5$e47dKMH3Ez?S+ZoCAb@N5YvKUFo4#DGf17<5B$<;eO*@ ztG(){4Zc5a=*qKZS}6DH-bfWUi1NAMhAo#hVNFt=oudRb2V#|(wfcMIjDlm%5URJ= zgiYaZc@AUX(3HB=R0%iRXPLGstMRpmscub9M&vhoGjDE6gl`g3>)GAt`qLzqou41M z!I~2ai0Qf@sO4IEsdz@+&D3aQicWA^%>9h``?kvy_(8YSyy*;MK+0RI%ndAu`5hhi z$VOQp9nlz+QLh1^n}GItpv`huaJKyU)l&0cXpscI>)wFt2vkS$Gl zTRg5C#*UJNM%|Ni3<7I223pucqVb^2CtUb1nRj2`&z%g;ozBdirR07q=b)vfQU4D` CL>qtr literal 0 HcmV?d00001 diff --git a/docs/internals/freetype_internals.html b/docs/internals/freetype_internals.html new file mode 100644 index 000000000..8659e7e93 --- /dev/null +++ b/docs/internals/freetype_internals.html @@ -0,0 +1,788 @@ + + + + + + + FreeType 2 Internals + + + + + +
    +

    +FreeType 2.0 Internals

    + +
    +

    +Version 1.0

    + +
    +

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

    + +


    +


    +
      +

    +Introduction:

    + +
    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/include/freetype.h b/include/freetype.h new file mode 100644 index 000000000..4edaec503 --- /dev/null +++ b/include/freetype.h @@ -0,0 +1,2156 @@ +/***************************************************************************/ +/* */ +/* freetype.h */ +/* */ +/* FreeType high-level API and common types (specification only). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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. Note that each driver has its own */ + /* version number (for example, the TrueType driver is at 1.2, as */ + /* defined by the macros TT_FREETYPE_MAJOR and TT_FREETYPE_MINOR in the */ + /* file `ttlib/truetype.h'. */ + /* */ +#define FREETYPE_MAJOR 2 +#define FREETYPE_MINOR 0 + + + /*************************************************************************/ + /* */ + /* To make freetype.h independent from configuration files we check */ + /* whether 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 EXPORT_DEF +#define EXPORT_DEF extern +#endif + +#include +#include +#include + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /* */ + /* */ + /* 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_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 :: Previous element in the list. NULL if first. */ + /* next :: Next element in the list. NULL if last. */ + /* data :: 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 :: Head (first element) of doubly-linked list. */ + /* tail :: 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 ) + + + /*************************************************************************/ + /*************************************************************************/ + /* */ + /* 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 finalisation. */ + /* 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_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_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 = 0, + 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_big5 = FT_MAKE_TAG('b','i','g','5'), + + ft_encoding_adobe_standard = FT_MAKE_TAG('a','d','o','b'), + ft_encoding_adobe_expert = FT_MAKE_TAG('a','d','b','e'), + + 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. */ + /* */ + /* */ + /* 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. */ + /* */ + /* 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). */ + /* */ + /* generic :: A field reserved for client uses. See the */ + /* FT_Generic type description. */ + /* */ + /* 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. */ + /* */ + /* 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. */ + /* */ + /* num_charmaps :: The total number of character maps 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. */ + /* */ + /* 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 maximum glyph width is given by */ + /* `bbox.xMax-bbox.xMin' (not to be confused */ + /* with the maximum _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 maximum 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 maximum 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. */ + /* */ + /* max_points :: The maximum 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 maximum 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. */ + /* */ + typedef struct FT_FaceRec_ + { + FT_Driver driver; + FT_Memory memory; + FT_Stream stream; + + FT_Long num_faces; + FT_Long face_index; + + /* a generic pointer for client use */ + FT_Generic generic; + + /* the face's current glyph slot(s) */ + FT_GlyphSlot glyph; + + /* the face's current size, may be nil */ + FT_Size size; + + /* the face's current charmap */ + FT_CharMap charmap; + + /* the face's table of available charmaps */ + FT_Int num_charmaps; + FT_CharMap* charmaps; + + /* the face's current sizes list */ + FT_ListRec sizes_list; + + /* a pointer to the face's extensions block, if supported */ + void* extensions; + + 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 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_UShort max_points; + FT_Short max_contours; + + } 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_WIDTH */ + /* */ + /* */ + /* A bit-field constant, used to indicate that a given face contains */ + /* fixed-width characters (like Courier, MonoType, etc). */ + /* */ +#define FT_FACE_FLAG_FIXED_WIDTH 4 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_FACE_FLAG_FIXED_WIDTH */ + /* */ + /* */ + /* 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_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 + + +#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) + + + /*************************************************************************/ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* pointSize :: The current point size in 26.6 points, where */ + /* 1 point equals 1/72 inch. */ + /* */ + /* 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. */ + /* */ + /* */ + /* This structure doesn't return the vertical ascender, descender, */ + /* and height, as well as a few other esoteric properties. One can */ + /* however compute these through the size's x_scale and y_scale, */ + /* applied to the relevant face properties. */ + /* */ + 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; + + + + typedef struct FT_SubGlyph_ FT_SubGlyph; + + struct FT_SubGlyph_ + { + FT_Int index; + + FT_Byte* control_data; + FT_Int control_len; + + FT_UShort flags; + + FT_Int arg1; + FT_Int arg2; + + FT_Matrix transform; + FT_SubGlyph* parent; + }; + + +#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 + + + /*************************************************************************/ + /* */ + /* 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.. */ + /* */ + /* */ + /* 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. */ + /* */ + /* 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. */ + /* */ + /* metrics2 :: This field can be used to return alternate glyph */ + /* metrics after a single load. It can contain either */ + /* the glyph's metrics in font units, or the scaled but */ + /* unhinted ones. See the load flags that apply when */ + /* calling the API function FT_Load_Glyph(). */ + /* */ + /* 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. */ + /* */ + /* outline :: The outline descriptor for the current glyph, if it */ + /* is a vectorial one. The nature of the last loaded */ + /* glyph can be retrieved through the result value */ + /* returned by FT_Load_Glyph(). */ + /* */ + /* bitmap :: The bitmap/graymap descriptor for the current glyph, */ + /* if it is a fixed-width one. The nature of the last */ + /* loaded glyph can be retrieved through the result value */ + /* returned by FT_Load_Glyph(). */ + /* */ + /* */ + typedef struct FT_GlyphSlotRec_ + { + FT_Face face; + FT_GlyphSlot next; + + FT_Glyph_Metrics metrics; + FT_Glyph_Metrics metrics2; + + FT_Glyph_Tag format; + FT_Bitmap bitmap; + FT_Outline outline; + + FT_Int num_subglyphs; + FT_Int max_subglyphs; + FT_SubGlyph* subglyphs; + + void* control_data; + void* control_len; + + void* other; + + } 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. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + 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 a target library object. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + EXPORT_DEF + FT_Error FT_Done_FreeType( FT_Library library ); + + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Open_Face */ + /* */ + /* */ + /* Creates a new face object from a given resource and typeface */ + /* index. */ + /* */ + /* */ + /* resource :: A handle to a source resource. */ + /* */ + /* face_index :: The index of the face within the resource. The */ + /* first face has index 0. */ + /* */ + /* face :: A handle to a new face object. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + /* */ + /* Unlike FreeType 1.1, this function automatically creates a glyph */ + /* slot for the face object which can be accessed directly through */ + /* `face->slot'. */ + /* */ + /* Note that additional slots can be added to each face through 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. */ + /* */ + EXPORT_DEF + FT_Error FT_New_Face( FT_Library library, + const char* filepathname, + FT_Long face_index, + FT_Face* face ); + + + EXPORT_DEF + FT_Error FT_Open_Face( FT_Library library, + FT_Stream stream, + FT_Long face_index, + FT_Face* face ); + + EXPORT_DEF + FT_Error FT_New_Memory_Face( FT_Library library, + void* file_base, + FT_Long file_size, + FT_Long face_index, + FT_Face *face ); + + /*************************************************************************/ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + EXPORT_DEF + FT_Error FT_Done_Face( FT_Face face ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_New_Size */ + /* */ + /* */ + /* Creates a new size object from a given face object. */ + /* */ + /* */ + /* face :: A handle to a parent face object. */ + /* */ + /* */ + /* size :: A handle to a new size object. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + EXPORT_DEF + FT_Error FT_New_Size( FT_Face face, + FT_Size* size ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Done_Size */ + /* */ + /* */ + /* Discards a given size object. */ + /* */ + /* */ + /* size :: A handle to a target size object */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + EXPORT_DEF + FT_Error FT_Done_Size( FT_Size size ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_Char_Size */ + /* */ + /* */ + /* Sets the character dimensions of a given size object. The */ + /* `char_size' value is used for the width and height, expressed in */ + /* 26.6 fractional points. 1 point = 1/72 inch. */ + /* */ + /* */ + /* size :: A handle to a target size object. */ + /* char_size :: The character size, in 26.6 fractional points. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + /* */ + /* When dealing with fixed-size faces (i.e., non-scalable formats), */ + /* use the function FT_Set_Pixel_Sizes(). */ + /* */ + 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 size object. The width */ + /* and height are expressed in integer pixels. */ + /* */ + /* */ + /* size :: A handle to a target size object. */ + /* pixel_width :: The character width, in integer pixels. */ + /* pixel_height :: The character height, in integer pixels. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + EXPORT_DEF + FT_Error FT_Set_Pixel_Sizes( FT_Face face, + FT_UInt pixel_width, + FT_UInt pixel_height ); + + + /*************************************************************************/ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* slot :: A handle to a new glyph slot object. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + EXPORT_DEF + FT_Error FT_New_GlyphSlot( FT_Face face, + FT_GlyphSlot* aslot ); + + + /*************************************************************************/ + /* */ + /* */ + /* 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. */ + /* */ + EXPORT_DEF + void FT_Done_GlyphSlot( 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. */ + /* */ + 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.. */ + /* */ + 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 when FT_LOAD_NO_SCALE is set. */ + /* */ +#define FT_LOAD_NO_HINTING 2 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_NO_OUTLINE */ + /* */ + /* */ + /* A bit-field constant, used with FT_Load_Glyph() to indicate that */ + /* the function should not load the vector outline of a given glyph. */ + /* If an embedded bitmap exists for the glyph in the font, it will be */ + /* loaded, otherwise nothing is returned and an error is produced. */ + /* */ +#define FT_LOAD_NO_OUTLINE 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. If an outline exists for the glyph in the font, it is */ + /* loaded, otherwise nothing is returned and an error is produced. */ + /* */ +#define FT_LOAD_NO_BITMAP 8 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_LINEAR */ + /* */ + /* */ + /* A bit-field constant, used with FT_Load_Glyph() to indicate that */ + /* the function should return the linearly scaled metrics for the */ + /* glyph in `slot->metrics2' (these metrics are not grid-fitted). */ + /* Otherwise, `metrics2' gives the original font units values. */ + /* */ +#define FT_LOAD_LINEAR 16 + + + /*************************************************************************/ + /* */ + /* */ + /* 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_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. */ + /* */ + /* XXXXX : IMPORTANT NOTE, THIS FLAG IS NOT YET IMPLEMENTED !! */ + /* */ +#define FT_LOAD_NO_RECURSE 256 + + + /*************************************************************************/ + /* */ + /* */ + /* 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_Get_Glyph_Bitmap */ + /* */ + /* */ + /* Renders a given glyph into a bitmap or pixmap. This function will */ + /* use the registered rasters to render the glyph image. */ + /* */ + /* */ + /* face :: handle to the face object whose glyph slot contains */ + /* the glyph image */ + /* 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 a */ + /* glyph image into it! */ + /* */ + EXPORT_DEF + FT_Error FT_Get_Glyph_Bitmap( FT_Face face, + FT_Bitmap* map ); + + + /*************************************************************************/ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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. */ + /* */ + EXPORT_DEF + FT_Error FT_Get_Kerning( FT_Face face, + FT_UInt left_glyph, + FT_UInt right_glyph, + FT_Vector* kerning ); + + + +/* XXX : Not implemented yet, but should come soon */ +#if 0 + EXPORT_DEF + FT_Error FT_Select_Charmap( FT_Face face, + FT_Encoding encoding ); + + + EXPORT_DEF + FT_Error FT_Set_Charmap( FT_Face face, + FT_CharMap charmap ); +#endif + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Char_Index */ + /* */ + /* */ + /* Returns the glyph index of a given character code. This function */ + /* uses a charmap object to do the translation. */ + /* */ + /* */ + /* charmap :: A handle to a filter charmap object. */ + /* charcode :: The character code. */ + /* */ + /* */ + /* The glyph index. 0 means `undefined character code'. */ + /* */ + 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 maximum 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'. */ + /* */ + 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 maximum 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.0 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. */ + /* */ + 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 maximum 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 optimisation for FT_DivFix() is simple : if (a << 16) fits */ + /* in 32 bits, then the division is computed directly. Otherwise, */ + /* we use a specialised version of the old FT_MulDiv64 */ + /* */ + EXPORT_DEF + FT_Long FT_DivFix( FT_Long a, + FT_Long b ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Decompose_Outline */ + /* */ + /* */ + /* 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. */ + /* */ + EXPORT_DEF + int FT_Decompose_Outline( FT_Outline* outline, + FT_Outline_Funcs* interface, + void* user ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_New_Outline */ + /* */ + /* */ + /* 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 maximum number of points within the outline. */ + /* */ + /* numContours :: The maximum 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. You can copy the source */ + /* code of this function, replacing allocations with `malloc()' if */ + /* you want to control where the objects go. */ + /* */ + EXPORT_DEF + FT_Error FT_New_Outline( FT_Library library, + FT_UInt numPoints, + FT_Int numContours, + FT_Outline* outline ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Done_Outline */ + /* */ + /* */ + /* Destroys an outline created with FT_New_Outline(). */ + /* */ + /* */ + /* 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_Alloc()/FT_Free(). You can copy the source code */ + /* of this function, replacing allocations with `malloc()' in your */ + /* application if you want something simpler. */ + /* */ + EXPORT_DEF + FT_Error FT_Done_Outline( FT_Library library, + FT_Outline* outline ); + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Outline_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. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Yes. */ + /* */ + EXPORT_DEF + FT_Error FT_Get_Outline_CBox( FT_Outline* outline, + FT_BBox* cbox ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Translate_Outline */ + /* */ + /* */ + /* 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. */ + /* */ + EXPORT_DEF + void FT_Translate_Outline( FT_Outline* outline, + FT_Pos xOffset, + FT_Pos yOffset ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_Raster */ + /* */ + /* */ + /* Register a given raster to the library. */ + /* */ + /* */ + /* library :: A handle to a target library object. */ + /* */ + /* interface :: pointer to the raster's interface */ + /* */ + /* raster :: if this field is nil, this function will allocate */ + /* a new objet. Otherwise, it will simply use the one */ + /* provided here. */ + /* */ + /* Error code. 0 means success. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + EXPORT_DEF + FT_Error FT_Set_Raster( FT_Library library, + FT_Raster_Interface* interface, + FT_Raster raster ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_Raster_Mode */ + /* */ + /* */ + /* Set a raster-specific mode. */ + /* */ + /* */ + /* library :: A handle to a target library object. */ + /* format :: the glyph format used to select the raster */ + /* mode :: the raster-specific mode descriptor */ + /* args :: the mode arguments */ + /* */ + /* Error code. 0 means success. */ + /* */ + EXPORT_DEF + FT_Error FT_Set_Raster_Mode( FT_Library library, + FT_Glyph_Tag format, + const char* mode, + const char* args ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* FREETYPE_H */ + + +/* END */ diff --git a/include/ftbbox.h b/include/ftbbox.h new file mode 100644 index 000000000..ea68615a2 --- /dev/null +++ b/include/ftbbox.h @@ -0,0 +1,73 @@ +/***************************************************************************/ +/* */ +/* ftbbox.h */ +/* */ +/* FreeType bbox computation (specification). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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_Get_Outline_BBox */ + /* */ + /* */ + /* 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. */ + /* */ + EXPORT_DEF + FT_Error FT_Get_Outline_BBox( FT_Outline* outline, + FT_BBox* bbox ); + + +#ifdef __cplusplus + } +#endif + +#endif /* FTBBOX_H */ + + +/* END */ diff --git a/include/fterrors.h b/include/fterrors.h new file mode 100644 index 000000000..6df9ae3c3 --- /dev/null +++ b/include/fterrors.h @@ -0,0 +1,82 @@ +/***************************************************************************/ +/* */ +/* fterrors.h */ +/* */ +/* FreeType error codes (specification). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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_Err_Ok 0x000 + +#define FT_Err_Cannot_Open_Resource 0x001 +#define FT_Err_Unknown_File_Format 0x002 +#define FT_Err_Invalid_File_Format 0x002 + +#define FT_Err_Invalid_Argument 0x003 +#define FT_Err_Invalid_Handle 0x004 +#define FT_Err_Invalid_Glyph_Index 0x00A +#define FT_Err_Invalid_Character_Code 0x00B + +#define FT_Err_Unimplemented_Feature 0x010 +#define FT_Err_Invalid_Glyph_Format 0x00D + +#define FT_Err_Invalid_Library_Handle 0x004 +#define FT_Err_Invalid_Driver_Handle 0x005 +#define FT_Err_Invalid_Face_Handle 0x006 +#define FT_Err_Invalid_Size_Handle 0x007 +#define FT_Err_Invalid_Slot_Handle 0x008 +#define FT_Err_Invalid_CharMap_Handle 0x009 +#define FT_Err_Invalid_Outline 0x00B +#define FT_Err_Invalid_Dimensions 0x00C + +#define FT_Err_Unavailable_Outline 0x011 +#define FT_Err_Unavailable_Bitmap 0x012 +#define FT_Err_Unavailable_Pixmap 0x013 +#define FT_Err_File_Is_Not_Collection 0x014 +#define FT_Err_Too_Many_Drivers 0x015 +#define FT_Err_Too_Many_Glyph_Formats 0x016 +#define FT_Err_Too_Many_Extensions 0x017 + +#define FT_Err_Out_Of_Memory 0x100 +#define FT_Err_Unlisted_Object 0x101 + +#define FT_Err_Invalid_Resource_Handle 0x200 +#define FT_Err_Invalid_Stream_Handle 0x201 +#define FT_Err_Cannot_Open_Stream 0x202 +#define FT_Err_Invalid_Stream_Seek 0x203 +#define FT_Err_Invalid_Stream_Skip 0x204 +#define FT_Err_Invalid_Stream_Read 0x205 +#define FT_Err_Invalid_Stream_Operation 0x206 +#define FT_Err_Invalid_Frame_Operation 0x207 +#define FT_Err_Nested_Frame_Access 0x208 +#define FT_Err_Invalid_Frame_Read 0x209 + +#define FT_Err_Too_Many_Points 0x300 +#define FT_Err_Too_Many_Contours 0x301 +#define FT_Err_Invalid_Composite 0x302 +#define FT_Err_Too_Many_Hints 0x303 +#define FT_Err_Too_Many_Edges 0x304 +#define FT_Err_Too_Many_Strokes 0x305 + +/* range 0x400 - 0x4FF is reserved for TrueType specific stuff */ + +/* range 0x500 - 0x5FF is reserved for TrueDoc specific stuff */ + +/* range 0x600 - 0x6FF is reserved for Type1 specific stuff */ + +#define FT_Err_Raster_Uninitialized 0xF00 +#define FT_Err_Raster_Corrupted 0xF01 +#define FT_Err_Raster_Overflow 0xF02 + + +/* END */ diff --git a/include/ftimage.h b/include/ftimage.h new file mode 100644 index 000000000..f18174bb4 --- /dev/null +++ b/include/ftimage.h @@ -0,0 +1,627 @@ +/***************************************************************************/ +/* */ +/* ftimage.h */ +/* */ +/* This file defines the glyph image formats recognized by FreeType, as */ +/* well as the default raster interface. */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 FTIMAGE_H +#define FTIMAGE_H + + /*************************************************************************/ + /* */ + /* */ + /* 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. + * + * + * 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 spec. + * + * 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; + void* 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. It's a copy of the TT_Outline type that was defined */ + /* in FreeType 1.x. */ + /* */ + /* */ + /* 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. */ + /* */ + /* flags :: A pointer to an array of `n_points' chars, */ + /* giving each outline point's type. If bit 0 is */ + /* set, 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. */ + /* */ + /* owner :: This flag is a boolean which is set whenever the */ + /* outline structure/object owns the arrays it */ + /* refers to in the fields `points', `flags', and */ + /* `contours'. */ + /* */ + /* high_precision :: This flag is set automatically by the FreeType */ + /* library. It indicates that the scan-line */ + /* converter should use a higher precision when */ + /* rendering the outline. This is useful at small */ + /* pixel sizes to get adequate results, though at */ + /* the price of slower rendering. Don't try to */ + /* render large outlines with this flag set. Note */ + /* that it may be ignored in later implementations. */ + /* */ + /* second_pass :: A boolean which is set when the scan-line */ + /* converter should perform a second pass to */ + /* eliminate vertical drop-outs (only vertical */ + /* drop-outs are checked on the first pass). This */ + /* field may be ignored by later implementations. */ + /* */ + /* dropout_mode :: Specifies the drop-out control mode to use while */ + /* rendering an outline. Valid values are 0 (no */ + /* drop out check), 1, 2, 4, and 5. See the */ + /* TrueType specification for more details. A */ + /* value of 2 is usually an excellent generic */ + /* choice. This field may be ignored by some */ + /* raster implementations. */ + /* */ + /* */ + 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* flags; /* the points flags */ + short* contours; /* the contour end points */ + + char owner; /* the outline owns the coordinates, */ + /* flags, and contours array it uses */ + + char high_precision; /* high precision rendering */ + char second_pass; /* two sweeps rendering */ + char dropout_mode; /* dropout mode */ + + } FT_Outline; + + +#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. */ + /* */ + 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; + + } FT_Outline_Funcs; + + + + + /*************************************************************************/ + /* */ + /* */ + /* FT_IMAGE_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_IMAGE_TAG( _x1, _x2, _x3, _x4 ) \ + (((unsigned long)_x1 << 24) | \ + ((unsigned long)_x2 << 16) | \ + ((unsigned long)_x3 << 8) | \ + (unsigned long)_x4) + + + /*********************************************************************** + * + * + * FT_Glyph_Tag + * + * + * An enumeration type used to describethe 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_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 + * + ***********************************************************************/ + + typedef enum FT_Glyph_Tag_ + { + 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_Tag; + + + /*************************************************************************/ + /* */ + /* */ + /* 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_Raster_Init_Proc */ + /* */ + /* */ + /* Initializes a fresh raster object which should have been allocated */ + /* by client applications. This function is also used to set the */ + /* object's render pool. It can be used repeatedly on a single */ + /* object if one wants to change the pool's address or size. */ + /* */ + /* Note that the render pool has no state and is only used during a */ + /* call to FT_Raster_Render(). It is thus theorically possible to */ + /* share it between several non-concurrent components of your */ + /* applications when memory is a scarce resource. */ + /* */ + /* */ + /* raster :: a handle to the target raster object. */ + /* pool_base :: the render pool's base address in memory */ + /* pool_size :: the render pool's size in bytes. this must be at */ + /* least 4 kByte. */ + /* */ + /* An error condition, used as a FT_Error in the FreeType library. */ + /* 0 means success. */ + /* */ + typedef int (*FT_Raster_Init_Proc)( FT_Raster raster, + const char* pool_base, + long pool_size ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster_Set_Mode_Proc */ + /* */ + /* */ + /* Some raster implementations may have several modes of operation. */ + /* This function is used to select one of them, as well as pass some */ + /* arguments. */ + /* */ + /* */ + /* raster :: The target raster object. */ + /* */ + /* mode :: A pointer used to describe the mode to set. This is */ + /* completely raster-specific, and could be, for example, */ + /* a text string. */ + /* */ + /* args :: An argument to the set_mode command. This is completely */ + /* specific to the raster and the mode used. */ + /* */ + /* */ + /* An error code, used as a FT_Error by the FreeType library. */ + /* 0 means success. */ + /* */ + typedef int (*FT_Raster_Set_Mode_Proc)( FT_Raster raster, + const char* mode, + const char* args ); + + + /************************************************************************* + * + * + * FT_Raster_Render_Proc + * + * + * Renders an outline into a target bitmap/pixmap. + * + * + * raster :: A handle to a raster object used during rendering. + * + * source_image :: a typeless pointer to the source glyph image. + * (usually a FT_Outline*). + * + * target_bitmap :: descriptor to the target bitmap. + * + * + * Error code, interpreted as a FT_Error by FreeType library. + * 0 means success. + * + *************************************************************************/ + + typedef int (*FT_Raster_Render_Proc)( FT_Raster raster, + void* source_image, + FT_Bitmap* target_bitmap ); + + + /************************************************************************** + * + * + * FT_Raster_Interface + * + * + * A structure used to model the default raster interface. A raster + * is a module in charge of converting a glyph image into a bitmap. + * + * + * size :: the size in bytes of the given raster object. This + * is used to allocate a new raster when calling + * `FT_Set_Raster'. + * + * format :: the source glyph image format this raster is able to + * handle. + * + * init :: the raster's initialisation routine + * + * set_mode :: the raster's mode set routine + * + * render :: the raster's rendering routine + * + **************************************************************************/ + + typedef struct FT_Raster_Interface_ + { + long size; + FT_Glyph_Tag format_tag; + FT_Raster_Init_Proc init; + FT_Raster_Set_Mode_Proc set_mode; + FT_Raster_Render_Proc render; + + + } FT_Raster_Interface; + + +#endif /* FTIMAGE_H */ + + diff --git a/include/ftsystem.h b/include/ftsystem.h new file mode 100644 index 000000000..5f42e17de --- /dev/null +++ b/include/ftsystem.h @@ -0,0 +1,95 @@ +/************************************************************************** + * + * ftsystem.h 1.0 + * + * FreeType low-level system interface definition + * + * This file contains the definitions of the stream and memory interfaces + * used by FreeType. + * + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.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, + char* buffer, + unsigned long count ); + + typedef void (*FT_Stream_Close)( FT_Stream stream ); + + struct FT_StreamRec_ + { + 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; + char* cursor; + char* limit; + }; + + +#endif /* FTSYSTEM_H */ diff --git a/include/ttnamedid.h b/include/ttnamedid.h new file mode 100644 index 000000000..df7fcb75d --- /dev/null +++ b/include/ttnamedid.h @@ -0,0 +1,624 @@ +/******************************************************************* + * + * ttnameid.h + * + * TrueType Name ID definitions + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.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 +#define TT_PLATFORM_MICROSOFT 3 + + +/* + * possible values of the platform specific encoding identifier field in + * the name records of the TTF "name" table when the 'Platform' identifier + * code is TT_PLATFORM_APPLE_UNICODE + */ + +#define TT_APPLE_ID_DEFAULT 0 +#define TT_APPLE_ID_UNICODE_1_1 1 +#define TT_APPLE_ID_ISO_10646 2 +#define TT_APPLE_ID_UNICODE_2_0 3 + + +/* + * possible values of the platform specific encoding identifier field in + * the name records of the TTF "name" table when 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 when the 'Platform' identifier + * code is TT_PLATFORM_ISO + */ + +#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 when 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 when 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_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_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 +#define TT_MAC_LANGID_SCOTTISH_GAELIC 140 +#define TT_MAC_LANGID_IRISH_GAELIC 141 +#define TT_MAC_LANGID_BRETON 142 +#define TT_MAC_LANGID_INUKTITUT 143 + + +/* + * possible values of the language identifier field in the name records of + * the TTF "name" table when 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 + + +/* + * Bit Mask values for the Unicode Ranges from the TTF "OS2 " table. + */ + +/* General Scripts Area */ + +/* Bit 0 C0 Controls and Basic Latin */ +#define TT_UCR_BASIC_LATIN (1L << 0) /* U+0000-U+007F */ +/* Bit 1 C1 Controls and Latin-1 Supplement */ +#define TT_UCR_LATIN1_SUPPLEMENT (1L << 1) /* U+0080-U+00FF */ +/* Bit 2 Latin Extended-A */ +#define TT_UCR_LATIN_EXTENDED_A (1L << 2) /* U+0100-U+017F */ +/* Bit 3 Latin Extended-B */ +#define TT_UCR_LATIN_EXTENDED_B (1L << 3) /* U+0180-U+024F */ +/* Bit 4 IPA Extensions */ +#define TT_UCR_IPA_EXTENSIONS (1L << 4) /* U+0250-U+02AF */ +/* Bit 5 Spacing Modifier Letters */ +#define TT_UCR_SPACING_MODIFIER (1L << 5) /* U+02B0-U+02FF */ +/* Bit 6 Combining Diacritical Marks */ +#define TT_UCR_COMBINING_DIACRITICS (1L << 6) /* U+0300-U+036F */ +/* Bit 7 Greek */ +#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 */ +#define TT_UCR_BOPOMOFO (1L << 19) /* U+3100-U+312F */ +/* 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 */ +#define TT_UCR_CJK_UNIFIED_IDEOGRAPHS (1L << 27) /* U+4E00-U+9FFF */ + +/* 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+FSFF */ +/* 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+FEFF */ +/* 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+FEFF, + U+FFF0-U+FFFF */ +/* Bit 70 Tibetan */ +#define TT_UCR_TIBETAN (1L << 6) /* U+0F00-U+0FBF */ + + +/* 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 /* ndef HAVE_LIMIT_ON_IDENTS */ + +#endif /* TTNAMEID_H */ + + +/* END */ diff --git a/obj/README b/obj/README new file mode 100644 index 000000000..91fdcbdc1 --- /dev/null +++ b/obj/README @@ -0,0 +1 @@ +This directory contains all the object files created when building the library diff --git a/src/base/ftbase.c b/src/base/ftbase.c new file mode 100644 index 000000000..0a00e62cb --- /dev/null +++ b/src/base/ftbase.c @@ -0,0 +1,6 @@ +#include +#include +#include +#include + +#include diff --git a/src/base/ftbbox.c b/src/base/ftbbox.c new file mode 100644 index 000000000..71d443069 --- /dev/null +++ b/src/base/ftbbox.c @@ -0,0 +1,447 @@ +/***************************************************************************/ +/* */ +/* ftbbox.c */ +/* */ +/* FreeType bbox computation (body). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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. */ + /* */ + /*************************************************************************/ + + +#include +#include +#include + + typedef struct TBBox_Rec_ + { + FT_Vector last; + FT_BBox bbox; + + } TBBox_Rec; + + + /*************************************************************************/ + /* */ + /* */ + /* BBox_Move_To */ + /* */ + /* */ + /* This function is used as a `move_to' and `line_to' emitter during */ + /* FT_Raster_Decompose(). It simply records the destination point in */ + /* user->last. */ + /* */ + /* */ + /* to :: The destination vector. */ + /* user :: The current walk context. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + static + int BBox_Move_To( FT_Vector* to, + TBBox_Rec* user ) + { + user->last = *to; + + return 0; + } + + +#define CHECK_X( p, bbox ) \ + ( p->x < bbox.xMin || p->x > bbox.xMax ) + +#define CHECK_Y( p, bbox ) \ + ( p->y < bbox.yMin || p->y > bbox.yMax ) + + + /*************************************************************************/ + /* */ + /* */ + /* BBox_Conic_Check */ + /* */ + /* */ + /* Finds the extrema of a 1-dimensional conic Bezier curve and update */ + /* a bounding range. This version uses direct computation, as it */ + /* doesn't need square roots. */ + /* */ + /* */ + /* y1 :: The start coordinate. */ + /* y2 :: The coordinate of the control point. */ + /* y3 :: The end coordinate. */ + /* */ + /* */ + /* min :: The address of the current minimum. */ + /* max :: The address of the current maximum. */ + /* */ + static + void BBox_Conic_Check( FT_Pos y1, + FT_Pos y2, + FT_Pos y3, + FT_Pos* min, + FT_Pos* max ) + { + if( y1 == y3 ) + { + if ( y2 == y1 ) /* Flat arc */ + { + y3 = y1; + goto Suite; + } + } + else if ( y1 < y3 ) + { + if ( y2 >= y1 && y2 <= y3 ) /* Ascending arc */ + goto Suite; + } + else + { + if ( y2 >= y3 && y2 <= y1 ) /* Descending arc */ + { + y2 = y1; + y1 = y3; + y3 = y2; + goto Suite; + } + } + + y1 = y3 = FT_MulDiv( y2 - y1, y2 - y1, y1 - 2*y2 + y3 ); + + Suite: + if ( y1 < *min ) *min = y1; + if ( y3 > *max ) *max = y3; + } + + + /*************************************************************************/ + /* */ + /* */ + /* BBox_Conic_To */ + /* */ + /* */ + /* This function is used as a `conic_to' emitter during */ + /* FT_Raster_Decompose(). It checks a conic Bezier curve with the */ + /* current bounding box, and computes its extrema if necessary to */ + /* update it. */ + /* */ + /* */ + /* control :: A control point. */ + /* to :: The destination vector. */ + /* */ + /* */ + /* user :: The current walk context. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + /* */ + /* In the case of a non-monotonous arc, we compute directly the */ + /* extremum coordinates, as it is sufficiently fast. */ + /* */ + static + int BBox_Conic_To( FT_Vector* control, + FT_Vector* to, + TBBox_Rec* user ) + { + if ( CHECK_X( control, user->bbox ) || + CHECK_X( to, user->bbox ) ) + + BBox_Conic_Check( user->last.x, + control->x, + to->x, + &user->bbox.xMin, + &user->bbox.xMax ); + + if ( CHECK_Y( control, user->bbox ) || + CHECK_Y( to, user->bbox ) ) + + BBox_Conic_Check( user->last.y, + control->y, + to->y, + &user->bbox.yMin, + &user->bbox.yMax ); + + return 0; + } + + + /*************************************************************************/ + /* */ + /* */ + /* BBox_Cubic_Check */ + /* */ + /* */ + /* Finds the extrema of a 1-dimensional cubic Bezier curve and */ + /* updates a bounding range. This version uses splitting because we */ + /* don't want to use square roots and extra accuracies. */ + /* */ + /* */ + /* p1 :: The start coordinate. */ + /* p2 :: The coordinate of the first control point. */ + /* p3 :: The coordinate of the second control point. */ + /* p4 :: The end coordinate. */ + /* */ + /* */ + /* min :: The address of the current minimum. */ + /* max :: The address of the current maximum. */ + /* */ + static + void BBox_Cubic_Check( FT_Pos p1, + FT_Pos p2, + FT_Pos p3, + FT_Pos p4, + FT_Pos* min, + FT_Pos* max ) + { + FT_Pos stack[33], *arc; + + + arc = stack; + + arc[0] = p1; + arc[1] = p2; + arc[2] = p3; + arc[3] = p4; + + do + { + FT_Pos y1 = arc[0]; + FT_Pos y2 = arc[1]; + FT_Pos y3 = arc[2]; + FT_Pos y4 = arc[3]; + + + if ( y1 == y4 ) + { + if ( y1 == y2 && y1 == y3 ) /* Flat */ + { + y4 = y1; + goto Test; + } + } + else if ( y1 < y4 ) + { + if ( y2 >= y1 && y2 <= y4 && y3 >= y1 && y3 <= y4 ) /* Ascending */ + goto Test; + } + else + { + if ( y2 >= y4 && y2 <= y1 && y3 >= y4 && y3 <= y1 ) /* Descending */ + { + y2 = y1; + y1 = y4; + y4 = y2; + goto Test; + } + } + + /* Unknown direction, split the arc in two */ + arc[6] = y4; + arc[1] = y1 = ( y1 + y2 ) / 2; + arc[5] = y4 = ( y4 + y3 ) / 2; + y2 = ( y2 + y3 ) / 2; + arc[2] = y1 = ( y1 + y2 ) / 2; + arc[4] = y4 = ( y4 + y2 ) / 2; + arc[3] = ( y1 + y4 ) / 2; + + arc += 3; + goto Suite; + + Test: + if ( y1 < *min ) *min = y1; + if ( y4 > *max ) *max = y4; + arc -= 3; + + Suite: + ; + } while (arc >= stack); + } + + + /*************************************************************************/ + /* */ + /* */ + /* BBox_Cubic_To */ + /* */ + /* */ + /* This function is used as a `cubic_to' emitter during */ + /* FT_Raster_Decompose(). It checks a cubic Bezier curve with the */ + /* current bounding box, and computes its extrema if necessary to */ + /* update it. */ + /* */ + /* */ + /* control1 :: The first control point. */ + /* control2 :: The second control point. */ + /* to :: The destination vector. */ + /* */ + /* */ + /* user :: The current walk context. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + /* */ + /* In the case of a non-monotonous arc, we don't compute directly */ + /* extremum coordinates, we subdivise instead. */ + /* */ + static + int BBox_Cubic_To( FT_Vector* control1, + FT_Vector* control2, + FT_Vector* to, + TBBox_Rec* user ) + { + if ( CHECK_X( control1, user->bbox ) || + CHECK_X( control2, user->bbox ) || + CHECK_X( to, user->bbox ) ) + + BBox_Cubic_Check( user->last.x, + control1->x, + control2->x, + to->x, + &user->bbox.xMin, + &user->bbox.xMax ); + + if ( CHECK_Y( control1, user->bbox ) || + CHECK_Y( control2, user->bbox ) || + CHECK_Y( to, user->bbox ) ) + + BBox_Cubic_Check( user->last.y, + control1->y, + control2->y, + to->y, + &user->bbox.yMin, + &user->bbox.yMax ); + + return 0; + } + + + /*************************************************************************/ + /* */ + /* */ + /* 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. */ + /* */ + EXPORT_FUNC + FT_Error FT_Raster_GetBBox( FT_Outline* outline, + FT_BBox* abbox ) + { + FT_BBox cbox; + FT_BBox bbox; + FT_Vector* vec; + FT_UShort n; + + + /* if outline is empty, return (0,0,0,0) */ + if ( !outline ) + return FT_Err_Invalid_Outline; + + if ( outline->n_points == 0 || outline->n_contours <= 0 ) + { + abbox->xMin = abbox->xMax = 0; + abbox->yMin = abbox->yMax = 0; + return 0; + } + + /* We compute the control box, as well as the bounding box */ + /* of all `on' points in the outline. Then, if the two boxes */ + /* coincide, we exit immediately. */ + + vec = outline->points; + bbox.xMin = bbox.xMax = cbox.xMin = cbox.xMax = vec->x; + bbox.yMin = bbox.yMin = cbox.yMin = cbox.yMax = vec->y; + + for ( n = 1; n < outline->n_points; n++ ) + { + FT_Pos x = vec->x; + FT_Pos y = vec->y; + + + /* update control box */ + if ( x < cbox.xMin ) cbox.xMin = x; + if ( x > cbox.xMax ) cbox.xMax = x; + + if ( y < cbox.yMin ) cbox.yMin = y; + if ( y > cbox.yMax ) cbox.yMax = y; + + if ( FT_CURVE_TAG( outline->flags[n] ) == FT_Curve_Tag_On ) + { + /* update bbox for `on' points only */ + if ( x < bbox.xMin ) bbox.xMin = x; + if ( x > bbox.xMax ) bbox.xMax = x; + + if ( y < bbox.yMin ) bbox.yMin = y; + if ( y > bbox.yMax ) bbox.yMax = y; + } + + vec++; + } + + /* test two boxes for equality */ + if ( cbox.xMin < bbox.xMin || cbox.xMax > bbox.xMax || + cbox.yMin < bbox.yMin || cbox.yMax > bbox.yMax ) + { + /* the two boxes are different, now walk over the outline to */ + /* get the Bezier arc extrema. */ + + static FT_Outline_Funcs interface = + { + (FT_Outline_MoveTo_Func) BBox_Move_To, + (FT_Outline_LineTo_Func) BBox_Move_To, + (FT_Outline_ConicTo_Func) BBox_Conic_To, + (FT_Outline_CubicTo_Func) BBox_Cubic_To + }; + + FT_Error error; + TBBox_Rec user; + + + user.bbox = bbox; + + error = FT_Decompose_Outline( outline, &interface, &user ); + if ( error ) + return error; + + *abbox = user.bbox; + } + else + *abbox = bbox; + + return FT_Err_Ok; + } + + +/* END */ diff --git a/src/base/ftcalc.c b/src/base/ftcalc.c new file mode 100644 index 000000000..9acc58eef --- /dev/null +++ b/src/base/ftcalc.c @@ -0,0 +1,505 @@ +/***************************************************************************/ +/* */ +/* ftcalc.c */ +/* */ +/* Arithmetic computations (body). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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() and FT_MulFix() are declared in freetype.h. */ + /* */ + /*************************************************************************/ + +#include +#include +#include /* for ABS() */ + + + BASE_FUNC + FT_Int32 FT_Sqrt32( FT_Int32 x ) + { + FT_ULong val, root, newroot, mask; + + root = 0; + mask = 0x40000000; + 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; + } + + +#ifdef LONG64 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_MulDiv */ + /* */ + /* */ + /* A very simple function used to perform the computation `(A*B)/C' */ + /* with maximum 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'. */ + /* */ + 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*( ((FT_Int64)a * b + (c >> 1) )/c); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_MulFix */ + /* */ + /* */ + /* A very simple function used to perform the computation */ + /* `(A*B)/0x10000' with maximum 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.0 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. */ + /* */ + 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 maximum 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 optimisation for FT_DivFix() is simple : if (a << 16) fits */ + /* in 32 bits, then the division is computed directly. Otherwise, */ + /* we use a specialised version of the old FT_MulDiv64 */ + /* */ + EXPORT_FUNC + FT_Int32 FT_DivFix( FT_Long a, + FT_Long b ) + { + FT_Int32 s; + FT_Word32 q; + + s = a; a = ABS(a); + s ^= b; b = ABS(b); + + if ( b == 0 ) + /* check for divide by 0 */ + q = 0x7FFFFFFF; + + else + /* compute result directly */ + q = ((FT_Int64)a << 16) / b; + + return (FT_Int32)( s < 0 ? -q : q ); + } + + +#else /* LONG64 */ + + + /*************************************************************************/ + /* */ + /* */ + /* FT_MulDiv */ + /* */ + /* */ + /* A very simple function used to perform the computation `(A*B)/C' */ + /* with maximum 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 */ + /* */ + 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 ) + { + a = ( a*b + (c >> 1) ) / c; + } + else + { + FT_Int64 temp, temp2; + + FT_MulTo64( a, b, &temp ); + temp2.hi = (FT_Int32)(c >> 31); + temp2.lo = (FT_Word32)(c / 2); + FT_Add64( &temp, &temp2, &temp ); + a = FT_Div64by32( &temp, c ); + } + + return ( s < 0 ) ? -a : a; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_MulFix */ + /* */ + /* */ + /* A very simple function used to perform the computation */ + /* `(A*B)/0x10000' with maximum 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 optimisation 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. */ + /* */ + EXPORT_FUNC + FT_Long FT_MulFix( FT_Long a, + FT_Long b ) + { + FT_Long s; + + if ( a == 0 || b == 0x10000L ) + return a; + + s = a; a = ABS(a); + s ^= b; b = ABS(b); + + if ( a <= 2048 && b <= 1048576L ) + { + a = ( a*b + 0x8000 ) >> 16; + } + else + { + FT_Long al = a & 0xFFFF; + + a = (a >> 16)*b + al*(b >> 16) + ( al*(b & 0xFFFF) >> 16 ); + } + + return ( s < 0 ? -a : a ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_DivFix */ + /* */ + /* */ + /* A very simple function used to perform the computation */ + /* `(A*0x10000)/B' with maximum 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 optimisation for FT_DivFix() is simple : if (a << 16) fits */ + /* in 32 bits, then the division is computed directly. Otherwise, */ + /* we use a specialised version of the old FT_MulDiv64 */ + /* */ + EXPORT_FUNC + FT_Long FT_DivFix( FT_Long a, + FT_Long b ) + { + FT_Int32 s; + FT_Word32 q; + + s = a; a = ABS(a); + s ^= b; b = ABS(b); + + if ( b == 0 ) + /* check for divide by 0 */ + q = 0x7FFFFFFF; + + else if ( (a >> 16) == 0 ) + { + /* compute result directly */ + q = (FT_Word32)(a << 16) / (FT_Word32)b; + } + else + { + /* we need more bits, we'll have to do it by hand */ + FT_Word32 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 ); + } + + + BASE_FUNC + void FT_Add64( FT_Int64* x, + FT_Int64* y, + FT_Int64* z ) + { + register FT_Word32 lo, hi; + + lo = x->lo + y->lo; + hi = x->hi + y->hi + ( lo < x->lo ); + + z->lo = lo; + z->hi = hi; + } + + + BASE_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_Word32 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_Word32)-(FT_Int32)z->lo; + z->hi = ~z->hi + !(z->lo); + } + } + + + BASE_FUNC + FT_Int32 FT_Div64by32( FT_Int64* x, + FT_Int32 y ) + { + FT_Int32 s; + FT_Word32 q, r, i, lo; + + + s = x->hi; + if ( s < 0 ) + { + x->lo = (FT_Word32)-(FT_Int32)x->lo; + x->hi = ~x->hi + !(x->lo); + } + s ^= y; y = ABS( y ); + + /* Shortcut */ + if ( x->hi == 0 ) + { + q = x->lo / y; + return ( s < 0 ) ? -(FT_Int32)q : (FT_Int32)q; + } + + r = x->hi; + lo = x->lo; + + if ( r >= (FT_Word32)y ) /* we know y is to be treated as unsigned here */ + return ( s < 0 ) ? 0x80000001L : 0x7FFFFFFFL; + /* Return Max/Min Int32 if divide overflow. */ + /* This includes division by zero! */ + q = 0; + for ( i = 0; i < 32; i++ ) + { + r <<= 1; + q <<= 1; + r |= lo >> 31; + + if ( r >= (FT_Word32)y ) + { + r -= y; + q |= 1; + } + lo <<= 1; + } + + return ( s < 0 ) ? -(FT_Int32)q : (FT_Int32)q; + } + + +#endif /* LONG64 */ + + +/* END */ diff --git a/src/base/ftcalc.h b/src/base/ftcalc.h new file mode 100644 index 000000000..1bbe178f0 --- /dev/null +++ b/src/base/ftcalc.h @@ -0,0 +1,85 @@ +/***************************************************************************/ +/* */ +/* ftcalc.h */ +/* */ +/* Arithmetic computations (specification). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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) ) + +#else /* LONG64 */ + + typedef struct FT_Int64_ + { + FT_Word32 lo; + FT_Word32 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 ) + + BASE_DEF void FT_Add64 ( FT_Int64* x, FT_Int64* y, FT_Int64* z ); + BASE_DEF void FT_MulTo64 ( FT_Int32 x, FT_Int32 y, FT_Int64* z ); + BASE_DEF FT_Int32 FT_Div64by32( FT_Int64* x, FT_Int32 y ); + +#endif /* LONG64 */ + +#define SQRT_32( x ) FT_Sqrt32( x ) + + BASE_DEF FT_Int32 FT_Sqrt32( FT_Int32 l ); + + /*************************************************************************/ + /* */ + /* 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/src/base/ftdebug.c b/src/base/ftdebug.c new file mode 100644 index 000000000..168f9b767 --- /dev/null +++ b/src/base/ftdebug.c @@ -0,0 +1,93 @@ +/***************************************************************************/ +/* */ +/* ftdebug.c */ +/* */ +/* Debugging and logging component (body). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 + +#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 + + + /*************************************************************************/ + /* */ + /* The Print() function is defined in ftconfig.h. It defaults to */ + /* vprintf() on systems which have it. */ + /* */ + /*************************************************************************/ + + + void FT_Message( const char* fmt, ... ) + { + va_list ap; + + + va_start( ap, fmt ); + vprintf( fmt, ap ); + va_end( ap ); + } + + + void FT_Panic( const char* fmt, ... ) + { + va_list ap; + + + va_start( ap, fmt ); + vprintf( fmt, ap ); + va_end( ap ); + + exit( EXIT_FAILURE ); + } + + +#ifdef FT_DEBUG_LEVEL_TRACE + + EXPORT_FUNC + void FT_SetTraceLevel( FT_Trace component, + char level ) + { + if ( component >= trace_max ) + return; + + /* if component is `trace_any', then 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/src/base/ftdebug.h b/src/base/ftdebug.h new file mode 100644 index 000000000..c619f3529 --- /dev/null +++ b/src/base/ftdebug.h @@ -0,0 +1,191 @@ +/***************************************************************************/ +/* */ +/* ftdebug.h */ +/* */ +/* Debugging and logging component (specification). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 nor generated. The code is free from any */ + /* debugging parts. */ + /* */ + /*************************************************************************/ + + +#ifndef FTDEBUG_H +#define FTDEBUG_H + +#include /* for FT_DEBUG_LEVEL_TRACE, FT_DEBUG_LEVEL_ERROR */ + + +#ifdef __cplusplus + extern "C" { +#endif + + +#ifdef FT_DEBUG_LEVEL_TRACE + + + typedef enum FT_Trace_ + { + trace_any = 0, + + /* first, define an enum for each common component */ + trace_io, /* in ftsys */ + trace_memory, /* in ftsys */ + trace_sync, /* in ftsys */ + trace_stream, /* stream manager - see ftstream.c */ + trace_calc, /* computations - see ftcalc.c */ + trace_raster, /* raster - see ftraster.c */ + trace_list, /* list manager - see ftlist.c */ + trace_objs, /* base objects - see ftobjs.c */ + + /* then define an enum for each TrueType driver component */ + trace_ttobjs, + trace_ttload, + trace_ttgload, + trace_ttinterp, + trace_ttcmap, + trace_ttextend, + trace_ttdriver, + + /* define an enum for each TrueDoc driver component */ + trace_tdobjs, + trace_tdload, + trace_tdgload, + trace_tdhint, + trace_tddriver, + + /* define an enum for each Type1 driver component */ + trace_t1objs, + trace_t1load, + trace_t1gload, + trace_t1hint, + trace_t1driver, + + /* other trace levels */ + trace_init, + + /* the last level must always be `trace_max' */ + trace_max + + } FT_Trace; + + extern char ft_trace_levels[trace_max]; + + + /*************************************************************************/ + /* */ + /* IMPORTANT! */ + /* */ + /* Each component must define the macro FT_COMPONENT to a valid */ + /* Trace_Component value before using any TRACE macro. */ + /* */ + /*************************************************************************/ + + +#define FT_TRACE( level, varformat ) \ + if ( ft_trace_levels[FT_COMPONENT] >= level ) \ + FT_Message##varformat + + + EXPORT_DEF + void FT_SetTraceLevel( FT_Trace component, + char level ); + + +#elif defined( FT_DEBUG_LEVEL_ERROR ) + + +#define FT_TRACE( level, varformat ) /* nothing */ + + +#else /* release mode */ + + +#define FT_Assert( condition ) /* nothing */ + +#define FT_TRACE( level, varformat ) /* nothing */ +#define FT_ERROR( varformat ) /* 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 ttdebug.c. */ + /* */ + /*************************************************************************/ + +#if defined( FT_DEBUG_LEVEL_TRACE ) || defined( FT_DEBUG_LEVEL_ERROR ) + + +#include "stdio.h" /* for vprintf() */ + +#define FT_Assert( condition ) \ + if ( !(condition) ) \ + FT_Panic( "assertion failed on line %d of file %s\n", __LINE__, __FILE__ ); + + extern void FT_Message( const char* fmt, ... ); + + /* print a message and exit */ + extern void FT_Panic ( const char* fmt, ... ); + +#define FT_ERROR( varformat ) FT_Message##varformat + + +#endif /* FT_DEBUG_LEVEL_TRACE || FT_DEBUG_LEVEL_ERROR */ + + +#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/src/base/ftdriver.h b/src/base/ftdriver.h new file mode 100644 index 000000000..04cf74809 --- /dev/null +++ b/src/base/ftdriver.h @@ -0,0 +1,641 @@ +/***************************************************************************/ +/* */ +/* ftdriver.h */ +/* */ +/* FreeType driver interface (specification). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** D R I V E R S ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* FTDriver_initDriver */ + /* */ + /* */ + /* A driver method used to create a new driver object for a given */ + /* format. */ + /* */ + /* */ + /* driver :: A handle to the `new' driver object. The fields */ + /* `library', `system', and `lock' are already set when the */ + /* base layer calls this method. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + typedef FT_Error (*FTDriver_initDriver)( FT_Driver driver ); + + + /*************************************************************************/ + /* */ + /* */ + /* FTDriver_doneEngine */ + /* */ + /* */ + /* A driver method used to finalize a given driver object. Note that */ + /* all faces and resources for this driver have been released before */ + /* this call, and that this function should NOT destroy the driver */ + /* object. */ + /* */ + /* */ + /* driver :: A handle to target driver object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + typedef FT_Error (*FTDriver_doneDriver)( FT_Driver driver ); + + + + /*************************************************************************/ + /* */ + /* */ + /* FTDriver_getInterface */ + /* */ + /* */ + /* 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 when the requested extension */ + /* isn't available (i.e., wasn't compiled in the driver at build */ + /* time). */ + /* */ + typedef void* (*FTDriver_getInterface)( FT_Driver driver, + const FT_String* interface ); + + + /*************************************************************************/ + /* */ + /* */ + /* FTDriver_formatInterface */ + /* */ + /* */ + /* A driver interface field whose value is a driver-specific */ + /* interface method tables. This table contains entry points to */ + /* various functions that are strictly related to the driver's */ + /* format. */ + /* */ + typedef void* FT_FormatInterface; + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** F A C E S ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* FTDriver_initFace */ + /* */ + /* */ + /* A driver method used to initialize a new face object. The object */ + /* must be created by the caller. */ + /* */ + /* */ + /* driver :: A handle to the source driver object. */ + /* resource :: A handle to the source resource. */ + /* typeface_index :: The index of face in the font resource. Used to */ + /* access individual faces in collections. */ + /* */ + /* face :: A handle to the new target face. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The `typeface_index' parameter field will be set to -1 when the */ + /* engine only wants to test the format of the resource. This means */ + /* that font drivers should simply check the font format, then return */ + /* immediately with an error code of 0 (meaning success). The field */ + /* `num_faces' should be set. */ + /* */ + /* done_face() will be called subsequently, whatever the result was. */ + /* */ + typedef FT_Error (*FTDriver_initFace)( FT_Stream stream, + FT_Long typeface_index, + FT_Face face ); + + + /*************************************************************************/ + /* */ + /* */ + /* FTDriver_doneFace */ + /* */ + /* */ + /* A driver method used to finalize a given face object. This */ + /* function does NOT destroy the object, that is the responsibility */ + /* of the caller. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + typedef void (*FTDriver_doneFace)( FT_Face face ); + + + /*************************************************************************/ + /* */ + /* */ + /* FTDriver_getKerning */ + /* */ + /* */ + /* 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 method. Other layouts, or more sophisticated */ + /* kernings are out of the scope of this method (the basic driver */ + /* interface is meant to be simple). */ + /* */ + /* They can be implemented through format-specific interfaces. */ + /* */ + typedef FT_Error (*FTDriver_getKerning)( FT_Face face, + FT_UInt left_glyph, + FT_UInt right_glyph, + FT_Vector* kerning ); + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** S I Z E S ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* FTDriver_initSize */ + /* */ + /* */ + /* A driver method used to initialize a new size object. The object */ + /* must be created by the caller. */ + /* */ + /* */ + /* face :: A handle to the parent face object. */ + /* size :: A handle to the new size object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* This function should return an error if the face's format isn't */ + /* scalable. */ + /* */ + typedef FT_Error (*FTDriver_initSize)( FT_Size size ); + + + /*************************************************************************/ + /* */ + /* */ + /* FTDriver_setCharSizes */ + /* */ + /* */ + /* A driver method used to reset a size's character sizes (horizontal */ + /* and vertical) expressed in fractional points. */ + /* */ + /* */ + /* size :: A handle to the target size object. */ + /* char_width :: The character width expressed in 26.6 fractional */ + /* points. */ + /* char_height :: The character height expressed in 26.6 fractional */ + /* points. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* This function should always FAIL if the face format isn't */ + /* scalable! */ + /* */ + typedef FT_Error (*FTDriver_setCharSizes)( FT_Size size, + FT_F26Dot6 char_width, + FT_F26Dot6 char_height, + FT_UInt horz_resolution, + FT_UInt vert_resolution ); + + + /*************************************************************************/ + /* */ + /* */ + /* FTDriver_setPixelSizes */ + /* */ + /* */ + /* A driver method used to reset a size's character sizes (horizontal */ + /* and vertical) expressed in integer pixels. */ + /* */ + /* */ + /* size :: A handle to the target size object. */ + /* */ + /* pixel_width :: The character width expressed in 26.6 fractional */ + /* pixels. */ + /* */ + /* pixel_height :: The character height expressed in 26.6 fractional */ + /* pixels. */ + /* */ + /* point_size :: The corresponding character size in points. This */ + /* value is only sent to the TrueType bytecode */ + /* interpreter, even though 99% of glyph programs */ + /* will simply ignore it. A safe value there is the */ + /* maximum of the pixel width and height (multiplied */ + /* by 64 to make it a 26.6 fixed float). */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* This function should work with all kinds of `Size' objects, either */ + /* fixed or scalable ones. The `point_size' parameter will simply be */ + /* ignored in case of fixed formats. */ + /* */ + typedef FT_Error (*FTDriver_setPixelSizes)( FT_Size size, + FT_UInt pixel_width, + FT_UInt pixel_height ); + + + /*************************************************************************/ + /* */ + /* */ + /* FTDriver_doneSize */ + /* */ + /* */ + /* A driver method used to finalize a given size object. This method */ + /* does NOT destroy the object; this is the responsibility of the */ + /* caller. */ + /* */ + /* */ + /* size :: A handle to the target size object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + typedef void (*FTDriver_doneSize)( FT_Size size ); + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** G L Y P H S L O T S ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* FTDriver_initGlyphSlot */ + /* */ + /* */ + /* A driver method used to initialize a new glyph slot object. The */ + /* object must be created by the caller. The glyph slot is a */ + /* container where a single glyph can be loaded, either in outline or */ + /* bitmap format. */ + /* */ + /* */ + /* face :: A handle to the parent face object. */ + /* slot :: A handle to the new glyph slot object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + typedef FT_Error (*FTDriver_initGlyphSlot)( FT_GlyphSlot slot ); + + + /*************************************************************************/ + /* */ + /* */ + /* FTDriver_doneGlyphSlot */ + /* */ + /* */ + /* A driver method used to finalize a given glyph slot. The object */ + /* is not destroyed by this function. */ + /* */ + /* */ + /* face :: A handle to the parent face object. */ + /* slot :: A handle to the new glyph slot object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + typedef void (*FTDriver_doneGlyphSlot)( FT_GlyphSlot slot ); + + + /*************************************************************************/ + /* */ + /* */ + /* FTDriver_loadGlyph */ + /* */ + /* */ + /* A driver method used to load a glyph within a given glyph slot. */ + /* */ + /* */ + /* slot :: A handle to 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 */ + /* 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). */ + /* */ + /* result :: A set of bit flags indicating the type of data that */ + /* was loaded in the glyph slot (outline, bitmap, */ + /* pixmap, etc). */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + typedef FT_Error (*FTDriver_loadGlyph)( FT_GlyphSlot slot, + FT_Size size, + FT_UInt glyph_index, + FT_Int load_flags ); + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** C H A R A C T E R M A P S ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* */ + /* FTDriver_getCharIndex */ + /* */ + /* */ + /* Uses a charmap to return a given character code's glyph index. */ + /* */ + /* */ + /* charmap :: A handle to the source charmap object. */ + /* charcode :: The character code. */ + /* */ + /* */ + /* The glyph index. 0 means `undefined character code'. */ + /* */ + typedef FT_UInt (*FTDriver_getCharIndex)( FT_CharMap charmap, + FT_Long charcode ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_DriverInterface */ + /* */ + /* */ + /* A structure which holds a font driver's basic interface used by */ + /* the high-level parts of FreeType (or other applications). */ + /* */ + /* Most scalable drivers provide a specialized interface to access */ + /* format specific features. It can be retrieved with a call to */ + /* `get_format_interface()', and should be defined in each font */ + /* driver header (e.g., ttdriver.h, t1driver.h, etc). */ + /* */ + /* All fields are function pointers. */ + /* */ + /* */ + /* driver_object_size :: The size in bytes of a single driver */ + /* object. */ + /* */ + /* face_object_size :: The size in bytes of a single face object. */ + /* */ + /* size_object_size :: The size in bytes of a single size object. */ + /* */ + /* slot_object_size :: The size in bytes of a single glyph slot */ + /* object. */ + /* */ + /* driver_name :: a string to describe the driver to the */ + /* system. It doesn't necessarily describe */ + /* in detail all the font formats the driver */ + /* may support. */ + /* */ + /* driver_version :: driver version number. starts at 1 */ + /* */ + /* driver_requires :: the FreeType major version this driver is */ + /* written for. This number should be equal */ + /* to or greater than 2 ! */ + /* */ + /* format_interface :: A pointer to the driver's format-specific */ + /* interface. */ + /* */ + /* init_driver :: Used to initialize a given driver object. */ + /* */ + /* done_driver :: Used to finalize and destroy a given */ + /* driver object. */ + /* */ + /* get_extension :: Returns an interface for a given driver */ + /* extension. */ + /* */ + /* init_face :: Initializes a given face object. */ + /* */ + /* done_face :: Discards a face object, as well as all */ + /* child objects (sizes, charmaps, glyph */ + /* slots). */ + /* */ + /* get_kerning :: Returns the kerning vector corresponding */ + /* to a pair of glyphs, expressed in unscaled */ + /* font units. */ + /* */ + /* init_size :: Initializes a given size object. */ + /* */ + /* done_size :: Finalizes a given size object. */ + /* */ + /* set_size_char_sizes :: Resets a scalable size object's character */ + /* size. */ + /* */ + /* set_pixel_sizes :: Resets a face size object's pixel */ + /* dimensions. Applies to both scalable and */ + /* fixed faces. */ + /* */ + /* init_glyph_slot :: Initializes a given glyph slot object. */ + /* */ + /* done_glyph_slot :: Finalizes a given glyph slot. */ + /* */ + /* load_glyph :: Loads a given glyph into a given slot. */ + /* */ + typedef struct FT_DriverInterface_ + { + FT_Int driver_object_size; + FT_Int face_object_size; + FT_Int size_object_size; + FT_Int slot_object_size; + + FT_String* driver_name; + FT_Int driver_version; + FT_Int driver_requires; + + void* format_interface; + + FTDriver_initDriver init_driver; + FTDriver_doneDriver done_driver; + FTDriver_getInterface get_interface; + + FTDriver_initFace init_face; + FTDriver_doneFace done_face; + FTDriver_getKerning get_kerning; + + FTDriver_initSize init_size; + FTDriver_doneSize done_size; + FTDriver_setCharSizes set_char_sizes; + FTDriver_setPixelSizes set_pixel_sizes; + + FTDriver_initGlyphSlot init_glyph_slot; + FTDriver_doneGlyphSlot done_glyph_slot; + FTDriver_loadGlyph load_glyph; + + FTDriver_getCharIndex get_char_index; + + } FT_DriverInterface; + + + + /*************************************************************************/ + /* */ + /* */ + /* FT_DriverChain */ + /* */ + /* */ + /* A very structure used exclusively by "ftinit.c" in the function */ + /* FT_Add_Default_Drivers. This function is in charge of loading the */ + /* set of "default" font drivers into each new library object. */ + /* */ + /* The set itself is determined at _compile_ time through various */ + /* macro definitions. */ + /* */ + /* */ + /* next :: pointer to next element in driver list chain */ + /* interface :: pointer to the driver's interface */ + /* */ + typedef struct FT_DriverChain_ FT_DriverChain; + + struct FT_DriverChain_ + { + const FT_DriverChain* next; + const FT_DriverInterface* interface; + }; + + +/************************************************************************* + * + * Here is a template of the code that should appear in each + * font driver's _interface_ file (the one included by "ftinit.c"). + * + * It is used to build, at compile time, a simple linked list of + * the interfaces of the drivers which have been #included in + * "ftinit.c". See the source code of the latter file for details + * + * (Note that this is only required when you want your driver included + * in the set of default drivers loaded by FT_Init_FreeType. Other + * drivers can still be added manually at runtime with FT_Add_Driver. + * + * { + * #ifdef FTINIT_DRIVER_CHAIN + * + * static + * const FT_DriverChain ftinit__driver_chain = + * { + * FT_INIT_LAST_DRIVER_CHAIN, + * &_driver_interface + * }; + * + * #undef FT_INIT_LAST_DRIVER_CHAIN + * #define FT_INIT_LAST_DRIVER_CHAIN &ftinit__driver_chain + * + * #endif + * } + * + * replace with your driver's prefix + * + *************************************************************************/ + + +#endif /* FTDRIVER_H */ + + +/* END */ diff --git a/src/base/ftextend.c b/src/base/ftextend.c new file mode 100644 index 000000000..415d38b96 --- /dev/null +++ b/src/base/ftextend.c @@ -0,0 +1,199 @@ +/******************************************************************* + * + * ftextend.h 2.0 + * + * Extensions Implementation + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.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 "ftextend.h" +#include "ftobjs.h" + +/* required by the tracing mode */ +#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; + + + /* Initialize the extension component */ + + LOCAL_FUNC + FT_Error FT_Init_Extensions( FT_Driver driver ) + { + FT_Error error; + FT_Memory memory; + FT_Extension_Registry* registry; + + memory = driver->library->memory; + if ( ALLOC( registry, sizeof (*registry) ) ) + return error; + + registry->num_extensions = 0; + registry->cur_offset = 0; + driver->extensions = registry; + + return FT_Err_Ok; + } + + + /* Finalize the extension component */ + + LOCAL_FUNC + FT_Error FT_Done_Extensions( FT_Driver driver ) + { + FT_Memory memory = driver->memory; + + FREE( driver->extensions ); + return FT_Err_Ok; + } + + + /* Register a new extension */ + + EXPORT_FUNC + FT_Error FT_Register_Extension( FT_Driver driver, + FT_Extension_Class* clazz ) + { + FT_Extension_Registry* registry; + + 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; + } + + return FT_Err_Ok; + } + + + /* Query an extension block by extension_ID */ + + EXPORT_FUNC + void* FT_Get_Extension( FT_Face face, + const char* extension_id, + void* *extension_interface ) + { + FT_Extension_Registry* registry; + + 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; + return (void*)((char*)face->extensions + cur->offset); + } + } + + /* could not find the extension id */ + *extension_interface = 0; + return 0; + } + + /* Destroy all extensions within a face object. 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->memory; + FREE( face->extensions ); + } + return FT_Err_Ok; + } + + + /* Create an extension within a face object. 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 succesfully if none is there */ + registry = (FT_Extension_Registry*)face->driver->extensions; + if (!registry) return FT_Err_Ok; + + memory = face->driver->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/src/base/ftextend.h b/src/base/ftextend.h new file mode 100644 index 000000000..4433a3b24 --- /dev/null +++ b/src/base/ftextend.h @@ -0,0 +1,166 @@ +/******************************************************************* + * + * ftextend.h 2.0 + * + * Extensions Interface. + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.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 "ftconfig.h" +#include "ftobjs.h" + + +#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 + * to it at creation time. This function is used to initialize + * a given extension data for a given face. + * + * + * ext :: a typeless pointer to the extension data. + * face :: handle to the source face object the extension is + * associated with + * + * + * Error condition. 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 + * to it at creation time. This function is used to finalize + * a given extension data for a given face. This occurs before + * the face object itself is finalized. + * + * + * ext :: a typeless pointer to the extension data. + * face :: 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 + * + * inteface :: 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; + + + 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 + + /* Returns an extension's data & inteface according to its ID */ + 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/src/base/ftinit.c b/src/base/ftinit.c new file mode 100644 index 000000000..ca754aedf --- /dev/null +++ b/src/base/ftinit.c @@ -0,0 +1,169 @@ +/***************************************************************************/ +/* */ +/* ftinit.c */ +/* */ +/* FreeType initialisation layer (body). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 three following + * functions: + * + * FT_Default_Drivers: + * This function is used to add the set of default drivers + * to a fresh new library object. The set is computed at compile + * time from the Makefiles inclusions in Makefile.lib. See the + * document "FreeType Internals" for more info. + * + * + * FT_Init_FreeType: + * This function creates a system object for the current platform, + * builds a library out of it, then calls FT_Default_Drivers + * + * + * FT_Done_FreeType: + * This function simply finalise the library and the corresponding + * system object. + * + * + * 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 + +#undef FT_COMPONENT +#define FT_COMPONENT trace_init + + /*************************************************************************/ + /* */ + /* The macros FT_SUPPORT_xxxx are defined by Makefile.lib when this file */ + /* is compiled. They come from a make variable called FTINIT_MACROS */ + /* which is updated by each driver Makefile. */ + /* */ + /* This means that when a driver isn't part of the build, ftinit.o */ + /* won't try to reference it. */ + /* */ + /*************************************************************************/ + +#define FTINIT_DRIVER_CHAIN +#define FT_INIT_LAST_DRIVER_CHAIN ((FT_DriverChain*) 0) + + /* Include the SFNT driver interface if needed */ + +#ifdef FT_SUPPORT_SFNT +#include "sfdriver.h" +#endif + + /* Include the TrueType driver interface if needed */ + +#ifdef FT_SUPPORT_TRUETYPE +#include "ttdriver.h" +#endif + + + /* Include the Type1 driver interface if needed */ + +#ifdef FT_SUPPORT_TYPE1 +#include "t1driver.h" +#endif + + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Default_Drivers */ + /* */ + /* */ + /* Adds the set of default drivers to a given library object. */ + /* */ + /* */ + /* library :: A handle to a new library object. */ + /* */ + EXPORT_FUNC + void FT_Default_Drivers( FT_Library library ) + { + FT_Error error; + const FT_DriverChain* chain = FT_INIT_LAST_DRIVER_CHAIN; + + while (chain) + { + error = FT_Add_Driver( library, chain->interface ); + + /* notify errors, but don't stop */ + if (error) + { + FT_ERROR(( "FT.Default_Drivers: cannot install `%s', error = %x\n", + chain->interface->driver_name, + error )); + } + + chain = chain->next; + error = 0; /* clear error */ + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + 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:" )); + FT_ERROR(( " cannot find memory manager" )); + return FT_Err_Unimplemented_Feature; + } + + /* builds a library out of it, then fill it with the set of */ + /* default drivers.. */ + error = FT_New_Library( memory, library ); + if ( !error ) + FT_Default_Drivers(*library); + + return error; + } + + +/* END */ diff --git a/src/base/ftlist.c b/src/base/ftlist.c new file mode 100644 index 000000000..fd2241f36 --- /dev/null +++ b/src/base/ftlist.c @@ -0,0 +1,300 @@ +/***************************************************************************/ +/* */ +/* ftlist.c */ +/* */ +/* Generic list support for FreeType (body). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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. */ + /* */ + /*************************************************************************/ + + +#include +#include +#include + + + /*************************************************************************/ + /* */ + /* */ + /* 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 at 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 wether we're 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 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 where destructions take */ + /* place. */ + /* */ + /* 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/src/base/ftlist.h b/src/base/ftlist.h new file mode 100644 index 000000000..23193263b --- /dev/null +++ b/src/base/ftlist.h @@ -0,0 +1,228 @@ +/***************************************************************************/ +/* */ +/* ftlist.c */ +/* */ +/* Generic list support for FreeType (specification). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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_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. */ + /* */ + EXPORT_DEF + FT_ListNode FT_List_Find( FT_List list, + void* data ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_List_Add */ + /* */ + /* */ + /* Appends an element at the end of a list. */ + /* */ + /* */ + /* list :: A pointer to the parent list. */ + /* node :: The node to append. */ + /* */ + EXPORT_DEF + void FT_List_Add( FT_List list, + FT_ListNode node ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_List_Insert */ + /* */ + /* */ + /* Inserts an element at the head of a list. */ + /* */ + /* */ + /* list :: A pointer to parent list. */ + /* node :: The node to insert. */ + /* */ + EXPORT_DEF + void FT_List_Insert( FT_List list, + FT_ListNode 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. */ + /* */ + EXPORT_DEF + void FT_List_Remove( FT_List list, + FT_ListNode node ); + + + /*************************************************************************/ + /* */ + /* */ + /* 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. */ + /* */ + 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_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 of the last iterator call. */ + /* */ + 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 */ + /* finalisation 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 */ + /* used to point to the iteration's state. */ + /* */ + typedef void (*FT_List_Destructor)( FT_Memory memory, + void* data, + void* user ); + + + /*************************************************************************/ + /* */ + /* */ + /* 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. */ + /* */ + /* system :: The current system object where destructions take */ + /* place. */ + /* */ + /* user :: A user-supplied field which is passed as the last */ + /* argument to the destructor. */ + /* */ + 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/src/base/ftobjs.c b/src/base/ftobjs.c new file mode 100644 index 000000000..9e8e93302 --- /dev/null +++ b/src/base/ftobjs.c @@ -0,0 +1,2123 @@ +/***************************************************************************/ +/* */ +/* ftobjs.c */ +/* */ +/* The FreeType private base classes (base). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** M E M O R Y ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the PTRACE() and PERROR() 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' where allocation */ + /* occurs. */ + /* */ + /* 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_TRACE2(( "FT_Alloc:" )); + FT_TRACE2(( " size = %ld, block = 0x%08lx, ref = 0x%08lx\n", + size, (long)*P, (long)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' where allocation */ + /* occurs. */ + /* */ + /* current :: 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. */ + /* */ + /* When the memory object's flag FT_SYSTEM_FLAG_NO_REALLOC is */ + /* set, this function will try to emulate a realloc through uses */ + /* of FT_Alloc and FT_Free. Otherwise, it will call the system- */ + /* specific "realloc" implementation. */ + /* */ + /* (Some embedded systems do not have a working realloc). */ + /* */ + 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' where allocation */ + /* occured. */ + /* */ + /* 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_TRACE2(( "FT_Free:" )); + FT_TRACE2(( " Freeing block 0x%08lx, ref 0x%08lx\n", + (long)P, (P ? (long)*P : -1) )); + + FT_Assert( P != 0 ); + + if ( *P ) + { + memory->free( memory, *P ); + *P = 0; + } + } + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** O B J E C T M A N A G E M E N T ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + /* destructor for sizes list */ + static + void destroy_size( FT_Memory memory, + FT_Size size, + FT_Driver driver ) + { + /* finalize format-specific stuff */ + driver->interface.done_size( size ); + FREE( size ); + } + + + /* destructor for faces list */ + static + void destroy_face( FT_Memory memory, + FT_Face face, + FT_Driver driver ) + { + /* Discard glyph slots for this face */ + /* XXX: 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; + + /* finalize format-specific stuff */ + driver->interface.done_face( face ); + + /* Now discard client data */ + if ( face->generic.finalizer ) + face->generic.finalizer( face ); + + /* get rid of it */ + FREE( face ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* Destroy_Driver */ + /* */ + /* */ + /* Destroys a given driver object. This also destroys all child */ + /* faces. */ + /* */ + /* */ + /* driver :: A handle to the target driver object. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + /* */ + /* The driver _must_ be LOCKED! */ + /* */ + static + void Destroy_Driver( FT_Driver driver ) + { + FT_Memory memory = driver->memory; + + /* now, finalize all faces in the driver list */ + FT_List_Finalize( &driver->faces_list, + (FT_List_Destructor)destroy_face, + memory, + driver ); + + /* finalize the driver object */ + if (driver->interface.done_driver) + driver->interface.done_driver(driver); + + /* finalize client-data */ + if (driver->generic.finalizer) + driver->generic.finalizer(driver); + + /* discard it */ + FREE( driver ); + } + + + + + + BASE_FUNC + FT_Glyph_Format* FT_Get_Glyph_Format( FT_Library library, + FT_Glyph_Tag format_tag ) + { + FT_Glyph_Format* cur = library->glyph_formats; + FT_Glyph_Format* limit = cur + FT_MAX_GLYPH_FORMATS; + + for ( ; cur < limit; cur ++ ) + { + if ( cur->format_tag == format_tag ) + return cur; + } + + return 0; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_Raster */ + /* */ + /* */ + /* This function is used to change the raster module used to convert */ + /* 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. */ + /* */ + /* */ + /* library :: A handle to a new library object. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + EXPORT_FUNC + FT_Error FT_Set_Raster( FT_Library library, + FT_Raster_Interface* interface, + FT_Raster raster ) + { + FT_Memory memory = library->memory; + FT_Error error = FT_Err_Ok; + FT_Glyph_Format* format; + + /* allocate the render pool if necessary */ + if ( !library->raster_pool && + ALLOC( library->raster_pool, FT_RENDER_POOL_SIZE ) ) + goto Exit; + + /* find the glyph formatter for the raster's format */ + format = FT_Get_Glyph_Format( library, interface->format_tag ); + if (!format) + { + error = FT_Err_Invalid_Argument; + goto Exit; + } + + /* free previous raster object if necessary */ + if (format->raster_allocated) + { + FREE( format->raster ); + format->raster_allocated = 0; + } + + /* allocate new raster object is necessary */ + if (!raster) + { + if ( ALLOC( raster, interface->size ) ) + goto Exit; + + format->raster_allocated = 1; + } + format->raster = raster; + format->raster_interface = interface; + + /* initialize the raster object */ + error = interface->init( raster, + (char*)library->raster_pool, + FT_RENDER_POOL_SIZE ); + if (error) + { + if (format->raster_allocated) + { + FREE( format->raster ); + format->raster_allocated = 0; + } + } + + Exit: + return error; + } + + EXPORT_FUNC + void FT_Set_Debug_Hook( FT_Library library, + FT_UInt hook_index, + FT_DebugHook_Func debug_hook ) + { + if (hook_index < (sizeof(library->debug_hooks)/sizeof(void*))) + { + library->debug_hooks[hook_index] = debug_hook; + } + } + + + + BASE_FUNC + FT_Error FT_Add_Glyph_Format( FT_Library library, + FT_Glyph_Format* format ) + { + FT_Glyph_Format* new = 0; + + { + FT_Glyph_Format* cur = library->glyph_formats; + FT_Glyph_Format* limit = cur + FT_MAX_GLYPH_FORMATS; + + for ( ; cur < limit; cur++ ) + { + /* return an error if the format is already registered */ + if ( cur->format_tag == format->format_tag ) + return FT_Err_Invalid_Glyph_Format; + + if ( cur->format_tag == 0 && new == 0 ) + new = cur; + } + } + + /* if there is no place to hold the new format, return an error */ + if (!new) + return FT_Err_Too_Many_Glyph_Formats; + + *new = *format; + + /* now, create a raster object if we need to */ + return FT_Set_Raster( library, + format->raster_interface, + format->raster ); + } + + + + BASE_FUNC + FT_Error FT_Remove_Glyph_Format( FT_Library library, + FT_Glyph_Tag format_tag ) + { + FT_Memory memory; + FT_Glyph_Format* cur = library->glyph_formats; + FT_Glyph_Format* limit = cur + FT_MAX_GLYPH_FORMATS; + + memory = library->memory; + + for ( ; cur < limit; cur++ ) + { + if (cur->format_tag == format_tag) + { + if (cur->raster_allocated) + { + FREE( cur->raster ); + cur->raster_allocated = 0; + } + cur->format_tag = 0; + return FT_Err_Ok; + } + } + + return FT_Err_Invalid_Argument; + } + + + /*************************************************************************/ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* library :: A handle to a new library object. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + EXPORT_FUNC + FT_Error FT_New_Library( FT_Memory memory, + FT_Library* alibrary ) + { + FT_Library library = 0; + FT_Error error; + + /* First of all, allocate the library object */ + if ( ALLOC( library, sizeof ( *library ) ) ) + return error; + + library->memory = memory; + + /* now register the default raster for the `outline' glyph image format */ + { + FT_Glyph_Format outline_format = + { + ft_glyph_format_outline, + &ft_default_raster, + 0, + 0 + }; + + error = FT_Add_Glyph_Format( library, &outline_format ); + } + + /* That's ok now */ + *alibrary = library; + + return FT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Done_Library */ + /* */ + /* */ + /* Discards a given library object. This closes all drivers and */ + /* discards all resource objects. */ + /* */ + /* */ + /* library :: A handle to the target library */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + EXPORT_FUNC + FT_Error FT_Done_Library( FT_Library library ) + { + FT_Memory memory; + FT_Int 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 drivers in the library */ + for ( n = 0; n < library->num_drivers; n++ ) + { + FT_Driver driver = library->drivers[n]; + + if ( driver ) + { + Destroy_Driver( driver ); + library->drivers[n] = 0; + } + } + + /* Destroy raster object */ + FREE( library->raster_pool ); + + { + FT_Glyph_Format* cur = library->glyph_formats; + FT_Glyph_Format* limit = cur + FT_MAX_GLYPH_FORMATS; + + for ( ; cur < limit; cur++ ) + { + if ( cur->raster_allocated ) + { + FREE( cur->raster ); + cur->raster_allocated = 0; + } + } + } + + FREE( library ); + + return FT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_Raster_Mode */ + /* */ + /* */ + /* Set a raster-specific mode. */ + /* */ + /* */ + /* library :: A handle to a target library object. */ + /* format :: the glyph format used to select the raster */ + /* mode :: the raster-specific mode descriptor */ + /* args :: the mode arguments */ + /* */ + /* Error code. 0 means success. */ + /* */ + EXPORT_FUNC + FT_Error FT_Set_Raster_Mode( FT_Library library, + FT_Glyph_Tag format_tag, + const char* mode, + const char* args ) + { + FT_Memory memory; + FT_Error error; + FT_Glyph_Format* format = 0; + + { + FT_Glyph_Format* cur = library->glyph_formats; + FT_Glyph_Format* limit = cur + FT_MAX_GLYPH_FORMATS; + + for (; cur < limit; cur++) + { + if (cur->format_tag == format_tag) + { + format = cur; + break; + } + } + } + + if (!format) + return FT_Err_Invalid_Argument; + + memory = library->memory; + + error = FT_Err_Ok; + if (format->raster) + error = format->raster_interface->set_mode( format->raster, mode, args ); + + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Add_Driver */ + /* */ + /* */ + /* Registers a new driver in a given library object. This function */ + /* takes only a pointer to a driver interface. It uses it to create */ + /* the new driver, then sets up some important fields. */ + /* */ + /* */ + /* library :: A handle to the target library object. */ + /* */ + /* driver_interface :: A pointer to a driver interface table. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + /* */ + /* This function doesn't check whether the driver is already */ + /* installed! */ + /* */ + EXPORT_FUNC + FT_Error FT_Add_Driver( FT_Library library, + const FT_DriverInterface* driver_interface ) + { + FT_Error error; + FT_Driver driver; + FT_Memory memory; + + if ( !library || !driver_interface ) + return FT_Err_Invalid_Library_Handle; + + memory = library->memory; + error = FT_Err_Ok; + + if ( library->num_drivers >= FT_MAX_DRIVERS ) + error = FT_Err_Too_Many_Drivers; + else + { + if ( ALLOC( driver, driver_interface->driver_object_size ) ) + goto Exit; + + driver->library = library; + driver->memory = memory; + driver->interface = *driver_interface; + + if (driver_interface->init_driver) + { + error = driver_interface->init_driver( driver ); + if ( error ) goto Fail; + } + + library->drivers[library->num_drivers++] = driver; + goto Exit; + + Fail: + FREE( driver ); + } + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Remove_Driver */ + /* */ + /* */ + /* Unregister a given driver. This closes the driver, which in turn */ + /* destroys all faces, sizes, slots, etc. associated with it. */ + /* */ + /* This function also DESTROYS the driver object. */ + /* */ + /* */ + /* driver :: A handle to target driver object. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + EXPORT_FUNC + FT_Error FT_Remove_Driver( FT_Driver driver ) + { + FT_Library library; + FT_Memory memory; + FT_Driver *cur, *last; + FT_Error error; + + + if ( !driver ) + return FT_Err_Invalid_Driver_Handle; + + library = driver->library; + memory = driver->memory; + + if ( !library || !memory ) + return FT_Err_Invalid_Driver_Handle; + + /* look-up driver entry in library table */ + error = FT_Err_Invalid_Driver_Handle; + cur = library->drivers; + last = cur + library->num_drivers - 1; + + for ( ; cur <= last; cur++ ) + { + if ( *cur == driver ) + { + /* Destroy the driver object */ + Destroy_Driver( driver ); + + /* now move the last driver in the table to the vacant slot */ + if (cur < last) + { + *cur = *last; + *last = 0; + } + library->num_drivers--; + + /* exit loop */ + error = FT_Err_Ok; + break; + } + } + + return error; + } + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Driver */ + /* */ + /* */ + /* returns the handle of the driver responsible for a given format */ + /* (or service) according to its `name'. */ + /* */ + /* */ + /* library :: handle to library object. */ + /* driver_name :: name of driver to look-up. */ + /* */ + /* */ + /* handle to driver object. 0 otherwise */ + /* */ + EXPORT_FUNC + FT_Driver FT_Get_Driver( FT_Library library, + char* driver_name ) + { + FT_Driver *cur, *limit; + + if (!library || !driver_name) + return 0; + + cur = library->drivers; + limit = cur + library->num_drivers; + for ( ; cur < limit; cur++ ) + { + if ( strcmp( (*cur)->interface.driver_name, driver_name ) == 0 ) + return *cur; + } + return 0; + } + + + + static + FT_Error open_face( FT_Driver driver, + FT_Stream stream, + FT_Long face_index, + FT_Face* aface ) + { + FT_Memory memory; + FT_DriverInterface* interface; + FT_Face face = 0; + FT_Error error; + + + interface = &driver->interface; + memory = driver->memory; + + /* allocate the face object, and performs basic initialisation */ + if ( ALLOC( face, interface->face_object_size ) ) + goto Fail; + + face->driver = driver; + face->memory = memory; + face->stream = stream; + + error = interface->init_face( stream, face_index, face ); + if ( error ) + goto Fail; + + *aface = face; + + Fail: + if ( error ) + { + interface->done_face( face ); + FREE( face ); + *aface = 0; + } + + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_New_Face */ + /* */ + /* */ + /* Creates a new face object from a given resource and typeface */ + /* index. */ + /* */ + /* */ + /* resource :: A handle to a source resource. */ + /* */ + /* face_index :: The index of the face within the resource. The */ + /* first face has index 0. */ + /* */ + /* face :: A handle to a new face object. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + /* */ + /* Unlike FreeType 1.1, 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 through 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. */ + /* */ + EXPORT_FUNC + FT_Error FT_New_Face( FT_Library library, + const char* pathname, + FT_Long face_index, + FT_Face *aface ) + { + FT_Stream stream; + FT_Memory memory; + FT_Error error; + + memory = library->memory; + if ( ALLOC( stream, sizeof(*stream) ) ) + goto Fail; + + stream->memory = memory; + + error = FT_New_Stream( pathname, stream ); + if (error) goto Fail_Stream; + + error = FT_Open_Face( library, stream, face_index, aface ); + if (!error) + return error; + + /* close stream in case of error */ + stream->close( stream ); + + Fail_Stream: + FREE(stream); + Fail: + return error; + } + + EXPORT_FUNC + FT_Error FT_New_Memory_Face( FT_Library library, + void* file_base, + FT_Long file_size, + FT_Long face_index, + FT_Face* face ) + { + FT_Stream stream; + FT_Memory memory; + FT_Error error; + + memory = library->memory; + if ( ALLOC( stream, sizeof(*stream) ) ) + goto Fail; + + stream->memory = memory; + + FT_New_Memory_Stream( library, (void*)file_base, file_size, stream ); + + error = FT_Open_Face( library, stream, face_index, face ); + if (!error) + return error; + + FREE(stream); + Fail: + return error; + } + + + EXPORT_FUNC + FT_Error FT_Open_Face( FT_Library library, + FT_Stream stream, + FT_Long face_index, + FT_Face* aface ) + { + FT_Error error; + FT_Driver driver; + FT_Memory memory; + FT_Face face = 0; + FT_ListNode node = 0; + + *aface = 0; + + if ( !library || !stream ) + return FT_Err_Invalid_Handle; + + memory = library->memory; + + { + /* check each font driver for an appropriate format */ + FT_Driver* cur = library->drivers; + FT_Driver* limit = cur + library->num_drivers; + + for ( ; cur < limit; cur++ ) + { + driver = *cur; + if (driver->interface.face_object_size) + { + error = open_face( driver, stream, face_index, &face ); + if ( !error ) + goto Success; + + if ( error != FT_Err_Unknown_File_Format ) + goto Bad_Resource; + } + } + + /* no driver is able to handle this format */ + error = FT_Err_Unknown_File_Format; + goto Bad_Resource; + } + + Success: + /****************************************************************/ + /* if we were simply checking the font format, discard the face */ + /* object, then return successfully. */ + if ( face_index < 0 ) + { + driver->interface.done_face( face ); + FREE( face ); + goto Exit; + } + + FT_TRACE4(( "FT_New_Face: New face object, adding to list\n" )); + + /****************************************************************/ + /* Otherwise add the face object to its driver's list */ + if ( ALLOC( node, sizeof ( *node ) ) ) + goto Fail; + + node->data = face; + FT_List_Add( &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; + } + + /****************************************************************/ + /* 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; + } + + *aface = face; + goto Exit; + + Fail: + FT_Done_Face( face ); + + Bad_Resource: + + Exit: + FT_TRACE4(( "FT_Open_Face: Return %d\n", error )); + 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. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + EXPORT_FUNC + FT_Error FT_Done_Face( FT_Face face ) + { + FT_Error error; + FT_Driver driver; + FT_Memory memory; + FT_DriverInterface* interface; + FT_ListNode node; + + + if (!face || !face->driver ) + return FT_Err_Invalid_Face_Handle; + + driver = face->driver; + interface = &driver->interface; + memory = driver->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; + } + else + error = FT_Err_Invalid_Face_Handle; + + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_New_Size */ + /* */ + /* */ + /* Creates a new size object from a given face object. */ + /* */ + /* */ + /* face :: A handle to a parent face object. */ + /* */ + /* */ + /* size :: A handle to a new size object. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + EXPORT_FUNC + FT_Error FT_New_Size( FT_Face face, + FT_Size* asize ) + { + FT_Error error; + FT_Memory memory; + FT_Driver driver; + FT_DriverInterface* interface; + + FT_Size size = 0; + FT_ListNode node = 0; + + + if ( !face || !face->driver ) + return FT_Err_Invalid_Face_Handle; + + *asize = 0; + driver = face->driver; + interface = &driver->interface; + memory = face->memory; + + /* Allocate new size object and perform basic initialisation */ + if ( ALLOC( size, interface->size_object_size ) || + ALLOC( node, sizeof ( FT_ListNodeRec ) ) ) + goto Exit; + + size->face = face; + + error = interface->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 ); + + /* record as current size for the face */ + face->size = size; + } + + 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 */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + 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 || !size->face ) + return FT_Err_Invalid_Size_Handle; + + driver = size->face->driver; + if ( !driver ) + return FT_Err_Invalid_Driver_Handle; + + memory = driver->memory; + + error = FT_Err_Ok; + face = size->face; + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_Char_Size */ + /* */ + /* */ + /* Sets the character dimensions of a given size object. The */ + /* `char_size' value is used for the width and height, expressed in */ + /* 26.6 fractional points. 1 point = 1/72 inch. */ + /* */ + /* */ + /* size :: A handle to a target size object. */ + /* char_size :: The character size, in 26.6 fractional points. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + /* */ + /* When dealing with fixed-size faces (i.e., non-scalable formats), */ + /* use the function FT_Set_Pixel_Sizes(). */ + /* */ + 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_Driver driver; + FT_Memory memory; + FT_DriverInterface* interface; + + if ( !face || !face->size || !face->driver) + return FT_Err_Invalid_Face_Handle; + + 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; + interface = &driver->interface; + memory = driver->memory; + + error = interface->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 size object. The width */ + /* and height are expressed in integer pixels. */ + /* */ + /* */ + /* size :: A handle to a target size object. */ + /* pixel_width :: The character width, in integer pixels. */ + /* pixel_height :: The character height, in integer pixels. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + EXPORT_FUNC + FT_Error FT_Set_Pixel_Sizes( FT_Face face, + FT_UInt pixel_width, + FT_UInt pixel_height ) + { + FT_Error error; + FT_Driver driver; + FT_Memory memory; + FT_DriverInterface* interface; + + if ( !face || !face->size || !face->driver ) + return FT_Err_Invalid_Face_Handle; + + driver = face->driver; + interface = &driver->interface; + memory = driver->memory; + + error = interface->set_pixel_sizes( face->size, pixel_width, pixel_height ); + + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + EXPORT_FUNC + FT_Error FT_New_GlyphSlot( FT_Face face, + FT_GlyphSlot* aslot ) + { + FT_Error error; + FT_Driver driver; + FT_DriverInterface* interface; + FT_Memory memory; + FT_GlyphSlot slot; + + + *aslot = 0; + + if ( !face || !face->driver ) + return FT_Err_Invalid_Face_Handle; + + driver = face->driver; + interface = &driver->interface; + memory = driver->memory; + + FT_TRACE4(( "FT_New_GlyphSlot: Creating new slot object\n" )); + if ( ALLOC( slot, interface->slot_object_size ) ) + goto Exit; + + slot->face = face; + + slot->max_subglyphs = 0; + slot->num_subglyphs = 0; + slot->subglyphs = 0; + + error = interface->init_glyph_slot( slot ); + if ( !error ) + { + /* in case of success, add slot to the face's list */ + slot->next = face->glyph; + face->glyph = slot; + *aslot = slot; + } + + if ( error ) + FREE( 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. */ + /* */ + EXPORT_FUNC + void FT_Done_GlyphSlot( FT_GlyphSlot slot ) + { + if (slot) + { + FT_Driver driver = slot->face->driver; + FT_Memory memory = driver->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; + break; + } + cur = cur->next; + } + + driver->interface.done_glyph_slot( slot ); + FREE( slot ); + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Load_Glyph */ + /* */ + /* */ + /* A function used to load a single glyph within a given glyph slot, */ + /* for a given size. */ + /* */ + /* */ + /* slot :: 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). */ + /* */ + /* result :: A set of bit flags indicating the type of data that */ + /* was loaded in the glyph slot (outline or bitmap, */ + /* etc). */ + /* */ + /* You can set this field to 0 if you don't want this */ + /* information. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + EXPORT_FUNC + FT_Error FT_Load_Glyph( FT_Face face, + FT_UInt glyph_index, + FT_Int load_flags ) + { + FT_Error error; + FT_Driver driver; + + if ( !face || !face->size || !face->glyph ) + return FT_Err_Invalid_Face_Handle; + + driver = face->driver; + + error = driver->interface.load_glyph( face->glyph, + face->size, + glyph_index, + load_flags ); + + return error; + } + + + EXPORT_FUNC + FT_Error FT_Load_Char( FT_Face face, + FT_ULong char_code, + FT_Int load_flags ) + { + FT_Error error; + FT_Driver driver; + FT_UInt glyph_index; + + if (!face || !face->size || !face->glyph || !face->charmap ) + return FT_Err_Invalid_Face_Handle; + + driver = face->driver; + glyph_index = FT_Get_Char_Index( face, char_code ); + + if (glyph_index == 0) + error = FT_Err_Invalid_Character_Code; + else + error = driver->interface.load_glyph( face->glyph, + face->size, + glyph_index, + load_flags ); + 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. */ + /* */ + /* */ + /* 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. */ + /* */ + EXPORT_FUNC + FT_Error FT_Get_Kerning( FT_Face face, + FT_UInt left_glyph, + FT_UInt right_glyph, + FT_Vector* kerning ) + { + FT_Error error; + FT_Driver driver; + FT_Memory memory; + + + if ( !face ) + { + error = FT_Err_Invalid_Face_Handle; + goto Exit; + } + + driver = face->driver; + memory = driver->memory; + + if ( driver->interface.get_kerning ) + { + error = driver->interface.get_kerning( face, left_glyph, + right_glyph, kerning ); + } + else + { + kerning->x = 0; + kerning->y = 0; + error = FT_Err_Ok; + } + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Char_Index */ + /* */ + /* */ + /* Returns the glyph index of a given character code. This function */ + /* uses a charmap object to do the translation. */ + /* */ + /* */ + /* charmap :: A handle to a filter charmap object. */ + /* charcode :: The character code. */ + /* */ + /* */ + /* The glyph index. 0 means `undefined character code'. */ + /* */ + EXPORT_DEF + FT_UInt FT_Get_Char_Index( FT_Face face, + FT_ULong charcode ) + { + FT_UInt result; + FT_Driver driver; + + result = 0; + if ( face && face->charmap ) + { + driver = face->driver; + result = driver->interface.get_char_index( face->charmap, charcode ); + } + return result; + } + + /*************************************************************************/ + /* */ + /* */ + /* FT_Decompose_Outline */ + /* */ + /* */ + /* 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. */ + /* */ + EXPORT_FUNC + int FT_Decompose_Outline( FT_Outline* outline, + FT_Outline_Funcs* interface, + void* user ) + { + typedef enum _phases + { + phase_point, + phase_conic, + phase_cubic, + phase_cubic2 + + } TPhase; + + FT_Vector v_first; + FT_Vector v_last; + FT_Vector v_control; + FT_Vector v_control2; + FT_Vector v_start; + + FT_Vector* point; + char* flags; + + int n; /* index of contour in outline */ + int first; /* index of first point in contour */ + int index; /* current point's index */ + + int error; + + char tag; /* current point's state */ + TPhase phase; + + + first = 0; + + for ( n = 0; n < outline->n_contours; n++ ) + { + int last; /* index of last point in contour */ + + + last = outline->contours[n]; + + v_first = outline->points[first]; + v_last = outline->points[last]; + + v_start = v_control = v_first; + + tag = FT_CURVE_TAG( outline->flags[first] ); + index = first; + + /* A contour cannot start with a cubic control point! */ + + if ( tag == FT_Curve_Tag_Cubic ) + return FT_Err_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->flags[last] ) == FT_Curve_Tag_On ) + { + /* start at last point if it is on the curve */ + v_start = v_last; + } + 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; + } + phase = phase_conic; + } + else + phase = phase_point; + + + /* Begin a new contour with MOVE_TO */ + + error = interface->move_to( &v_start, user ); + if ( error ) + return error; + + point = outline->points + first; + flags = outline->flags + first; + + /* now process each contour point individually */ + + while ( index < last ) + { + index++; + point++; + flags++; + + tag = FT_CURVE_TAG( flags[0] ); + + switch ( phase ) + { + case phase_point: /* the previous point was on the curve */ + + switch ( tag ) + { + /* two succesive on points -> emit segment */ + case FT_Curve_Tag_On: + error = interface->line_to( point, user ); + break; + + /* on point + conic control -> remember control point */ + case FT_Curve_Tag_Conic: + v_control = point[0]; + phase = phase_conic; + break; + + /* on point + cubic control -> remember first control */ + default: + v_control = point[0]; + phase = phase_cubic; + break; + } + break; + + case phase_conic: /* the previous point was a conic control */ + + switch ( tag ) + { + /* conic control + on point -> emit conic arc */ + case FT_Curve_Tag_On: + error = interface->conic_to( &v_control, point, user ); + phase = phase_point; + break; + + /* two successive conics -> emit conic arc `in between' */ + case FT_Curve_Tag_Conic: + { + FT_Vector v_middle; + + + v_middle.x = (v_control.x + point->x)/2; + v_middle.y = (v_control.y + point->y)/2; + + error = interface->conic_to( &v_control, + &v_middle, user ); + v_control = point[0]; + } + break; + + default: + error = FT_Err_Invalid_Outline; + } + break; + + case phase_cubic: /* the previous point was a cubic control */ + + /* this point _must_ be a cubic control too */ + if ( tag != FT_Curve_Tag_Cubic ) + return FT_Err_Invalid_Outline; + + v_control2 = point[0]; + phase = phase_cubic2; + break; + + + case phase_cubic2: /* the two previous points were cubics */ + + /* this point _must_ be an on point */ + if ( tag != FT_Curve_Tag_On ) + error = FT_Err_Invalid_Outline; + else + error = interface->cubic_to( &v_control, &v_control2, + point, user ); + phase = phase_point; + break; + } + + /* lazy error testing */ + if ( error ) + return error; + } + + /* end of contour, close curve cleanly */ + error = 0; + + tag = FT_CURVE_TAG( outline->flags[first] ); + + switch ( phase ) + { + case phase_point: + if ( tag == FT_Curve_Tag_On ) + error = interface->line_to( &v_first, user ); + break; + + case phase_conic: + error = interface->conic_to( &v_control, &v_start, user ); + break; + + case phase_cubic2: + if ( tag == FT_Curve_Tag_On ) + error = interface->cubic_to( &v_control, &v_control2, + &v_first, user ); + else + error = FT_Err_Invalid_Outline; + break; + + default: + error = FT_Err_Invalid_Outline; + break; + } + + if ( error ) + return error; + + first = last + 1; + } + + return 0; + } + + + static + const FT_Outline null_outline = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_New_Outline */ + /* */ + /* */ + /* 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 maximum number of points within the outline. */ + /* */ + /* numContours :: The maximum 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. You can copy the source */ + /* code of this function, replacing allocations with `malloc()' if */ + /* you want to control where the objects go. */ + /* */ + BASE_FUNC + FT_Error FT_New_Outline( FT_Library library, + FT_UInt numPoints, + FT_Int numContours, + FT_Outline* outline ) + { + FT_Error error; + FT_Memory memory; + + + if ( !outline ) + return FT_Err_Invalid_Argument; + + *outline = null_outline; + memory = library->memory; + + if ( ALLOC_ARRAY( outline->points, numPoints * 2L, FT_Pos ) || + ALLOC_ARRAY( outline->flags, 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->owner = TRUE; + + return FT_Err_Ok; + + Fail: + outline->owner = TRUE; + FT_Done_Outline( library, outline ); + + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Done_Outline */ + /* */ + /* */ + /* Destroys an outline created with FT_New_Outline(). */ + /* */ + /* */ + /* 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_Alloc()/FT_Free(). You can copy the source code */ + /* of this function, replacing allocations with `malloc()' in your */ + /* application if you want something simpler. */ + /* */ + BASE_FUNC + FT_Error FT_Done_Outline( FT_Library library, + FT_Outline* outline ) + { + FT_Memory memory = library->memory; + + + if ( outline ) + { + if ( outline->owner ) + { + FREE( outline->points ); + FREE( outline->flags ); + FREE( outline->contours ); + } + *outline = null_outline; + + return FT_Err_Ok; + } + else + return FT_Err_Invalid_Argument; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Outline_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. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Yes. */ + /* */ + BASE_FUNC + FT_Error FT_Get_Outline_CBox( FT_Outline* outline, + FT_BBox* cbox ) + { + if ( outline && cbox ) + { + if ( outline->n_points == 0 ) + { + cbox->xMin = 0; + cbox->yMin = 0; + cbox->xMax = 0; + cbox->yMax = 0; + } + else + { + FT_UShort k; + FT_Vector* vec = outline->points; + + + cbox->xMin = cbox->xMax = vec->x; + cbox->yMin = cbox->yMax = vec->y; + vec++; + + for ( k = 1; k < outline->n_points; k++ ) + { + FT_Pos x, y; + + + x = vec->x; + if ( x < cbox->xMin ) cbox->xMin = x; + if ( x > cbox->xMax ) cbox->xMax = x; + + y = vec->y; + if ( y < cbox->yMin ) cbox->yMin = y; + if ( y > cbox->yMax ) cbox->yMax = y; + vec++; + } + } + return FT_Err_Ok; + } + else + return FT_Err_Invalid_Argument; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Translate_Outline */ + /* */ + /* */ + /* 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. */ + /* */ + BASE_FUNC + void FT_Translate_Outline( 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_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. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + EXPORT_FUNC + FT_Error FT_Done_FreeType( FT_Library library ) + { + /* Discard the library object */ + FT_Done_Library( library ); + + return FT_Err_Ok; + } + +/* END */ diff --git a/src/base/ftobjs.h b/src/base/ftobjs.h new file mode 100644 index 000000000..8dc90ec4a --- /dev/null +++ b/src/base/ftobjs.h @@ -0,0 +1,710 @@ +/***************************************************************************/ +/* */ +/* ftobjs.h */ +/* */ +/* The FreeType private base classes (specification). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 + + /*************************************************************************/ + /* */ + /* 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 ) ( (void)(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 + + + /*************************************************************************/ + /* */ + /* */ + /* 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 ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* */ + /* 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' where allocation */ + /* occurs. */ + /* */ + /* 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_DEF + FT_Error FT_Alloc( FT_Memory memory, + FT_Long size, + void** P ); + + + /*************************************************************************/ + /* */ + /* */ + /* 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' where allocation */ + /* occurs. */ + /* */ + /* current :: 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. */ + /* */ + /* When the memory object's flag FT_memory_FLAG_NO_REALLOC is */ + /* set, this function will try to emulate a realloc through uses */ + /* of FT_Alloc and FT_Free. Otherwise, it will call the memory- */ + /* specific "realloc" implementation. */ + /* */ + /* (Some embedded memorys do not have a working realloc). */ + /* */ + BASE_DEF + FT_Error FT_Realloc( FT_Memory memory, + FT_Long current, + FT_Long size, + void** P ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Free */ + /* */ + /* */ + /* Releases a given block of memory allocated through FT_Alloc(). */ + /* */ + /* */ + /* memory :: A handle to a given `memory object' where allocation */ + /* occured. */ + /* */ + /* P :: This is the _address_ of a _pointer_ which points to the */ + /* allocated block. It is always set to NULL on exit. */ + /* */ + /* */ + /* If P or *P are NULL, this function should return successfully. */ + /* This is a strong convention within all of FreeType and its */ + /* drivers. */ + /* */ + BASE_DEF + void FT_Free( FT_Memory memory, + void** P ); + + + + /* This include is needed by the MEM_xxx() macros, it should be */ + /* available on every platform we know !! */ +#include + +#define MEM_Set( dest, byte, count ) memset( dest, byte, count ) + +#ifdef HAVE_MEMCPY +#define MEM_Copy( dest, source, count ) memcpy( dest, source, count ) +#else +#define MEM_Copy( dest, source, count ) bcopy( source, dest, count ) +#endif + +#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. */ + /* */ + + /* */ + /* Note that ALL memory allocation functions need an IMPLICIT argument */ + /* called `memory' to point to the current memory object. */ + /* */ +#define MEM_Alloc( _pointer_, _size_ ) \ + FT_Alloc( memory, _size_, (void**)&(_pointer_) ) + +#define MEM_Realloc( _pointer_, _current_, _size_ ) \ + FT_Realloc( memory, _current_, _size_, (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_) ) + + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** D R I V E R S ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* */ + /* FT_DriverRec */ + /* */ + /* */ + /* The root font driver class. A font driver is responsible for */ + /* managing and loading font files of a given format. */ + /* */ + /* */ + /* library :: A handle to the driver's parent library. */ + /* */ + /* memory :: A handle to the driver's memory object. This is a */ + /* duplicate of `library->memory'. */ + /* */ + /* interface :: A set of driver methods that implement its */ + /* behaviour. These methods are called by the */ + /* various FreeType functions like FT_New_Face(), */ + /* FT_Load_Glyph(), etc. */ + /* */ + /* format :: A typeless pointer, used to store the address of */ + /* the driver's format specific interface. This is a */ + /* table of other driver methods that are specific to */ + /* its format. Format specific interfaces are */ + /* defined in the driver's header files (e.g., */ + /* `freetype/drivers/ttlib/ttdriver.h'). */ + /* */ + /* version :: The driver's version. It can be used for */ + /* versioning and dynamic driver update if needed. */ + /* */ + /* description :: An ASCII string describing the driver's supported */ + /* format, like `truetype', `type1', etc. */ + /* */ + /* faces_list :: The list of faces currently opened by this driver. */ + /* */ + /* extensions :: a typeless pointer to the driver's extensions */ + /* registry, when they are supported through the */ + /* config macro FT_CONFIG_OPTION_EXTENSIONS */ + /* */ + typedef struct FT_DriverRec_ + { + FT_Library library; + FT_Memory memory; + + FT_Generic generic; + + FT_DriverInterface interface; + FT_FormatInterface format; + + FT_Int version; /* driver version */ + FT_String* description; /* format description */ + + FT_ListRec faces_list; /* driver's faces list */ + + void* extensions; + + } FT_DriverRec; + + +#ifdef FT_CONFIG_OPTION_ALTERNATE_GLYPH_FORMATS + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** G L Y P H F O R M A T S ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + /************************************************************************* + * + * + * FT_Glyph_Format + * + * + * A structure used to model various properties of a non-standard + * glyph image format. + * + * + * format_tag :: the glyph format tag + * + * raster_interface :: the default rasters interface for this glyph + * format. + * + * raster :: the default raster object for this glyph format + * if set to nil, a new object will be allocated + * automatically through the raster interface. + * + * raster_owned :: a boolean used internally by the library. If + * set, if indicates that the current raster object + * was allocated by the library. + * + *************************************************************************/ + + typedef struct FT_Glyph_Format_ + { + FT_Glyph_Tag format_tag; + FT_Raster_Interface* raster_interface; + FT_Raster raster; + FT_Bool raster_allocated; + + } FT_Glyph_Format; + + + /************************************************************************* + * + * + * FT_Add_Glyph_Format + * + * + * Register a new glyph format into the library + * + * + * library :: handle to target library object + * interface :: pointer to glyph format interface + * + * + * Error code. 0 means success + * + * + * This function should normally be called by those font drivers which + * need to use their own glyph image format. + * + *************************************************************************/ + + EXPORT_DEF + FT_Error FT_Add_Glyph_Format( FT_Library library, + FT_Glyph_Format* format ); + + + /************************************************************************* + * + * + * FT_Remove_Glyph_Format + * + * + * Un-Register a given glyph format from the library + * + * + * library :: handle to target library object + * glyph_format :: glyph format tag + * + * + * Error code. 0 means success + * + * + * This function should normally be called by those font drivers which + * need to use their own glyph image format. + * + *************************************************************************/ + + EXPORT_DEF + FT_Error FT_Remove_Glyph_Format( FT_Library library, + FT_Glyph_Tag glyph_format ); + + /************************************************************************* + * + * + * FT_Get_Glyph_Format + * + * + * Return a pointer to the glyph format descriptor corresponding to + * a given format tag. + * + * + * library :: handle to source library object + * + * format_tag :: glyph format tag + * + * + * a pointer to the corresponding glyph format descriptor, if it was + * registered in the library. 0 otherwise. + * + *************************************************************************/ + + BASE_DEF + FT_Glyph_Format* FT_Get_Glyph_Format( FT_Library library, + FT_Glyph_Tag format_tag ); + + + +#endif /* FT_CONFIG_OPTION_ALTERNATE_GLYPH_FORMATS */ + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** 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_drivers :: The number of drivers currently registered */ + /* within this library. This is set to 0 for new */ + /* libraries. New drivers are added through the */ + /* FT_Add_Driver() API function. */ + /* */ + /* drivers :: A table used to store handles to the currently */ + /* registered font drivers. Note that each driver */ + /* contains a list of its opened faces. */ + /* */ + /* glyph_formats :: A table used to store glyph format descriptors */ + /* for new image formats that may have been */ + /* registered within the library */ + /* */ + /* raster_pool :: The raster object's render pool. This can */ + /* ideally be changed dynamically at run-time. */ + /* */ + typedef void (*FT_DebugHook_Func)( void* arg ); + + typedef struct FT_LibraryRec_ + { + FT_Memory memory; /* library's memory object */ + + FT_Generic generic; + + FT_Int num_drivers; + FT_Driver drivers[ FT_MAX_DRIVERS ]; /* driver objects */ + + FT_Glyph_Format glyph_formats[FT_MAX_GLYPH_FORMATS]; + + void* raster_pool; /* scan-line conversion render pool */ + + FT_DebugHook_Func debug_hooks[4]; + + } FT_LibraryRec; + + + /*************************************************************************/ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* library :: A handle to a new library object. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + /* */ + /* This function is normally not called by client applications, */ + /* unless they want to create a specific instance of FreeType which */ + /* uses a specific memory allocator. */ + /* */ + 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 face objects. */ + /* */ + /* */ + /* library :: A handle to the target library. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + EXPORT_DEF + FT_Error FT_Done_Library( FT_Library library ); + + + + EXPORT_DEF + void FT_Set_Debug_Hook( FT_Library library, + FT_UInt hook_index, + FT_DebugHook_Func debug_hook ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Add_Driver */ + /* */ + /* */ + /* Registers a new driver in a given library object. This function */ + /* takes only a pointer to a driver interface. It uses it to create */ + /* the new driver, then sets up some important fields. */ + /* */ + /* */ + /* library :: A handle to the target library object. */ + /* */ + /* driver_interface :: A pointer to a driver interface table. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + /* */ + /* This function doesn't check whether the driver is already */ + /* installed! */ + /* */ + EXPORT_DEF + FT_Error FT_Add_Driver( FT_Library library, + const FT_DriverInterface* driver_interface ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Remove_Driver */ + /* */ + /* */ + /* Unregister a given driver. This closes the driver, which in turn */ + /* destroys all faces, sizes, slots, etc. associated with it. */ + /* */ + /* This function also DESTROYS the driver object. */ + /* */ + /* */ + /* driver :: A handle to target driver object. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + EXPORT_DEF + FT_Error FT_Remove_Driver( FT_Driver driver ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Driver */ + /* */ + /* */ + /* returns the handle of the driver responsible for a given format */ + /* (or service) according to its `name'. */ + /* */ + /* */ + /* library :: handle to library object. */ + /* driver_name :: name of driver to look-up. */ + /* */ + /* */ + /* handle to driver object. 0 otherwise */ + /* */ + EXPORT_DEF + FT_Driver FT_Get_Driver( FT_Library library, + char* driver_name ); + +#ifndef FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM + + /************************************************************************** + * + * + * FT_New_Stream + * + * + * Open a new stream from a given standard ASCII file path name + * + * + * filepathname :: an ASCII string naming the file to be opened + * + * + * astream :: the opened stream descriptor to be used by the library + * + * + * Error code. 0 means success + * + * + * This function must be implemented by the system-specific part + * of the engine, i.e. `ftsystem.c'. + * + * This function should only fill the stream descriptor. Note that + * the stream's `memory' field should be left to the caller. + * + **************************************************************************/ + + extern + FT_Error FT_New_Stream( const char* filepathname, + FT_Stream astream ); + + + /************************************************************************** + * + * + * FT_New_Memory + * + * + * Returns a handle to a new memory object + * + * + * Handle to the memory object. 0 means failure + * + * + * This function must be implemented by the system-specific part + * of the engine, i.e. `ftsystem.c'. + * + * It is only used by `ftinit' in order to implement the function + * FT_Init_FreeType. + * + **************************************************************************/ + + extern + FT_Memory FT_New_Memory( void ); + +#endif + +/* 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 + extern + FT_Raster_Interface ft_default_raster; +#endif + + +#endif /* FTOBJS_H */ + + +/* END */ diff --git a/src/base/ftoutln.c b/src/base/ftoutln.c new file mode 100644 index 000000000..f6f91603b --- /dev/null +++ b/src/base/ftoutln.c @@ -0,0 +1,286 @@ +/***************************************************************************/ +/* */ +/* ftoutln.c */ +/* */ +/* FreeType outline management (body). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 +#include +#include +#include + + /*************************************************************************/ + /* */ + /* */ + /* FT_Copy_Outline */ + /* */ + /* */ + /* 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. */ + /* */ + BASE_FUNC + FT_Error FT_Copy_Outline( FT_Outline* source, + FT_Outline* target ) + { + 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 * 2 * sizeof ( FT_Pos ) ); + + MEM_Copy( target->flags, source->flags, + source->n_points * sizeof ( FT_Byte ) ); + + MEM_Copy( target->contours, source->contours, + source->n_contours * sizeof ( FT_Short ) ); + + target->high_precision = source->high_precision; + target->second_pass = target->second_pass; + target->dropout_mode = source->dropout_mode; + + return FT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Outline_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. */ + /* */ + BASE_FUNC + FT_Error FT_Get_Outline_Bitmap( FT_Library library, + FT_Outline* outline, + FT_Bitmap* map ) + { + FT_Error error; + FT_Glyph_Format* format; + + error = FT_Err_Invalid_Glyph_Format; + format = FT_Get_Glyph_Format( library, ft_glyph_format_outline ); + if (!format) goto Exit; + + error = FT_Err_Invalid_Glyph_Format; + if (!format->raster) goto Exit; + + error = format->raster_interface->render( format->raster, outline, map ); + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Transform_Outline */ + /* */ + /* */ + /* 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_Translate_Outline() if you need to translate the */ + /* outline's points. */ + /* */ + BASE_FUNC + void FT_Transform_Outline( FT_Outline* outline, + FT_Matrix* matrix ) + { + FT_UShort n; + FT_Vector* vec; + + + vec = outline->points; + for ( n = 0; n < outline->n_points; n++ ) + { + FT_Pos x, y; + + + x = FT_MulFix( vec->x, matrix->xx ) + + FT_MulFix( vec->y, matrix->xy ); + + y = FT_MulFix( vec->x, matrix->yx ) + + FT_MulFix( vec->y, matrix->yy ); + + vec->x = x; + vec->y = y; + vec++; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Transform_Vector */ + /* */ + /* */ + /* Transforms a single vector through a 2x2 matrix. */ + /* */ + /* */ + /* x :: The horizontal vector coordinate. */ + /* y :: The vertical vector coordinate. */ + /* */ + /* */ + /* matrix :: A pointer to the source 2x2 matrix. */ + /* */ + /* */ + /* Yes. */ + /* */ + BASE_FUNC + void FT_Transform_Vector( FT_Pos* x, + FT_Pos* y, + FT_Matrix* matrix ) + { + FT_Pos xz, yz; + + + xz = FT_MulFix( *x, matrix->xx ) + + FT_MulFix( *y, matrix->xy ); + + yz = FT_MulFix( *x, matrix->yx ) + + FT_MulFix( *y, matrix->yy ); + + *x = xz; + *y = yz; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Matrix_Multiply */ + /* */ + /* */ + /* Performs the matrix operation `b = a*b'. */ + /* */ + /* */ + /* a :: A pointer to matrix `a'. */ + /* */ + /* */ + /* b :: A pointer to matrix `b'. */ + /* */ + /* */ + /* Yes. */ + /* */ + BASE_FUNC + void FT_Matrix_Multiply( FT_Matrix* a, + FT_Matrix* b ) + { + FT_Fixed xx, xy, yx, yy; + + + 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. */ + /* */ + BASE_FUNC + FT_Error FT_Matrix_Invert( FT_Matrix* matrix ) + { + FT_Pos delta, xx, yy; + + + /* 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; + } + + +/* END */ diff --git a/src/base/ftoutln.h b/src/base/ftoutln.h new file mode 100644 index 000000000..c8ce7cc68 --- /dev/null +++ b/src/base/ftoutln.h @@ -0,0 +1,153 @@ +#ifndef FTOUTLN_H +#define FTOUTLN_H + +#include + + /*************************************************************************/ + /* */ + /* */ + /* FT_Copy_Outline */ + /* */ + /* */ + /* 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. */ + /* */ + EXPORT_DEF + FT_Error FT_Copy_Outline( FT_Outline* source, + FT_Outline* target ); + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Outline_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. */ + /* */ + EXPORT_DEF + FT_Error FT_Get_Outline_Bitmap( FT_Library library, + FT_Outline* outline, + FT_Bitmap* map ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Transform_Outline */ + /* */ + /* */ + /* 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_Translate_Outline() if you need to translate the */ + /* outline's points. */ + /* */ + EXPORT_DEF + void FT_Transform_Outline( FT_Outline* outline, + FT_Matrix* matrix ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Transform_Vector */ + /* */ + /* */ + /* Transforms a single vector through a 2x2 matrix. */ + /* */ + /* */ + /* x :: The horizontal vector coordinate. */ + /* y :: The vertical vector coordinate. */ + /* */ + /* */ + /* matrix :: A pointer to the source 2x2 matrix. */ + /* */ + /* */ + /* Yes. */ + /* */ + EXPORT_DEF + void FT_Transform_Vector( FT_Pos* x, + FT_Pos* y, + FT_Matrix* matrix ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Matrix_Multiply */ + /* */ + /* */ + /* Performs the matrix operation `b = a*b'. */ + /* */ + /* */ + /* a :: A pointer to matrix `a'. */ + /* */ + /* */ + /* b :: A pointer to matrix `b'. */ + /* */ + /* */ + /* Yes. */ + /* */ + 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. */ + /* */ + EXPORT_DEF + FT_Error FT_Matrix_Invert( FT_Matrix* matrix ); + +#endif /* FTOUTLN_H */ diff --git a/src/base/ftraster.c b/src/base/ftraster.c new file mode 100644 index 000000000..abf78f37e --- /dev/null +++ b/src/base/ftraster.c @@ -0,0 +1,4372 @@ +/***************************************************************************/ +/* */ +/* ftraster2.c */ +/* */ +/* The FreeType glyph rasterizer (body). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 `raster' component implements FreeType's scan-line converter, the */ + /* one used to generate bitmaps and pixmaps from vectorial outline */ + /* descriptions. */ + /* */ + /* It has been rewritten entirely for FreeType 2.0, in order to become */ + /* completely independent of the rest of the library. It should now be */ + /* possible to include it more easily in all kinds of libraries and */ + /* applications, which do not necessarily need the font engines and API. */ + /* */ + /* This version contains the following features: */ + /* */ + /* - Support for third-order Bezier arcs. */ + /* */ + /* - Improved performance of the 5-levels anti-aliasing algorithm. */ + /* */ + /* - 17-levels anti-aliasing for smoother curves, though the difference */ + /* isn't always noticeable, depending on your palette. */ + /* */ + /* - An API to decompose a raster outline into a path (i.e., into a */ + /* a series of segments and arcs). */ + /* */ + /* Planned additions: */ + /* */ + /* - Getting rid of the second pass for horizontal drop-out detection. */ + /* I've got a few ideas, but I'll have to experiment in Pascal with */ + /* them. to avoid damaging of the rendering of glyphs at small sizes. */ + /* */ + /* - Adding a `composition' callback, which should be invoked during */ + /* anti-aliased rendering. In short, it will allow line-by-line */ + /* composition (i.e., transparencies, etc.) of the output in a fairly */ + /* portable way. Of course, a single sweep is required there. */ + /* */ + /*************************************************************************/ + + +#include +#ifndef _STANDALONE_ +#include +#endif + +#ifndef EXPORT_FUNC +#define EXPORT_FUNC /* nothing */ +#endif + +#undef FT_COMPONENT +#define FT_COMPONENT trace_raster + +#ifdef _STANDALONE_ + + /*************************************************************************/ + /* */ + /* The following defines are used when the raster is compiled as a */ + /* stand-alone object. Each of them is commented, and you're free to */ + /* toggle them to suit your needs. */ + /* */ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* FT_RASTER_INT_IS_32 */ + /* */ + /* Set this configuration macro to the unsigned type which has 32 */ + /* bits. */ + /* */ +#define FT_RASTER_INT_IS_32 + + + /*************************************************************************/ + /* */ + /* FT_RASTER_OPTION_ANTI_ALIAS */ + /* */ + /* Define this configuration macro if you want to support */ + /* anti-aliasing. */ + /* */ +#define FT_RASTER_OPTION_ANTI_ALIAS + + + /*************************************************************************/ + /* */ + /* FT_RASTER_OPTION_CONIC_BEZIERS */ + /* */ + /* Define this configuration macro if your source outlines contain */ + /* second-order Bezier arcs. Typically, these are TrueType outlines. */ + /* */ +#define FT_RASTER_CONIC_BEZIERS + + + /*************************************************************************/ + /* */ + /* FT_RASTER_OPTION_CUBIC_BEZIERS */ + /* */ + /* Define this configuration macro if your source outlines contain */ + /* third-order Bezier arcs. Typically, these are Type1 outlines. */ + /* */ +#define FT_RASTER_CUBIC_BEZIERS + + + /*************************************************************************/ + /* */ + /* FT_RASTER_ANTI_ALIAS_5 */ + /* */ + /* Define this configuration macro if you want to enable the 5-grays */ + /* anti-aliasing mode. Ignored if FT_RASTER_OPTION_ANTI_ALIAS isn't */ + /* defined. */ + /* */ +#define FT_RASTER_ANTI_ALIAS_5 + + + /*************************************************************************/ + /* */ + /* FT_RASTER_ANTI_ALIAS_17 */ + /* */ + /* Define this configuration macro if you want to enable the 17-grays */ + /* anti-aliasing mode. Ignored if FT_RASTER_OPTION_ANTI_ALIAS isn't */ + /* defined. */ + /* */ +/* #define FT_RASTER_ANTI_ALIAS_17 */ + + + /*************************************************************************/ + /* */ + /* FT_RASTER_LITTLE_ENDIAN */ + /* FT_RASTER_BIG_ENDIAN */ + /* */ + /* The default anti-alias routines are processor-independent, but */ + /* slow. Define one of these macros to suit your own system, and */ + /* enjoy greatly improved rendering speed. */ + /* */ + +/* #define FT_RASTER_LITTLE_ENDIAN */ +/* #define FT_RASTER_BIG_ENDIAN */ + + +#else /* _STANDALONE_ */ + +#include +#include + + /*************************************************************************/ + /* */ + /* The following defines are used when the raster is compiled within the */ + /* FreeType base layer. Don't change these unless you really know what */ + /* you're doing. */ + /* */ + /*************************************************************************/ + + +#ifdef FT_CONFIG_OPTION_ANTI_ALIAS +#define FT_RASTER_OPTION_ANTI_ALIAS +#endif + +#define FT_RASTER_CONIC_BEZIERS +#define FT_RASTER_CUBIC_BEZIERS + +#define FT_RASTER_ANTI_ALIAS_5 +/* #define FT_RASTER_ANTI_ALIAS_17 */ + +#ifdef FT_CONFIG_OPTION_LITTLE_ENDIAN +#define FT_RASTER_LITTLE_ENDIAN +#endif + +#ifdef FT_CONFIG_OPTION_BIG_ENDIAN +#define FT_RASTER_BIG_ENDIAN +#endif + + +#endif /* _STANDALONE_ */ + + +/* to keep the compiler happy */ +#ifndef PTRACE2 +#define PTRACE2(x) /*void*/ +#endif + + /*************************************************************************/ + /* */ + /* FT_RASTER_ANY_ENDIAN indicates that no endianess was defined by one */ + /* of the configuration macros. */ + /* */ +#if !defined( FT_RASTER_LITTLE_ENDIAN ) && !defined( FT_RASTER_BIG_ENDIAN ) +#define FT_RASTER_ANY_ENDIAN +#endif + + + /*************************************************************************/ + /* */ + /* The rasterizer is a very general purpose component. Please leave the */ + /* following redefinitions here (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 UNUSED +#define UNUSED( arg ) ( (void)(arg) ) +#endif + + +#undef FAILURE +#define FAILURE TRUE + +#undef SUCCESS +#define SUCCESS FALSE + +#ifndef ABS +#define ABS(x) ( (x) < 0 ? -(x) : (x) ) +#endif + + /*************************************************************************/ + /* */ + /* Please don't touch the following macros. Their importance is */ + /* historical to FreeType, but they have some nice effects, like getting */ + /* rid of all `->' symbols when accessing the raster object (replacing */ + /* them with a simple `.'). */ + /* */ + /*************************************************************************/ + + /* used in function signatures to define the _first_ argument */ +#define RAS_ARG_ FT_Raster raster, +#define RAS_ARG FT_Raster raster + + /* used to call a function within this component, first parameter */ +#define RAS_VAR_ raster, +#define RAS_VAR raster + + /* used to access the current raster object, with a `.' instead of a */ + /* `->' */ +#define ras (*raster) + + + /*************************************************************************/ + /* */ + /* For anti-aliasing modes, we use a 2 or 4 lines intermediate bitmap */ + /* which is filtered repeatedly to render each pixmap row. The */ + /* following macro defines this buffer's size in bytes (which is part of */ + /* raster objects). */ + /* */ +#define ANTI_ALIAS_BUFFER_SIZE 2048 + + + /*************************************************************************/ + /* */ + /* Error codes returned by the scan-line converter/raster. */ + /* */ +#define ErrRaster_Ok 0 +#define ErrRaster_Uninitialized_Object 1 +#define ErrRaster_Overflow 2 +#define ErrRaster_Negative_Height 3 +#define ErrRaster_Invalid_Outline 4 +#define ErrRaster_Invalid_Map 5 +#define ErrRaster_AntiAlias_Unsupported 6 +#define ErrRaster_Invalid_Pool 7 +#define ErrRaster_Unimplemented 8 +#define ErrRaster_Bad_Palette_Count 9 + + +#define Flow_Up 1 +#define Flow_Down -1 + +#define SET_High_Precision( p ) Set_High_Precision( RAS_VAR_ p ) + + + /*************************************************************************/ + /* */ + /* Fast MulDiv, as `b' is always < 64. Don't use intermediate */ + /* precision. */ + /* */ +#define FMulDiv( a, b, c ) ( (a) * (b) / (c) ) + + + /*************************************************************************/ + /* */ + /* Define DEBUG_RASTER if you want to generate a debug version of the */ + /* rasterizer. This will progressively draw the glyphs while all the */ + /* computation are done directly on the graphics screen (the glyphs will */ + /* will be shown inverted). */ + /* */ + /* Note that DEBUG_RASTER should only be used for debugging with b/w */ + /* rendering, not with gray levels. */ + /* */ + /* The definition of DEBUG_RASTER should appear in the file */ + /* `ftconfig.h'. */ + /* */ +#ifdef DEBUG_RASTER + extern char* vio; /* A pointer to VRAM or display buffer */ +#endif + + + /*************************************************************************/ + /* */ + /* The maximum number of stacked Bezier curves. Setting this constant */ + /* to more than 32 is a pure waste of space. */ + /* */ +#define MaxBezier 32 + + + /*************************************************************************/ + /* */ + /* The number fractional bits of *input* coordinates. We always use the */ + /* 26.6 format (i.e, 6 bits for the fractional part), but hackers are */ + /* free to experiment with different values. */ + /* */ +#define Pixel_Bits 6 + + + /*************************************************************************/ + /* */ + /* An unsigned type that is exactly 32 bits on your platform. This */ + /* means `unsigned long' on 16-bit machines, and `unsigned int' on */ + /* others. */ + /* */ +#ifdef _STANDALONE_ +#if defined( FT_RASTER_INT_IS_32 ) + typedef unsigned int FT_Word32; +#elif defined( FT_RASTER_LONG_IS_32 ) + typedef unsigned long FT_Word32; +#else +#error "no 32bit type found - please check your configuration" +#endif +#endif + + + /*************************************************************************/ + /* */ + /* A pointer to an unsigned char. */ + /* */ + typedef unsigned char* PByte; + + typedef char TResult; + + typedef unsigned char Byte; + + /*************************************************************************/ + /* */ + /* The type of the pixel coordinates used within the render pool during */ + /* scan-line conversion. We use longs to store either 26.6 or 22.10 */ + /* fixed float values, depending on the `precision' we want to use */ + /* (i.e., low resp. high precision). These are ideals in order to */ + /* subdivise Bezier arcs in halves by simple additions and shifts. */ + /* */ + /* Note that this is an 8-bytes integer on 64 bits systems. */ + /* */ + typedef long TPos, *PPos; + + + /*************************************************************************/ + /* */ + /* The type of a scanline position/coordinate within a map. */ + /* */ + typedef int TScan, *PScan; + + + /*************************************************************************/ + /* */ + /* States and directions of each line, arc, and profile. */ + /* */ + typedef enum _TDirection + { + Unknown, + Ascending, + Descending, + Flat + + } TDirection; + + + struct _TProfile; + typedef struct _TProfile TProfile; + typedef TProfile* PProfile; + + + /*************************************************************************/ + /* */ + /* The `master' structure used for decomposing outlines. */ + /* */ + struct _TProfile + { + TPos X; /* current coordinate during sweep */ + PProfile link; /* link to next profile - various purpose */ + PPos offset; /* start of profile's data in render pool */ + int flow; /* Profile orientation: Asc/Descending */ + TScan height; /* profile's height in scanlines */ + TScan start; /* profile's starting scanline */ + + TScan 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; + + + /*************************************************************************/ + /* */ + /* A simple record used to implement a stack of bands, required by the */ + /* sub-banding mechanism. */ + /* */ + typedef struct _TBand + { + TScan y_min; /* band's minimum */ + TScan y_max; /* band's maximum */ + + } TBand; + + + /*************************************************************************/ + /* */ + /* The size in _TPos_ of a profile record in the render pool. */ + /* */ +#define AlignProfileSize \ + ( (sizeof ( TProfile ) + sizeof ( TPos ) - 1) / sizeof ( TPos ) ) + + + /*************************************************************************/ + /* */ + /* Prototypes used for sweep function dispatch. */ + /* */ + typedef void (*Function_Sweep_Init)( RAS_ARG_ int* min, + int* max ); + + typedef void (*Function_Sweep_Span)( RAS_ARG_ TScan y, + TPos x1, + TPos x2 ); + + typedef int (*Function_Test_Pixel)( RAS_ARG_ TScan y, + int x ); + + typedef void (*Function_Set_Pixel)( RAS_ARG_ TScan y, + int x, + int color ); + + typedef void (*Function_Sweep_Step)( RAS_ARG ); + + typedef struct Raster_Render_ + { + Function_Sweep_Init init; + Function_Sweep_Span span; + Function_Sweep_Step step; + Function_Test_Pixel test_pixel; + Function_Set_Pixel set_pixel; + + } Raster_Render; + + + /*************************************************************************/ + /* */ + /* Compute lowest integer coordinate below a given value. */ + /* */ +#define FLOOR( x ) ( (x) & ras.precision_mask ) + + + /*************************************************************************/ + /* */ + /* Compute highest integer coordinate above a given value. */ + /* */ +#define CEILING( x ) ( ((x) + ras.precision - 1) & ras.precision_mask ) + + + /*************************************************************************/ + /* */ + /* Get integer coordinate of a given 26.6 or 22.10 `x' coordinate -- no */ + /* rounding. */ + /* */ +#define TRUNC( x ) ( (signed long)(x) >> ras.precision_bits ) + + + /*************************************************************************/ + /* */ + /* Get the fractional part of a given coordinate. */ + /* */ +#define FRAC( x ) ( (x) & (ras.precision - 1) ) + + + /*************************************************************************/ + /* */ + /* Scale an `input coordinate' (as found in FT_Outline structures) into */ + /* a `work coordinate' which depends on current resolution and render */ + /* mode. */ + /* */ +#define SCALED( x ) ( ((x) << ras.scale_shift) - ras.scale_delta ) + + + /*************************************************************************/ + /* */ + /* DEBUG_PSET is used to plot a single pixel in VRam during debug mode. */ + /* */ +#ifdef DEBUG_RASTER +#define DEBUG_PSET Pset() +#else +#define DEBUG_PSET +#endif + + + /*************************************************************************/ + /* */ + /* This structure defines a point in a plane. */ + /* */ + typedef struct _TPoint + { + TPos x, y; + + } TPoint; + + + /*************************************************************************/ + /* */ + /* The most used variables are at the beginning of the structure. Thus, */ + /* their offset can be coded with less opcodes which results in a */ + /* smaller executable. */ + /* */ + struct FT_RasterRec_ + { + PPos cursor; /* Current cursor in render pool */ + + PPos pool; /* The render pool base address */ + PPos pool_size; /* The render pool's size */ + PPos pool_limit; /* Limit of profiles zone in pool */ + + int bit_width; /* target bitmap width */ + PByte bit_buffer; /* target bitmap buffer */ + PByte pix_buffer; /* target pixmap buffer */ + + TPoint last; + long minY, maxY; + + int error; + + int precision_bits; /* precision related variables */ + int precision; + int precision_half; + long precision_mask; + int precision_shift; + int precision_step; + int precision_jitter; + + FT_Outline* outline; + + int n_points; /* number of points in current glyph */ + int n_contours; /* number of contours in current glyph */ + int n_extrema; /* number of `extrema' scanlines */ + + TPoint* arc; /* current Bezier arc pointer */ + + int num_profs; /* current number of profiles */ + + char fresh; /* signals a fresh new profile which */ + /* `start' field must be completed */ + char joint; /* signals that the last arc ended */ + /* exactly on a scanline. Allows */ + /* removal of doublets */ + PProfile cur_prof; /* current profile */ + PProfile start_prof; /* head of linked list of profiles */ + PProfile first_prof; /* contour's first profile in case */ + /* of impact */ + TDirection state; /* rendering state */ + + FT_Bitmap target; /* description of target bit/pixmap */ + + int trace_bit; /* current offset in target bitmap */ + int trace_pix; /* current offset in target pixmap */ + int trace_incr; /* sweep's increment in target bitmap */ + + int gray_min_x; /* current min x during gray rendering */ + int gray_max_x; /* current max x during gray rendering */ + + /* dispatch variables */ + + Raster_Render render; + + int scale_shift; /* == 0 for bitmaps */ + /* == 1 for 5-levels pixmaps */ + /* == 2 for 17-levels pixmaps */ + + int scale_delta; /* ras.precision_half for bitmaps */ + /* 0 for pixmaps */ + + char dropout_mode; /* current drop_out control method */ + + char second_pass; /* indicates whether 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. */ + + char flipped; /* this flag is set during the rendering to */ + /* indicate the second pass. */ + + TBand band_stack[16]; /* band stack used for sub-banding */ + int band_top; /* band stack top */ + + TPoint arcs[2 * MaxBezier + 1]; /* The Bezier stack */ + +#if defined( FT_RASTER_OPTION_ANTI_ALIAS ) + + long grays[20]; /* Palette of gray levels used for render */ + + int gray_width; /* length in bytes of the monochrome */ + /* intermediate scanline of gray_lines. */ + /* Each gray pixel takes 2 or 4 bits long */ + + /* The gray_lines must hold 2 lines, thus with size */ + /* in bytes of at least `gray_width*2' */ + + int grays_count; /* number of entries in the palette */ + + char gray_lines[ANTI_ALIAS_BUFFER_SIZE]; + /* Intermediate table used to render the */ + /* graylevels pixmaps. */ + /* gray_lines is a buffer holding 2 or 4 */ + /* monochrome scanlines */ + + int count_table[256]; /* Look-up table used to quickly count */ + /* set bits in several gray 2x2 cells */ + /* at once. */ + +#endif /* FT_RASTER_OPTION_ANTI_ALIAS */ + }; + + + +#ifdef DEBUG_RASTER + + /*************************************************************************/ + /* */ + /* */ + /* Pset */ + /* */ + /* */ + /* Used for debugging only. Plots a point in VRAM during rendering */ + /* (not afterwards). */ + /* */ + /* */ + /* This procedure relies on the value of cProfile->start, which may */ + /* not be set when Pset() is called sometimes. This will usually */ + /* result in a dot plotted on the first screen scanline (far away */ + /* from its original position). */ + /* */ + /* This `feature' reflects nothing wrong in the current */ + /* implementation, and the bitmap is rendered correctly, so don't */ + /* panic if you see `flying' dots in debugging mode. */ + /* */ + static + void Pset( RAS_ARG ) + { + long o; + long x; + + + x = ras.cursor[-1]; + + switch ( ras.cur_prof->flow ) + { + case FT_Flow_Up: + o = Vio_ScanLineWidth * + ( ras.cursor - ras.cur_prof->offset + ras.cur_prof->start ) + + ( x / (ras.precision * 8) ); + break; + + case FT_Flow_Down: + o = Vio_ScanLineWidth * + ( ras.cur_prof->start - ras.cursor + ras.cur_prof->offset ) + + ( x / (ras.precision * 8) ); + break; + } + + if ( o > 0 ) + Vio[o] |= (unsigned)0x80 >> ( (x/ras.precision) & 7 ); + } + + + static + void Clear_Band( RAS_ARG_ TScan y1, + TScan y2 ) + { + MEM_Set( Vio + y1*Vio_ScanLineWidth, (y2-y1+1)*Vio_ScanLineWidth, 0 ); + } + +#endif /* DEBUG_RASTER */ + + + /*************************************************************************/ + /* */ + /* */ + /* Set_High_Precision */ + /* */ + /* */ + /* Sets precision variables according to the parameter flag. */ + /* */ + /* */ + /* High :: Set to True for high precision (typically for ppem < 18), */ + /* false otherwise. */ + /* */ + static + void Set_High_Precision( RAS_ARG_ char 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; + } + + ras.precision = 1 << ras.precision_bits; + ras.precision_half = ras.precision / 2; + ras.precision_shift = ras.precision_bits - Pixel_Bits; + ras.precision_mask = -ras.precision; + } + + /*************************************************************************/ + /* */ + /* A simple technical note on how the raster works: */ + /* */ + /* Converting an outline into a bitmap is achieved in several steps */ + /* which are: */ + /* */ + /* 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 wether is 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. Additionaly, 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 cursor */ + /* */ + /* The top of the profile stack is kept in the `cursor' 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 `extrema' 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 | */ + /* _ _ __________________|____________________| */ + /* */ + /* ^ ^ */ + /* | | */ + /* pool_limit end of render 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. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* New_Profile */ + /* */ + /* */ + /* Creates a new Profile in the render pool. */ + /* */ + /* */ + /* aState :: The state/orientation of the new profile. */ + /* */ + /* */ + /* SUCCESS or FAILURE. */ + /* */ + static + TResult New_Profile( RAS_ARG_ TDirection direction ) + { + if ( ras.start_prof == NULL ) + { + ras.cur_prof = (PProfile)ras.cursor; /* current profile */ + ras.start_prof = ras.cur_prof; /* first profile in pool */ + ras.cursor += AlignProfileSize; /* record profile in buffer */ + } + + /* check for overflow */ + if ( ras.cursor >= ras.pool_limit ) + { + ras.error = ErrRaster_Overflow; + return FAILURE; + } + + /* record profile direction */ + switch ( direction ) + { + case Ascending: + ras.cur_prof->flow = Flow_Up; + break; + + case Descending: + ras.cur_prof->flow = Flow_Down; + break; + + default: + ras.error = ErrRaster_Invalid_Map; + return FAILURE; + } + + /* initialize a few fields */ + { + PProfile cur = ras.cur_prof; + + + cur->start = 0; /* current start scanline */ + cur->height = 0; /* current height */ + cur->offset = ras.cursor; /* address of first coordinate */ + cur->link = (PProfile)0; /* link to next profile in pool */ + cur->next = (PProfile)0; /* link to next profile in contour */ + } + + /* record the first profile in a contour */ + if ( ras.first_prof == NULL ) + ras.first_prof = ras.cur_prof; + + ras.state = direction; + ras.fresh = TRUE; /* this profile has no coordinates yet */ + ras.joint = FALSE; + + return SUCCESS; + } + + + /*************************************************************************/ + /* */ + /* */ + /* End_Profile */ + /* */ + /* */ + /* Finalizes the current Profile and computes its height. If it is */ + /* not 0, the profile's fields are updated and a new profile is */ + /* pushed on top of its coordinates. Otherwise the current profile */ + /* is kept and the recording of intersections is restarted. */ + /* */ + /* */ + /* SUCCESS or FAILURE. */ + /* */ + static + TResult End_Profile( RAS_ARG ) + { + int h; + + + h = ras.cursor - ras.cur_prof->offset; + + if ( h < 0 ) + { + /* This error should _never_ occur unless the raster is buggy */ + ras.error = ErrRaster_Negative_Height; + return FAILURE; + } + + if ( h > 0 ) + { + PProfile old, new; + + /* record scanline height in current profile, create a new one */ + /* and set a link from the old one to it */ + old = ras.cur_prof; + old->height = h; + ras.cur_prof = new = (PProfile)ras.cursor; + + ras.cursor += AlignProfileSize; + + new->height = 0; + new->offset = ras.cursor; + old->next = new; + + ras.num_profs++; + } + + /* check for overflow */ + if ( ras.cursor >= ras.pool_limit ) + { + ras.error = ErrRaster_Overflow; + return FAILURE; + } + + ras.joint = FALSE; + + return SUCCESS; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Insert_Extrema */ + /* */ + /* */ + /* Records that a given scanline contains at least one local */ + /* extremum. The table of extrema is placed at the end of the render */ + /* pool and grows downwards. It is used during the sweep phase. */ + /* */ + /* */ + /* y :: The coordinate of the scanline containing an extremum. */ + /* */ + static + TResult Insert_Extrema( RAS_ARG_ TScan y ) + { + PPos extrema; + TScan y2; + int n; + + + PTRACE2(( "EXTREMA += %d", y )); + n = ras.n_extrema - 1; + extrema = ras.pool_size - ras.n_extrema; + + /* look for first y extremum that is <= */ + while ( n >= 0 && y < extrema[n] ) + n--; + + /* if it is <, simply insert it, ignore if == */ + if ( n >= 0 && y > extrema[n] ) + while ( n >= 0 ) + { + y2 = extrema[n]; + extrema[n] = y; + y = y2; + n--; + } + + if ( n < 0 ) + { + ras.pool_limit--; + ras.n_extrema++; + ras.pool_size[-ras.n_extrema] = y; + + if ( ras.pool_limit <= ras.cursor ) + { + ras.error = ErrRaster_Overflow; + return FAILURE; + } + } + return SUCCESS; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Finalize_Profile_Table */ + /* */ + /* */ + /* Adjusts all links in the profiles list. Called when the outline */ + /* parsing is done. */ + /* */ + /* */ + /* SUCCESS or FAILURE. */ + /* */ + static + TResult Finalize_Profile_Table( RAS_ARG ) + { + int n, bottom, top; + PProfile p; + + + n = ras.num_profs; + + if ( n > 1 ) + { + p = ras.start_prof; + while ( n > 0 ) + { + if ( n > 1 ) + p->link = (PProfile)( p->offset + p->height ); + else + p->link = NULL; + + switch ( p->flow ) + { + case Flow_Down: + PTRACE2(( "FLOW DOWN (start = %d, height = %d)", + p->start, p->height )); + bottom = p->start - p->height+1; + top = p->start; + p->start = bottom; + p->offset += p->height-1; + break; + + case Flow_Up: + default: + PTRACE2(( "FLOW UP (start = %d, height = %d)", + p->start, p->height )); + bottom = p->start; + top = p->start + p->height-1; + } + + if ( Insert_Extrema( RAS_VAR_ bottom ) || + Insert_Extrema( RAS_VAR_ top+1 ) ) + return FAILURE; + + p = p->link; + n--; + } + } + else + ras.start_prof = NULL; + + return SUCCESS; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Line_Up */ + /* */ + /* */ + /* Computes the scan-line intersections of an ascending line segment */ + /* and stores them in the render pool. */ + /* */ + /* */ + /* x1 :: The start x coordinate. */ + /* y1 :: The start y coordinate. */ + /* x2 :: The end x coordinate. */ + /* y2 :: The end y coordinate. */ + /* miny :: The minimum vertical grid coordinate. */ + /* maxy :: The maximum vertical grid coordinate. */ + /* */ + /* */ + /* SUCCESS or FAILURE. */ + /* */ + static + TResult Line_Up( RAS_ARG_ TPos x1, TPos y1, + TPos x2, TPos y2, + TPos miny, TPos maxy ) + { + TPos Dx, Dy; + int e1, e2, f1, f2, size; + TPos Ix, Rx, Ax; + + PPos top; + + + Dx = x2 - x1; + Dy = y2 - y1; + + if ( Dy <= 0 || y2 < miny || y1 > maxy ) + return SUCCESS; + + /* clip to higher scanline when necessary */ + if ( y2 > maxy ) + { + /* x2 += FMulDiv( Dx, maxy-y2, Dy ); UNNECESSARY */ + e2 = TRUNC( maxy ); + f2 = 0; + } + else + { + e2 = TRUNC( y2 ); + f2 = FRAC( y2 ); + } + + /* clip to lower scanline when necessary */ + if ( y1 < miny ) + { + TPos x, y; + + /* we use a binary search to compute the lower + // clipping intersection. That's because we don't + // want to use an external function like FT_MulDiv + // to compute it directly. + */ + if ( y2 == miny ) goto Exit; + do + { + x = (x1 + x2) >> 1; + y = (y1 + y2) >> 1; + + if (y <= miny) + { + x1 = x; + y1 = y; + } + else + { + x2 = x; + y2 = y; + } + } + while ( y1 < miny ); + + e1 = TRUNC( miny ); + f1 = 0; + } + else + { + e1 = TRUNC( y1 ); + f1 = FRAC( y1 ); + } + + /* adjust start point so that we begin on an integer scanline position */ + if ( f1 > 0 ) + { + if ( e1 == e2 ) goto Exit; + else + { + x1 += FMulDiv( Dx, ras.precision - f1, Dy ); + e1 += 1; + } + } + else + if ( ras.joint ) + { + ras.cursor--; + ras.joint = FALSE; + } + + ras.joint = ( f2 == 0 ); + + /* if this is a `fresh' profile, record its starting scanline */ + if ( ras.fresh ) + { + ras.cur_prof->start = e1; + ras.fresh = FALSE; + } + + /* check for overflow */ + size = e2 - e1 + 1; + if ( ras.cursor + size >= ras.pool_limit ) + { + ras.error = ErrRaster_Overflow; + return FAILURE; + } + + /* compute decision variables and push the intersections on top */ + /* of the render pool */ + Dx <<= ras.precision_bits; + Ix = Dx / Dy; + Rx = Dx % Dy; + if (Rx < 0) + { + Ix --; + Rx += Dy; + } + + Ax = -Dy; + Rx <<= 1; + Dy <<= 1; + + top = ras.cursor; + + while ( size > 0 ) + { + *top++ = x1; + + DEBUG_PSET; + + x1 += Ix; + Ax += Rx; + if ( Ax >= 0 ) + { + Ax -= Dy; + x1 ++; + } + size--; + } + + ras.cursor = top; + Exit: + return SUCCESS; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Line_Down */ + /* */ + /* */ + /* Computes the scan-line intersections of a descending line segment */ + /* and stores them in the render pool. */ + /* */ + /* */ + /* x1 :: The start x coordinate. */ + /* y1 :: The start y coordinate. */ + /* x2 :: The end x coordinate. */ + /* y2 :: The end y coordinate. */ + /* miny :: The minimum vertical grid coordinate. */ + /* maxy :: The maximum vertical grid coordinate. */ + /* */ + /* */ + /* SUCCESS or FAILURE. */ + /* */ + static + TResult Line_Down( RAS_ARG_ TPos x1, TPos y1, + TPos x2, TPos y2, + TPos miny, TPos maxy ) + { + TResult result, fresh; + + + /* simply invert the coordinates and call Line_Up */ + fresh = ras.fresh; + result = Line_Up( RAS_VAR_ x1, -y1, x2, -y2, -maxy, -miny ); + + /* if this was a fresh profile, invert the recorded start position */ + if ( fresh && !ras.fresh ) + ras.cur_prof->start = -ras.cur_prof->start; + + return result; + } + + + + + /* A function type describing the functions used to split bezier arcs */ + typedef void (*TSplitter)( TPoint* base ); + + /*************************************************************************/ + /* */ + /* */ + /* Bezier_Up */ + /* */ + /* */ + /* Computes the scan-line intersections of an ascending second-order */ + /* Bezier arc and stores them in the render pool. The arc is taken */ + /* from the top of the stack. */ + /* */ + /* */ + /* miny :: The minimum vertical grid coordinate. */ + /* maxy :: The maximum vertical grid coordinate. */ + /* */ + /* */ + /* SUCCESS or FAILURE. */ + /* */ + static + TResult Bezier_Up( RAS_ARG_ int degree, + TSplitter splitter, + TPos miny, + TPos maxy ) + { + TPos y1, y2, e, e2, e0; + int f1; + + TPoint* arc; + TPoint* start_arc; + + PPos top; + + + arc = ras.arc; + y1 = arc[degree].y; + y2 = arc[0].y; + top = ras.cursor; + + if ( y2 < miny || y1 > maxy ) + goto Fin; + + e2 = FLOOR( y2 ); /* integer end y */ + + if ( e2 > maxy ) + e2 = FLOOR(maxy); + + e0 = CEILING(miny); + + if ( y1 < miny ) + { + e = e0; /* integer start y == current scanline */ + } + else + { + e = CEILING( y1 ); /* integer start y == current scanline */ + f1 = FRAC( y1 ); /* fractional shift of start y */ + e0 = e; /* first integer scanline to be pushed */ + + if ( f1 == 0 ) /* do we start on an integer scanline? */ + { + if ( ras.joint ) + { + top--; + ras.joint = FALSE; + } + + *top++ = arc[degree].x; /* write directly start position */ + + DEBUG_PSET; + + e += ras.precision; /* go to next scanline */ + } + } + + /* record start position if necessary */ + if ( ras.fresh ) + { + ras.cur_prof->start = TRUNC( e0 ); + ras.fresh = FALSE; + } + + /* exit if the current scanline is already above the max scanline */ + if ( e2 < e ) + goto Fin; + + /* check for overflow */ + if ( ( top + TRUNC( e2 - e ) + 1 ) >= ras.pool_limit ) + { + ras.cursor = top; + ras.error = ErrRaster_Overflow; + return FAILURE; + } + + start_arc = arc; + + /* loop while there is still an arc on the bezier stack */ + /* and the current scan line is below y max == e2 */ + while ( arc >= start_arc && e <= e2 ) + { + ras.joint = FALSE; + + y2 = arc[0].y; /* final y of the top-most arc */ + + if ( y2 > e ) /* the arc intercepts the current scanline */ + { + y1 = arc[degree].y; /* start y of top-most arc */ + + if ( y2 - y1 >= ras.precision_step ) + { + /* if the arc's height is too great, split it */ + splitter( arc ); + arc += degree; + } + else + { + /* otherwise, approximate it as a segment and compute */ + /* its intersection with the current scanline */ + *top++ = arc[degree].x + + FMulDiv( arc[0].x-arc[degree].x, + e - y1, + y2 - y1 ); + + DEBUG_PSET; + + arc -= degree; /* pop the arc */ + e += ras.precision; /* go to next scanline */ + } + } + else + { + if ( y2 == e ) /* if the arc falls on the scanline */ + { /* record its _joint_ intersection */ + ras.joint = TRUE; + *top++ = arc[0].x; + + DEBUG_PSET; + + e += ras.precision; /* go to next scanline */ + } + arc -= degree; /* pop the arc */ + } + } + + Fin: + ras.cursor = top; + ras.arc -= degree; + return SUCCESS; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Bezier_Down */ + /* */ + /* */ + /* Computes the scan-line intersections of a descending second-order */ + /* Bezier arc and stores them in the render pool. The arc is taken */ + /* from the top of the stack. */ + /* */ + /* */ + /* miny :: The minimum vertical grid coordinate. */ + /* maxy :: The maximum vertical grid coordinate. */ + /* */ + /* */ + /* SUCCESS or FAILURE. */ + /* */ + static + TResult Bezier_Down( RAS_ARG_ int degree, + TSplitter splitter, + TPos miny, + TPos maxy ) + { + TPoint* arc = ras.arc; + TResult 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_VAR_ degree, splitter, -maxy, -miny ); + + if ( fresh && !ras.fresh ) + ras.cur_prof->start = -ras.cur_prof->start; + + arc[0].y = -arc[0].y; + return result; + } + + +#ifdef FT_RASTER_CONIC_BEZIERS + + /*************************************************************************/ + /* */ + /* */ + /* Split_Conic */ + /* */ + /* */ + /* Subdivides one second-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_Conic( TPoint* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Push_Conic */ + /* */ + /* */ + /* Clears the Bezier stack and pushes a new arc on top of it. */ + /* */ + /* */ + /* p2 :: A pointer to the second (control) point. */ + /* p3 :: A pointer to the third (end) point. */ + /* */ + /* */ + /* The first point is taken as `raster->last', so it doesn't appear */ + /* in the signature. */ + /* */ + static + void Push_Conic( RAS_ARG_ FT_Vector* p2, + FT_Vector* p3 ) + { +#undef STORE +#define STORE( _arc, point ) \ + { \ + TPos x = SCALED( point->x ); \ + TPos y = SCALED( point->y ); \ + \ + \ + if ( ras.flipped ) \ + { \ + _arc.x = y; \ + _arc.y = x; \ + } \ + else \ + { \ + _arc.x = x; \ + _arc.y = y; \ + } \ + } + + TPoint* arc; + + + ras.arc = arc = ras.arcs; + + arc[2] = ras.last; + STORE( arc[1], p2 ); + STORE( arc[0], p3 ); +#undef STORE + } + +#endif /* FT_RASTER_CONIC_BEZIERS */ + + + +#ifdef FT_RASTER_CUBIC_BEZIERS + + /*************************************************************************/ + /* */ + /* 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 ) + { + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Push_Cubic */ + /* */ + /* */ + /* Clears the Bezier stack and pushes a new third-order Bezier arc on */ + /* top of it. */ + /* */ + /* */ + /* p2 :: A pointer to the second (control) point. */ + /* p3 :: A pointer to the third (control) point. */ + /* p4 :: A pointer to the fourth (end) point. */ + /* */ + /* */ + /* The first point is taken as `raster->last', so it doesn't appear */ + /* in the signature. */ + /* */ + /* This is the same as Push_Conic(), except that it deals with */ + /* third-order Beziers. */ + /* */ + static + void Push_Cubic( RAS_ARG_ FT_Vector* p2, + FT_Vector* p3, + FT_Vector* p4 ) + { +#undef STORE +#define STORE( _arc, point ) \ + { \ + TPos x = SCALED( point->x ); \ + TPos y = SCALED( point->y ); \ + \ + \ + if ( ras.flipped ) \ + { \ + _arc.x = y; \ + _arc.y = x; \ + } \ + else \ + { \ + _arc.x = x; \ + _arc.y = y; \ + } \ + } + + TPoint* arc; + ras.arc = arc = ras.arcs; + + + arc[3] = ras.last; + STORE( arc[2], p2 ); + STORE( arc[1], p3 ); + STORE( arc[0], p4 ); + +#undef STORE + } + +#endif /* FT_RASTER_CUBIC_BEZIERS */ + + + /*************************************************************************/ + /* */ + /* */ + /* Check_Contour */ + /* */ + /* */ + /* Performs some checks at contour closure. */ + /* */ + /* */ + /* SUCCESS or FAILURE. */ + /* */ + static + TResult Check_Contour( RAS_ARG ) + { + PProfile lastProfile; + + + /* Sometimes, the first and last profile in a contour join on */ + /* an integer scan-line; we must then remove the last intersection */ + /* from the last profile to get rid of doublets */ + if ( ( FRAC( ras.last.y ) == 0 && + ras.last.y >= ras.minY && + ras.last.y <= ras.maxY ) ) + { + if ( ras.first_prof && ras.first_prof->flow == ras.cur_prof->flow ) + ras.cursor--; + } + + lastProfile = ras.cur_prof; + if ( End_Profile( RAS_VAR ) ) + return FAILURE; + + /* close the `next profile in contour' linked list */ + lastProfile->next = ras.first_prof; + + return SUCCESS; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Move_To */ + /* */ + /* */ + /* This function injects a new contour in the render pool. */ + /* */ + /* */ + /* to :: A pointer to the contour's first point. */ + /* raster :: A pointer to the current raster object. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + /* */ + /* This function is used as a `FTRasterMoveTo_Func' by the outline */ + /* decomposer. */ + /* */ + static + int Move_To( FT_Vector* to, + FT_Raster raster ) + { + TPos scaled_x, scaled_y; + + + /* if there was already a contour being built, perform some checks */ + if ( ras.start_prof ) + if ( Check_Contour( RAS_VAR ) ) + return FAILURE; + + /* set the `current last point' */ + scaled_x = SCALED( to->x ); + scaled_y = SCALED( to->y ); + + if ( ras.flipped ) + { + ras.last.x = scaled_y; + ras.last.y = scaled_x; + } + else + { + ras.last.x = scaled_x; + ras.last.y = scaled_y; + } + + ras.state = Unknown; + ras.first_prof = NULL; + + return SUCCESS; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Line_To */ + /* */ + /* */ + /* This function injects a new line segment in the render pool and */ + /* adjusts the profiles list accordingly. */ + /* */ + /* */ + /* to :: A pointer to the target position. */ + /* raster :: A pointer to the current raster object. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + /* */ + /* This function is used as a `FTRasterLineTo_Func' by the outline */ + /* decomposer. */ + /* */ + static + int Line_To( FT_Vector* to, + FT_Raster raster ) + { + TPos x, scaled_x; + TPos y, scaled_y; + + + scaled_x = SCALED( to->x ); + scaled_y = SCALED( to->y ); + + if ( ras.flipped ) + { + x = scaled_y; + y = scaled_x; + } + else + { + x = scaled_x; + y = scaled_y; + } + + /* First, detect a change of direction */ + if ( y != ras.last.y ) + { + TDirection new_state = ( (y > ras.last.y) ? Ascending : Descending ); + + + if ( ras.state != new_state ) + { + if ( ras.state != Unknown && + End_Profile( RAS_VAR ) ) + goto Fail; + + if ( New_Profile( RAS_VAR_ new_state ) ) + goto Fail; + } + } + + /* Then compute the lines */ + switch ( ras.state ) + { + case Ascending: + if ( Line_Up ( RAS_VAR_ ras.last.x, ras.last.y, + x, y, ras.minY, ras.maxY ) ) + goto Fail; + break; + + case Descending: + if ( Line_Down( RAS_VAR_ ras.last.x, ras.last.y, + x, y, ras.minY, ras.maxY ) ) + goto Fail; + break; + + default: + ; + } + + ras.last.x = x; + ras.last.y = y; + + return SUCCESS; + + Fail: + return FAILURE; + } + + +#ifdef FT_RASTER_CONIC_BEZIERS + + + /*************************************************************************/ + /* */ + /* */ + /* Conic_To */ + /* */ + /* */ + /* Injects a new conic Bezier arc and adjusts the profile list */ + /* accordingly. */ + /* */ + /* */ + /* control :: A pointer to an intermediate control point. */ + /* to :: A pointer to the end point. */ + /* raster :: A handle to the current raster object. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + /* */ + /* This function is used as a `FTRasterConicTo_Func' by the outline */ + /* decomposer. */ + /* */ + static + int Conic_To( FT_Vector* control, + FT_Vector* to, + FT_Raster raster ) + { + TPos y1, y2, y3, x3, ymin, ymax; + TDirection state_bez; + + + Push_Conic( RAS_VAR_ control, to ); + + 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_VAR_ state_bez ) ) + goto Fail; + } + + /* now call the appropriate routine */ + if ( state_bez == Ascending ) + { + if ( Bezier_Up( RAS_VAR_ 2, Split_Conic, ras.minY, ras.maxY ) ) + goto Fail; + } + else + if ( Bezier_Down( RAS_VAR_ 2, Split_Conic, ras.minY, ras.maxY ) ) + goto Fail; + } + + } while ( ras.arc >= ras.arcs ); + + ras.last.x = x3; + ras.last.y = y3; + + return SUCCESS; + + Fail: + return FAILURE; + } + +#else /* FT_RASTER_CONIC_BEZIERS */ + + + static + int Conic_To( FT_Vector* control, + FT_Vector* to, + FT_Raster raster ) + { + UNUSED( control ); + UNUSED( to ); + UNUSED( raster ); + + return ErrRaster_Invalid_Outline; + } + + +#endif /* FT_RASTER_CONIC_BEZIERS */ + + +#ifdef FT_RASTER_CUBIC_BEZIERS + + + /*************************************************************************/ + /* */ + /* */ + /* Cubic_To */ + /* */ + /* */ + /* Injects a new cubic Bezier arc and adjusts the profile list */ + /* accordingly. */ + /* */ + /* */ + /* control1 :: A pointer to the first control point. */ + /* control2 :: A pointer to the second control point. */ + /* to :: A pointer to the end point. */ + /* raster :: A handle to the current raster object. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + /* */ + /* This function is used as a `FTRasterCubicTo_Func' by the outline */ + /* decomposer. */ + /* */ + static + int Cubic_To( FT_Vector* control1, + FT_Vector* control2, + FT_Vector* to, + FT_Raster raster ) + { + TPos y1, y2, y3, y4, x4, ymin1, ymax1, ymin2, ymax2; + TDirection state_bez; + + + Push_Cubic( RAS_VAR_ control1, control2, to ); + + 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_VAR_ state_bez ) ) + goto Fail; + } + + /* compute intersections */ + if ( state_bez == Ascending ) + { + if ( Bezier_Up ( RAS_VAR_ 3, Split_Cubic, ras.minY, ras.maxY ) ) + goto Fail; + } + else + if ( Bezier_Down ( RAS_VAR_ 3, Split_Cubic, ras.minY, ras.maxY ) ) + goto Fail; + } + + } while ( ras.arc >= ras.arcs ); + + ras.last.x = x4; + ras.last.y = y4; + + return SUCCESS; + + Fail: + return FAILURE; + } + + +#else /* FT_RASTER_CUBIC_BEZIERS */ + + + int Cubic_To( FT_Vector* control1, + FT_Vector* control2, + FT_Vector* to, + FT_Raster raster ) + { + UNUSED( control1 ); + UNUSED( control2 ); + UNUSED( to ); + UNUSED( raster ); + + return ErrRaster_Invalid_Outline; + } + + +#endif /* FT_RASTER_CUBIC_BEZIERS */ + + +/********************************************************************/ +/* */ +/* The following function is compiled in the raster only when it is */ +/* compile as a stand-alone module.. */ + +/* It can, otherwise, be found in the FreeType base layer */ + +#ifdef _STANDALONE_ + /*************************************************************************/ + /* */ + /* */ + /* FT_Decompose_Outline */ + /* */ + /* */ + /* 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. */ + /* */ + +#if 0 + typedef int (*FTRasterMoveTo_Func)( FT_Vector* to, + void* user ); + + typedef int (*FTRasterLineTo_Func)( FT_Vector* to, + void* user ); + + typedef int (*FTRasterConicTo_Func)( FT_Vector* control, + FT_Vector* to, + void* user ); + + typedef int (*FTRasterCubicTo_Func)( FT_Vector* control1, + FT_Vector* control2, + FT_Vector* to, + void* user ); + + typedef struct FT_Raster_Funcs_ + { + FTRasterMoveTo_Func move_to; + FTRasterLineTo_Func line_to; + FTRasterConicTo_Func conic_to; + FTRasterCubicTo_Func cubic_to; + + } FT_Raster_Funcs; +#endif + + int FT_Decompose_Outline( FT_Outline* outline, + FT_Raster_Funcs* interface, + void* user ) + { + typedef enum _phases + { + phase_point, + phase_conic, + phase_cubic, + phase_cubic2 + + } TPhase; + + FT_Vector v_first; + FT_Vector v_last; + FT_Vector v_control; + FT_Vector v_control2; + FT_Vector v_start; + + FT_Vector* point; + PByte flags; + + int n; /* index of contour in outline */ + int first; /* index of first point in contour */ + int index; /* current point's index */ + + int error; + + char tag; /* current point's state */ + TPhase phase; + + + first = 0; + + for ( n = 0; n < outline->n_contours; n++ ) + { + int last; /* index of last point in contour */ + + + last = outline->contours[n]; + + v_first = outline->points[first]; + v_last = outline->points[last]; + + v_start = v_control = v_first; + + tag = FT_CURVE_TAG( outline->flags[first] ); + index = first; + + /* A contour cannot start with a cubic control point! */ + + if ( tag == FT_Curve_Tag_Cubic ) + return ErrRaster_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->flags[last] ) == FT_Curve_Tag_On ) + { + /* start at last point if it is on the curve */ + v_start = v_last; + } + 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; + } + phase = phase_conic; + } + else + phase = phase_point; + + + /* Begin a new contour with MOVE_TO */ + + error = interface->move_to( &v_start, user ); + if ( error ) + return error; + + point = outline->points + first; + flags = outline->flags + first; + + /* now process each contour point individually */ + + while ( index < last ) + { + index++; + point++; + flags++; + + tag = FT_CURVE_TAG( flags[0] ); + + switch ( phase ) + { + case phase_point: /* the previous point was on the curve */ + + switch ( tag ) + { + /* two succesive on points -> emit segment */ + case FT_Curve_Tag_On: + error = interface->line_to( point, user ); + break; + + /* on point + conic control -> remember control point */ + case FT_Curve_Tag_Conic: + v_control = point[0]; + phase = phase_conic; + break; + + /* on point + cubic control -> remember first control */ + default: + v_control = point[0]; + phase = phase_cubic; + break; + } + break; + + case phase_conic: /* the previous point was a conic control */ + + switch ( tag ) + { + /* conic control + on point -> emit conic arc */ + case FT_Curve_Tag_On: + error = interface->conic_to( &v_control, point, user ); + phase = phase_point; + break; + + /* two successive conics -> emit conic arc `in between' */ + case FT_Curve_Tag_Conic: + { + FT_Vector v_middle; + + + v_middle.x = (v_control.x + point->x)/2; + v_middle.y = (v_control.y + point->y)/2; + + error = interface->conic_to( &v_control, + &v_middle, user ); + v_control = point[0]; + } + break; + + default: + error = ErrRaster_Invalid_Outline; + } + break; + + case phase_cubic: /* the previous point was a cubic control */ + + /* this point _must_ be a cubic control too */ + if ( tag != FT_Curve_Tag_Cubic ) + return ErrRaster_Invalid_Outline; + + v_control2 = point[0]; + phase = phase_cubic2; + break; + + + case phase_cubic2: /* the two previous points were cubics */ + + /* this point _must_ be an on point */ + if ( tag != FT_Curve_Tag_On ) + error = ErrRaster_Invalid_Outline; + else + error = interface->cubic_to( &v_control, &v_control2, + point, user ); + phase = phase_point; + break; + } + + /* lazy error testing */ + if ( error ) + return error; + } + + /* end of contour, close curve cleanly */ + error = 0; + + tag = FT_CURVE_TAG( outline->flags[first] ); + + switch ( phase ) + { + case phase_point: + if ( tag == FT_Curve_Tag_On ) + error = interface->line_to( &v_first, user ); + break; + + case phase_conic: + error = interface->conic_to( &v_control, &v_start, user ); + break; + + case phase_cubic2: + if ( tag == FT_Curve_Tag_On ) + error = interface->cubic_to( &v_control, &v_control2, + &v_first, user ); + else + error = ErrRaster_Invalid_Outline; + break; + + default: + error = ErrRaster_Invalid_Outline; + break; + } + + if ( error ) + return error; + + first = last + 1; + } + + return SUCCESS; + } +#endif + + /*************************************************************************/ + /* */ + /* */ + /* Convert_Glyph */ + /* */ + /* */ + /* Converts a glyph into a series of segments and arcs and makes a */ + /* profiles list with them. */ + /* */ + /* */ + /* outline :: The glyph outline. */ + /* */ + /* */ + /* SUCCESS or FAILURE. */ + /* */ + static + TResult 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 + }; + + /* Set up state in the raster object */ + ras.start_prof = NULL; + ras.joint = FALSE; + ras.fresh = FALSE; + + ras.pool_limit = ras.pool_size - AlignProfileSize; + + ras.n_extrema = 0; + + ras.cur_prof = (PProfile)ras.cursor; + ras.cur_prof->offset = ras.cursor; + ras.num_profs = 0; + + /* Now decompose curve */ + if ( FT_Decompose_Outline( outline, &interface, &ras ) ) + return FAILURE; + /* XXX: the error condition is in ras.error */ + + /* Check the last contour if needed */ + if ( Check_Contour( RAS_VAR ) ) + return FAILURE; + + /* Finalize profiles list */ + return Finalize_Profile_Table( RAS_VAR ); + } + + + /*************************************************************************/ + /* */ + /* Init_Linked */ + /* */ + /* Inits 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; + TPos 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 reach this place, unless the Profile was not */ + /* part of the list. */ + } + + + /*************************************************************************/ + /* */ + /* Update */ + /* */ + /* Updates 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 to implement. */ + /* */ + 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 Bitmap Sweep Routines ********/ + /******** ********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* Vertical_Sweep_Init */ + /* */ + /* */ + /* Initializes the vertical bitmap sweep. Called by the generic */ + /* sweep/draw routine before its loop. */ + /* */ + /* */ + /* min :: The address of the current minimum scanline. */ + /* max :: The address of the current maximum scanline. */ + /* */ + static + void Vertical_Sweep_Init( RAS_ARG_ int* min, int* max ) + { + long pitch; + + UNUSED( max ); + + pitch = ras.target.pitch; + + /* start from the bottom line, going up !! */ + ras.trace_bit = - *min * pitch; + ras.trace_incr = -pitch; + + if (pitch > 0) + ras.trace_bit += pitch*(ras.target.rows-1); + + ras.gray_min_x = 0; + ras.gray_max_x = 0; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Vertical_Sweep_Span */ + /* */ + /* */ + /* Draws a single horizontal bitmap span during the vertical bitmap */ + /* sweep. */ + /* */ + /* */ + /* y :: The current scanline. */ + /* x1 :: The left span edge. */ + /* x2 :: The right span edge. */ + /* */ + static + void Vertical_Sweep_Span( RAS_ARG_ TScan y, + TPos x1, + TPos x2 ) + { + TPos e1, e2; + int c1, c2; + Byte f1, f2; + PByte target; + + + UNUSED( y ); + + /* Drop-out control */ + + e1 = TRUNC( CEILING( x1 ) ); + if ( x2 - x1 - ras.precision <= ras.precision_jitter ) + e2 = e1; + else + e2 = TRUNC( FLOOR( x2 ) ); + + if ( e1 <= e2 && e2 >= 0 && e1 < ras.bit_width ) + { + if ( e1 < 0 ) e1 = 0; + if ( e2 >= ras.bit_width ) e2 = ras.bit_width - 1; + + c1 = e1 >> 3; + c2 = e2 >> 3; + + f1 = ((unsigned char)0xFF >> (e1 & 7)); + f2 = ~((unsigned char)0x7F >> (e2 & 7)); + +#ifdef FT_RASTER_ANY_ENDIAN + if ( ras.gray_min_x > c1 ) ras.gray_min_x = c1; + if ( ras.gray_max_x < c2 ) ras.gray_max_x = c2; +#endif + + target = ras.bit_buffer + ras.trace_bit + 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 ); + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* Vertical_Test_Pixel */ + /* */ + /* */ + /* Tests a pixel `light' during the vertical bitmap sweep. Used */ + /* during drop-out control only. */ + /* */ + /* */ + /* y :: The current scanline. */ + /* x :: The current x coordinate. */ + /* */ + static + int Vertical_Test_Pixel( RAS_ARG_ TScan y, + int x ) + { + int c1 = x >> 3; + + + UNUSED( y ); + + return ( x >= 0 && x < ras.bit_width && + ras.bit_buffer[ras.trace_bit + c1] & (0x80 >> (x & 7)) ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* Vertical_Set_Pixel */ + /* */ + /* */ + /* Sets a single pixel in a bitmap during the vertical sweep. Used */ + /* during drop-out control. */ + /* */ + /* */ + /* y :: The current scanline. */ + /* x :: The current x coordinate. */ + /* color :: Ignored by this function. */ + /* */ + static + void Vertical_Set_Pixel( RAS_ARG_ int y, + int x, + int color ) + { + UNUSED( color ); + UNUSED( y ); + + if ( x >= 0 && x < ras.bit_width ) + { + int c1 = x >> 3; + + if ( ras.gray_min_x > c1 ) ras.gray_min_x = c1; + if ( ras.gray_max_x < c1 ) ras.gray_max_x = c1; + + ras.bit_buffer[ras.trace_bit+c1] |= (char)(0x80 >> (x & 7)); + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* Vertical_Sweep_Step */ + /* */ + /* */ + /* Called whenever the sweep jumps to another scanline. Only updates */ + /* the pointers in the vertical bitmap sweep. */ + /* */ + static + void Vertical_Sweep_Step( RAS_ARG ) + { + ras.trace_bit += ras.trace_incr; + } + + + static + const Raster_Render vertical_render_mono = + { + &Vertical_Sweep_Init, + &Vertical_Sweep_Span, + &Vertical_Sweep_Step, + &Vertical_Test_Pixel, + &Vertical_Set_Pixel + }; + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /******** ********/ + /******** Horizontal Bitmap Sweep Routines ********/ + /******** ********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* Horizontal_Sweep_Init */ + /* */ + /* */ + /* Initializes the horizontal bitmap sweep. Called by the generic */ + /* sweep/draw routine before its loop. */ + /* */ + /* */ + /* min :: The address of the current minimum pixel column. */ + /* max :: The address of the current maximum pixel column. */ + /* */ + static + void Horizontal_Sweep_Init( RAS_ARG_ int* min, + int* max ) + { + UNUSED( ras ); + UNUSED( min ); + UNUSED( max ); + + /* nothing, really */ + } + + + /*************************************************************************/ + /* */ + /* */ + /* Horizontal_Sweep_Span */ + /* */ + /* */ + /* Draws a single vertical bitmap span during the horizontal bitmap */ + /* sweep. Actually, this function is only used to check for weird */ + /* drop-out cases. */ + /* */ + /* */ + /* y :: The current pixel column. */ + /* x1 :: The top span edge. */ + /* x2 :: The bottom span edge. */ + /* */ + static + void Horizontal_Sweep_Span( RAS_ARG_ TScan y, + TPos x1, + TPos x2 ) + { + TPos e1, e2; + PByte bits; + Byte f1; + + UNUSED( y ); + + /* During the horizontal sweep, we only take care of drop-outs */ + if ( x2 - x1 < ras.precision ) + { + e1 = CEILING( x1 ); + e2 = FLOOR( x2 ); + + if ( e1 == e2 ) + { + bits = ras.bit_buffer + (y >> 3); + f1 = (Byte)(0x80 >> (y & 7)); + + e1 = TRUNC( e1 ); + + if ( e1 >= 0 && e1 < ras.target.rows ) + { + long pitch = ras.target.pitch; + long offset = - pitch * e1; + + if (pitch > 0) + offset += (ras.target.rows-1)*pitch; + + bits[offset] |= f1; + } + } + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* Horizontal_Test_Pixel */ + /* */ + /* */ + /* Tests a pixel `light' during the horizontal bitmap sweep. Used */ + /* during drop-out control only. */ + /* */ + /* */ + /* y :: The current pixel column. */ + /* x :: The current row/scanline. */ + /* */ + static + int Horizontal_Test_Pixel( RAS_ARG_ int y, + int x ) + { + char* bits = (char*)ras.bit_buffer + (y >> 3); + int f1 = (Byte)(0x80 >> (y & 7)); + long pitch = ras.target.pitch; + long offset = - pitch * x; + + if (pitch > 0) + offset += (ras.target.rows-1)*pitch; + + return ( x >= 0 && x < ras.target.rows && (bits[0] & f1) ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* Horizontal_Set_Pixel */ + /* */ + /* */ + /* Sets a single pixel in a bitmap during the horizontal sweep. Used */ + /* during drop-out control. */ + /* */ + /* */ + /* y :: The current pixel column. */ + /* x :: The current row/scanline. */ + /* color :: Ignored by this function. */ + /* */ + static + void Horizontal_Set_Pixel( RAS_ARG_ int y, + int x, + int color ) + { + char* bits = (char*)ras.bit_buffer + (y >> 3); + int f1 = (Byte)(0x80 >> (y & 7)); + + + UNUSED( color ); + + if ( x >= 0 && x < ras.target.rows ) + { + long pitch = ras.target.pitch; + long offset = - x*pitch; + + if (pitch > 0) + offset += (ras.target.rows-1)*pitch; + + bits[offset] |= f1; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* Horizontal_Sweep_Step */ + /* */ + /* */ + /* Called whenever the sweep jumps to another pixel column. */ + /* */ + static + void Horizontal_Sweep_Step( RAS_ARG ) + { + UNUSED( ras.target ); + + /* Nothing, really */ + } + + + static + const Raster_Render horizontal_render_mono = + { + &Horizontal_Sweep_Init, + &Horizontal_Sweep_Span, + &Horizontal_Sweep_Step, + &Horizontal_Test_Pixel, + &Horizontal_Set_Pixel + }; + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /******** ********/ + /******** Anti-Aliased Vertical Bitmap Sweep Routines ********/ + /******** ********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + +#ifdef FT_RASTER_OPTION_ANTI_ALIAS + + /*************************************************************************/ + /* */ + /* */ + /* Vertical_Gray_Sweep_Init */ + /* */ + /* */ + /* Initializes the vertical bitmap sweep. Called by the generic */ + /* sweep/draw routine before its loop. */ + /* */ + /* */ + /* min :: The address of the current minimum scanline. */ + /* max :: The address of the current maximum scanline. */ + /* */ + static + void Vertical_Gray_Sweep_Init( RAS_ARG_ int* min, int* max ) + { + long pitch; + + UNUSED( max ); + + pitch = ras.target.pitch; + + /* start from the bottom line, going up */ + ras.trace_incr = -pitch; + ras.trace_bit = - *min * pitch; + + if (pitch > 0) + ras.trace_bit += (ras.target.rows-1)*pitch; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Vertical_Gray_Sweep_Span */ + /* */ + /* */ + /* Draws a single horizontal bitmap span during the vertical bitmap */ + /* sweep. */ + /* */ + /* */ + /* y :: The current scanline. */ + /* x1 :: The left span edge. */ + /* x2 :: The right span edge. */ + /* */ + static + void Vertical_Gray_Sweep_Span( RAS_ARG_ TScan y, + TPos x1, + TPos x2 ) + { + TPos e1, e2; + int shift = ras.precision_bits - 6; + PByte target; + + + UNUSED( y ); + + x1 += ras.precision_half; + x2 += ras.precision_half; + +#ifdef FT_RASTER_OPTION_CONTRAST + if ( x2-x1 < ras.precision ) + { + x1 = ((x1+x2) >> 1) - ras.precision_half; + x2 = x1 + ras.precision; + } +#endif + + e1 = TRUNC( x1 ); + e2 = TRUNC( x2 ); + + if ( e1 <= e2 && e2 >= 0 && e1 < ras.bit_width ) + { + x1 = FRAC(x1) >> shift; + x2 = FRAC(x2) >> shift; + + if ( e1 < 0 ) + { + e1 = 0; + x1 = 0; + } + + if ( e2 > ras.bit_width ) + { + e2 = ras.bit_width-1; + x2 = 0; + } + + target = ras.bit_buffer + ras.trace_bit + e1; + e2 -= e1; + + if ( e2 > 0 ) + { + target[0] += (Byte)(64-x1); + e2--; + while (e2 > 0) + { + *(++target) += 64; + e2--; + } + if (x2) + target[1] += (Byte)x2; + } + else + { + target[0] += (Byte)(x2-x1); + } + } + } + + /*************************************************************************/ + /* */ + /* */ + /* Vertical_Gray_Test_Pixel */ + /* */ + /* */ + /* Tests a pixel `light' during the vertical bitmap sweep. Used */ + /* during drop-out control only. */ + /* */ + /* */ + /* y :: The current scanline. */ + /* x :: The current x coordinate. */ + /* */ + static + int Vertical_Gray_Test_Pixel( RAS_ARG_ TScan y, + int x ) + { + UNUSED( y ); + +#if 0 + /* as a rule of thumb, do not add a drop-out if the current */ + /* gray level is over 0.5 */ + + return ( x >= 0 && x < ras.bit_width && + ras.bit_buffer[ras.trace_bit + x] >= 64 ); +#else + UNUSED(x); + return 0; +#endif + } + + + /*************************************************************************/ + /* */ + /* */ + /* Vertical_Gray_Set_Pixel */ + /* */ + /* */ + /* Sets a single pixel in a bitmap during the vertical sweep. Used */ + /* during drop-out control. */ + /* */ + /* */ + /* y :: The current scanline. */ + /* x :: The current x coordinate. */ + /* color :: Ignored by this function. */ + /* */ + static + void Vertical_Gray_Set_Pixel( RAS_ARG_ int y, + int x, + int color ) + { + UNUSED( y ); + + if ( x >= 0 && x < ras.bit_width ) + { + unsigned char* pixel; + + pixel = ras.bit_buffer + ras.trace_bit + x; + + /* do not add too much to the pixel gray level */ + color += *pixel; + if (color < 64) + color = 64; + + *pixel = ( color >= 128 ? 128 : (unsigned char)color ); + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* Vertical_Sweep_Step */ + /* */ + /* */ + /* Called whenever the sweep jumps to another scanline. Only updates */ + /* the pointers in the vertical bitmap sweep. */ + /* */ + static + void Vertical_Gray_Sweep_Step( RAS_ARG ) + { + ras.trace_bit += ras.trace_incr; + } + + + + static + const Raster_Render vertical_render_gray = + { + &Vertical_Gray_Sweep_Init, + &Vertical_Gray_Sweep_Span, + &Vertical_Gray_Sweep_Step, + &Vertical_Gray_Test_Pixel, + &Vertical_Gray_Set_Pixel + }; + + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /******** ********/ + /******** Horizontal Bitmap Sweep Routines ********/ + /******** ********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* Horizontal_Sweep_Init */ + /* */ + /* */ + /* Initializes the horizontal bitmap sweep. Called by the generic */ + /* sweep/draw routine before its loop. */ + /* */ + /* */ + /* min :: The address of the current minimum pixel column. */ + /* max :: The address of the current maximum pixel column. */ + /* */ + static + void Horizontal_Gray_Sweep_Init( RAS_ARG_ int* min, + int* max ) + { + UNUSED( ras ); + UNUSED( min ); + UNUSED( max ); + + /* nothing, really */ + } + + + /*************************************************************************/ + /* */ + /* */ + /* Horizontal_Gray_Sweep_Span */ + /* */ + /* */ + /* Draws a single vertical bitmap span during the horizontal bitmap */ + /* sweep. */ + /* */ + /* */ + /* y :: The current scanline. */ + /* x1 :: The left span edge. */ + /* x2 :: The right span edge. */ + /* */ + static + void Horizontal_Gray_Sweep_Span( RAS_ARG_ TScan y, + TPos x1, + TPos x2 ) + { + TPos e1, e2; + int shift = ras.precision_bits - 6; + int incr; + PByte bits; + + + UNUSED( y ); + + x1 += ras.precision_half; + x2 += ras.precision_half; + +#ifdef FT_RASTER_OPTION_CONTRAST + if (x2-x1 < ras.precision) + { + x1 = ((x1+x2) >> 1) - ras.precision_half; + x2 = x1 + ras.precision; + } +#endif + + e1 = TRUNC( x1 ); + e2 = TRUNC( x2 ); + + if ( e1 <= e2 && e2 >= 0 && e1 < ras.bit_width ) + { + x1 = FRAC(x1) >> shift; + x2 = FRAC(x2) >> shift; + + if ( e1 < 0 ) + { + e1 = 0; + x1 = 0; + } + + if ( e2 >= ras.bit_width ) + { + e2 = ras.bit_width; + x2 = 0; + } + + incr = -ras.target.pitch; + bits = ras.bit_buffer + y; + bits += incr * e1; + if (incr < 0) + bits -= incr*(ras.target.rows-1); + + e2 -= e1; + + if ( e2 > 0 ) + { + bits[0] += (Byte)(64-x1); + e2--; + while (e2 > 0) + { + bits += incr; + bits[0] += 64; + e2--; + } + if (x2) + bits[incr] += (Byte)x2; + } + else + { + bits[0] += (Byte)(x2-x1); + } + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* Horizontal_Gray_Test_Pixel */ + /* */ + /* */ + /* Tests a pixel `light' during the horizontal bitmap sweep. Used */ + /* during drop-out control only. */ + /* */ + /* */ + /* y :: The current pixel column. */ + /* x :: The current row/scanline. */ + /* */ + static + int Horizontal_Gray_Test_Pixel( RAS_ARG_ int y, + int x ) + { +#if 0 + unsigned char* pixel = (unsigned char*)ras.bit_buffer + y; + + if ( ras.target.flow == Flow_Down ) + pixel += (ras.target.rows-1 - x) * ras.target.cols; + else + pixel += x * ras.target.cols; + + return ( x >= 0 && x < ras.target.rows && + *pixel >= 64 ); +#else + UNUSED(y); + UNUSED(x); + return 0; +#endif + } + + + /*************************************************************************/ + /* */ + /* */ + /* Horizontal_Set_Pixel */ + /* */ + /* */ + /* Sets a single pixel in a bitmap during the horizontal sweep. Used */ + /* during drop-out control. */ + /* */ + /* */ + /* y :: The current pixel column. */ + /* x :: The current row/scanline. */ + /* color :: Ignored by this function. */ + /* */ + static + void Horizontal_Gray_Set_Pixel( RAS_ARG_ int y, + int x, + int color ) + { + unsigned char* pixel = (unsigned char*)ras.bit_buffer + y; + + if ( x >= 0 && x < ras.target.rows ) + { + long pitch = ras.target.pitch; + + pixel -= pitch*x; + if (pitch > 0) + pixel += pitch*(ras.target.rows-1); + + color += *pixel; + if (color < 64) + color = 64; + + *pixel = (color >= 128 ? 128 : (unsigned char)color ); + } + } + + + static + void Gray_Ignore( void ) + { + ; + } + + + static + const Raster_Render horizontal_render_gray = + { + &Horizontal_Gray_Sweep_Init, + &Horizontal_Gray_Sweep_Span, + + (Function_Sweep_Step) &Gray_Ignore, + &Horizontal_Gray_Test_Pixel, + &Horizontal_Gray_Set_Pixel, + }; + +#endif /* FT_RASTER_OPTION_ANTI_ALIAS */ + + + /*************************************************************************/ + /* */ + /* A technical note to explain how the scanline sweep is performed: */ + /* */ + /* The function Draw_Sweep() is used to sweep the scanlines of the */ + /* target bitmap or pixmap. For each scanline, it must do the */ + /* following: */ + /* */ + /* - Get the set of all outline intersections for the current */ + /* scanline. */ + /* */ + /* - Sort these intersections (in increasing order). */ + /* */ + /* - Pair intersections to create spans (horizontal pixel segments) */ + /* that are then `drawn' by calling a `sweep_span' function. */ + /* */ + /* - Check for dropouts: If a span is too small to be drawn, it must */ + /* be re-adjusted in order to make it visible again. */ + /* */ + /* The sweep starts from the bottom of the outline (ymin) and goes */ + /* upwards (to ymax). Thus, the function manages the following: */ + /* */ + /* - A linked list of the profiles which are above the current */ + /* scanline. It is called the `wait' list as it contains all the */ + /* profiles waiting to be `activated' during the sweep. It contains */ + /* all profiles initially. */ + /* */ + /* - A linked list of the profiles covering the current scanline, */ + /* i.e., all the profiles that contain an intersection for the */ + /* current scanline. It is called the `draw' list. */ + /* */ + /* A profile travels from the wait list to the draw list if the */ + /* current scanline reaches its bottom border (its ymin). It is also */ + /* removed from the draw list (and becomes unlisted) when the current */ + /* scanline reaches the scanline above its upper border (its ymax). */ + /* */ + /* These positions correspond to the `extrema' table built by */ + /* Finalize_Profile_Table(). */ + /* */ + /* The draw list is always sorted in increasing order of the X */ + /* coordinates. We use a bubble sort because it is easy to implement */ + /* on a linked list, and because in 95% cases, the list is already */ + /* correctly sorted when going from one scanline to the other. */ + /* */ + /* The extrema table gives the scanline coordinates at which at least */ + /* one profile must be removed from the `draw' list, or another one */ + /* must be moved from the `wait' to `draw' lists. */ + /* */ + /* Note that when a dropout is detected, the corresponding span is not */ + /* drawn immediately but kept on a temporary list. All dropout spans */ + /* are drawn after the regular spans on a given scanline. This is a */ + /* requirement of the TrueType specification to properly implement */ + /* some drop-out control modes -- yes, it's weird! */ + /* */ + /* Finally, the parser contains four function pointers that are called */ + /* by Draw_Sweep(). Each rendering mode (monochrome, anti-aliased-5, */ + /* and anti-aliased-17) provide its own set of such functions. These */ + /* are: */ + /* */ + /* sweep_init: Called only when the sweep starts. Used to set */ + /* up some variables. */ + /* */ + /* sweep_span: Used to draw a horizontal span on the current */ + /* scanline. */ + /* */ + /* sweep_test_pixel: Used to test a pixel's intensity, as it is */ + /* required for drop-out control. */ + /* */ + /* sweep_put_pixel: Used to write a single pixel when a drop-out */ + /* needs to be lighted/drawn. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* Generic Sweep Drawing routine */ + /* */ + static + TResult Draw_Sweep( RAS_ARG ) + { + TScan y, y_change, y_height; + + PProfile P, Q, P_Left, P_Right; + + TScan min_Y, max_Y, top, bottom, dropouts; + + TPos x1, x2, e1, e2; + + TProfileList wait; + TProfileList draw; + + + /* Init empty linked lists */ + Init_Linked( &wait ); + Init_Linked( &draw ); + + /* first, compute min and max Y -- and add profiles to the wait list */ + P = ras.start_prof; + max_Y = TRUNC( ras.minY ); + min_Y = TRUNC( ras.maxY ); + + while ( P ) + { + Q = P->link; + + bottom = P->start; + top = 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 extrema table */ + if ( ras.n_extrema == 0 ) + { + ras.error = ErrRaster_Invalid_Outline; + return FAILURE; + } + + /* Now inits the sweep */ + PTRACE2(( "draw_sweep: initialize sweep\n" )); + ras.render.init( RAS_VAR_ &min_Y, &max_Y ); + PTRACE2(( " init min_y = %d, max_y = %d\n", 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.n_extrema > 0 && + ras.pool_size[-ras.n_extrema] == min_Y ) + ras.n_extrema--; + + PTRACE2(( "starting loop with n_extrema = %d", ras.n_extrema )); + while ( ras.n_extrema > 0 ) + { + PProfile prof = wait; + + + /* look in the wait list for new activations */ + while ( prof ) + { + PProfile next = prof->link; + + + prof->countL -= y_height; + if ( prof->countL == 0 ) + { + /* move the profile from the wait list to the draw list */ + DelOld( &wait, prof ); + InsNew( &draw, prof ); + } + prof = next; + } + + /* Sort the draw list */ + Sort( &draw ); + + /* compute next y extremum scanline; we won't change the */ + /* elements of the wait and draw lists until there */ + y_change = ras.pool_size[-ras.n_extrema--]; + y_height = y_change - y; + + PTRACE2(( ">>> y = %d, y_change = %d, y_height = %d", + y, y_change, y_height )); + + while ( y < y_change ) + { + int window; + PProfile left; + + + /* Let's trace */ + dropouts = 0; + + /* skip to next line if there is no active profile there */ + if ( !draw ) goto Next_Line; + + left = draw; + window = left->flow; + prof = left->link; + + PTRACE2(( ">>> line y = %d", y )); + + while ( prof ) + { + PProfile next = prof->link; + + + window += prof->flow; + + if ( window == 0 ) + { + x1 = left->X; + x2 = prof->X; + + if ( x1 > x2 ) + { + TPos xs = x1; + + + x1 = x2; + x2 = xs; + } + + if ( x2 - x1 <= ras.precision && ras.dropout_mode ) + { + e1 = CEILING( x1 ); + e2 = FLOOR( x2 ); + + if ( e1 > e2 || e2 == e1 + ras.precision ) + { + /* a drop out was detected */ + + left->X = x1; + prof->X = x2; + + /* mark profiles for drop-out processing */ + left->countL = 1; + prof->countL = 2; + dropouts++; + goto Skip_To_Next; + } + } + + PTRACE2(( "drawing span ( y=%d, x1=%d, x2=%d )", + y, x1, x2 )); + ras.render.span( RAS_VAR_ y, x1, x2 ); + + Skip_To_Next: + left = next; + } + prof = next; + } + + /* 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.render.step( RAS_VAR ); + + y++; + + if ( y < y_change ) + Sort( &draw ); + + PTRACE2(( "line sorted for next operation" )); + } + + /* Now finalize the profiles that needs it */ + + PTRACE2(( "finalizing profiles..." )); + { + PProfile prof, next; + + + prof = draw; + while ( prof ) + { + next = prof->link; + if (prof->height == 0) + DelOld( &draw, prof ); + prof = next; + } + } + + PTRACE2(( "profiles finalized for this run" )); + } + + /* for gray-scaling, flushes the bitmap scanline cache */ + while ( y <= max_Y ) + { + ras.render.step( RAS_VAR ); + y++; + } + + return SUCCESS; + + +Scan_DropOuts : + P_Left = draw; + + + while ( dropouts > 0 ) + { + TPos e1, e2; + PProfile left, right; + + + while ( P_Left->countL != 1 ) + P_Left = P_Left->link; + P_Right = P_Left->link; + while ( P_Right->countL != 2 ) + P_Right = P_Right->link; + + P_Left->countL = 0; + P_Right->countL = 0; + + /* Now perform the dropout control */ + x1 = P_Left->X; + x2 = P_Right->X; + + left = ( ras.flipped ? P_Right : P_Left ); + right = ( ras.flipped ? P_Left : P_Right ); + + PTRACE2(( "performing drop-out control ( x1= %d, x2 = %d )", + x1, x2 )); + + e1 = CEILING( x1 ); + e2 = FLOOR ( x2 ); + + if ( e1 > e2 ) + { + if ( e1 == e2 + ras.precision ) + { + switch ( ras.dropout_mode ) + { + 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 when: */ + /* */ + /* 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 */ + /* */ + + /* upper stub test */ + if ( ( left->next == right && left->height <= 0 ) || + + /* lower stub test */ + ( right->next == left && left->start == y ) || + + /* check that the rightmost pixel isn't set */ + ras.render.test_pixel( RAS_VAR_ y, TRUNC(e1)) ) + goto Next_Dropout; + + if ( ras.dropout_mode == 2 ) + e1 = e2; + else + e1 = CEILING( (x1 + x2 + 1)/2 ); + + break; + + default: + goto Next_Dropout; /* Unsupported mode */ + } + } + else + goto Next_Dropout; + } + + PTRACE2(( " -> setting pixel" )); + ras.render.set_pixel( RAS_VAR_ y, + TRUNC( e1 ), + (x2 - x1) >> ras.scale_shift ); + Next_Dropout: + + dropouts--; + } + goto Next_Line; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Render_Single_Pass */ + /* */ + /* */ + /* Performs one sweep with sub-banding. */ + /* */ + /* */ + /* flipped :: whether or not we have to flip. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + static + int Render_Single_Pass( RAS_ARG_ int flipped ) + { + TBand* band; + + + ras.flipped = flipped; + + band = ras.band_stack; + + PTRACE2(( "raster: entering render_single_pass (flipped = %d)\n", + flipped )); + + while ( band >= ras.band_stack ) + { + ras.maxY = ((long)band[0].y_max << (ras.scale_shift+6)) - 1; + + ras.minY = (long)band[0].y_min << (ras.scale_shift+6); + + ras.cursor = ras.pool; + ras.error = 0; + + PTRACE2(( "raster: band = [ %d, %d ]\n", + band[0].y_min, + band[0].y_max )); + + if ( Convert_Glyph( RAS_VAR_ ras.outline ) ) + { + int bottom, top, half; + + + if ( ras.error != ErrRaster_Overflow ) + return FAILURE; + ras.error = ErrRaster_Ok; + + PTRACE2(( "conversion failure, performing sub-banding\n" )); + + /* sub-banding */ + +#ifdef DEBUG_RASTER + ClearBand( RAS_VAR_ TRUNC( ras.minY ), TRUNC( ras.maxY ) ); +#endif + + bottom = band[0].y_min; + top = band[0].y_max; + half = ( top - bottom ) >> 1; + + if ( band >= ras.band_stack + 7 || half == 0 ) + { + ras.band_top = 0; + ras.error = ErrRaster_Invalid_Outline; + return ras.error; + } + + band[1].y_min = bottom + half; + band[1].y_max = top; + band[0].y_max = bottom + half; + + band ++; + } + else + { + PTRACE2(( "conversion succeeded, span drawing sweep\n" )); + if ( ras.start_prof ) + if ( Draw_Sweep( RAS_VAR ) ) + return ras.error; + band --; + } + } + + PTRACE2(( "raster: exiting render_single_pass\n" )); + + return SUCCESS; /* success */ + } + + + static + int Raster_Render1( FT_Raster raster ) + { + int error; + + + if ( ras.target.width > ABS(ras.target.pitch)*8 ) + return ErrRaster_Invalid_Map; + + ras.scale_shift = ras.precision_bits - 6; + ras.scale_delta = ras.precision_half; + + /* Vertical Sweep */ + ras.band_top = 0; + ras.band_stack[0].y_min = 0; + ras.band_stack[0].y_max = ras.target.rows; + + ras.render = vertical_render_mono; + ras.bit_width = ras.target.width; + ras.bit_buffer = (unsigned char*)ras.target.buffer; + + if ( (error = Render_Single_Pass( RAS_VAR_ 0 )) != 0 ) + return error; + + /* Horizontal Sweep */ + + if ( ras.second_pass && ras.dropout_mode != 0 ) + { + ras.render = horizontal_render_mono; + ras.band_top = 0; + ras.band_stack[0].y_min = 0; + ras.band_stack[0].y_max = ras.target.width; + + if ( (error = Render_Single_Pass( RAS_VAR_ 1 )) != 0 ) + return error; + } + + return ErrRaster_Ok; + } + + +#ifdef FT_RASTER_OPTION_ANTI_ALIAS + + + static + int Raster_Render8( FT_Raster raster ) + { + int error; + + if ( ras.target.width > ABS(ras.target.pitch) ) + return ErrRaster_Invalid_Map; + + /* Vertical Sweep */ + ras.band_top = 0; + ras.band_stack[0].y_min = 0; + ras.band_stack[0].y_max = ras.target.rows; + + ras.scale_shift = (ras.precision_bits-6); + ras.scale_delta = ras.precision_half; + ras.dropout_mode = 2; + + ras.render = vertical_render_gray; + ras.bit_width = ras.target.width; + ras.bit_buffer = (unsigned char*)ras.target.buffer; + ras.pix_buffer = (unsigned char*)ras.target.buffer; + + error = Render_Single_Pass( RAS_VAR_ 0 ); + if ( error ) + return error; + +#if 1 + /* Horizontal Sweep */ + ras.render = horizontal_render_gray; + ras.band_top = 0; + ras.bit_width = ras.target.rows; + ras.band_stack[0].y_min = 0; + ras.band_stack[0].y_max = ras.target.width; + + return Render_Single_Pass( RAS_VAR_ 1 ); +#else + return 0; +#endif + } + + +#else /* FT_RASTER_OPTION_ANTI_ALIAS */ + + + static + int Raster_Render8( FT_Raster raster ) + { + return ErrRaster_Unimplemented; + } + + +#endif /* FT_RASTER_OPTION_ANTI_ALIAS */ + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster_Render */ + /* */ + /* */ + /* Renders an outline into a target bitmap. */ + /* */ + /* */ + /* raster :: A handle to the raster object used during rendering. */ + /* outline :: A pointer to the source outline record/object. */ + /* bitmap :: A pointer to the target bitmap descriptor. */ + /* */ + /* */ + /* Error code, interpreted as a FT_Error by FreeType. 0 means */ + /* success. */ + /* */ + EXPORT_FUNC + int FT_Raster_Render( FT_Raster raster, + FT_Outline* outline, + FT_Bitmap* target_map ) + { + if ( !raster || !raster->pool || !raster->pool_size ) + return ErrRaster_Uninitialized_Object; + + /* return immediately if the outline is empty */ + if ( outline->n_points == 0 || outline->n_contours <= 0 ) + return ErrRaster_Ok; + + 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 ErrRaster_Invalid_Map; + + ras.outline = outline; + ras.target = *target_map; + + ras.dropout_mode = outline->dropout_mode; + ras.second_pass = outline->second_pass; + SET_High_Precision( outline->high_precision ); + + switch ( target_map->pixel_mode ) + { + case ft_pixel_mode_mono: + return Raster_Render1( raster ); + case ft_pixel_mode_grays: + return Raster_Render8( raster ); + + default: + return ErrRaster_Unimplemented; + } + } + + +#ifdef FT_RASTER_OPTION_ANTI_ALIAS + + + /*************************************************************************/ + /* */ + /* */ + /* Reset_Palette_5 */ + /* */ + /* */ + /* Resets lookup table when the 5-gray-levels palette changes. */ + /* */ + static + void Reset_Palette_5( RAS_ARG ) + { + + +#ifdef FT_RASTER_ANY_ENDIAN + + + int i, j, l, c; + + + for ( i = 0; i < 256; i++ ) + { + l = 0; + j = i; + + for ( c = 0; c < 4; c++ ) + { + l <<= 4; + + if ( j & 0x80 ) l++; + if ( j & 0x40 ) l++; + + j = ( j << 2 ) & 0xFF; + } + + ras.count_table[i] = l; + } + + +#else /* FT_RASTER_ANY_ENDIAN */ + + + int i; + + + for ( i = 0; i < 256; i++ ) + { + int cnt1, cnt2; + + cnt1 = ((i & 128) >> 7) + + ((i & 64) >> 6) + + ((i & 8) >> 3) + + ((i & 4) >> 2); + + cnt2 = ((i & 32) >> 5) + + ((i & 16) >> 4) + + ((i & 2) >> 1) + + (i & 1); + + /* */ + /* Note that when the endianess isn't specified through one of the */ + /* configuration, we use the big-endian storage in `count_table' */ + /* */ + +#if defined( FT_RASTER_LITTLE_ENDIAN ) + ras.count_table[i] = (ras.grays[cnt2] << 8) | ras.grays[cnt1]; +#else + ras.count_table[i] = (ras.grays[cnt1] << 8) | ras.grays[cnt2]; +#endif + } + + +#endif /* FT_RASTER_ANY_ENDIAN */ + } + + + /*************************************************************************/ + /* */ + /* */ + /* Reset_Palette_17 */ + /* */ + /* */ + /* Resets lookup table when 17-gray-levels palette changes. */ + /* */ +#ifdef FT_RASTER_ANTI_ALIAS_17 + + + static + void Reset_Palette_17( RAS_ARG ) + { + int i; + + + for ( i = 0; i < 256; i++ ) + ras.count_table[i] = ((i & 128) >> 7) + + ((i & 64) >> 6) + + ((i & 8) >> 3) + + ((i & 4) >> 2) + + ((i & 32) >> 5) + + ((i & 16) >> 4) + + ((i & 2) >> 1) + + (i & 1); +} + + +#endif /* FT_RASTER_ANTI_ALIAS_17 */ + + +#endif /* TT_RASTER_OPTION_ANTI_ALIAS */ + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster_ObjSize */ + /* */ + /* */ + /* This function returns the size of a raster object in bytes. */ + /* Client applications are thus able to allocate objects in their own */ + /* heap/memory space, without revealing the internal structures of */ + /* the scan-line converter. */ + /* */ + /* */ + /* The size in bytes of a single raster object. */ + /* */ + EXPORT_FUNC + long FT_Raster_ObjSize( void ) + { + return (long)sizeof( struct FT_RasterRec_ ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster_Init */ + /* */ + /* */ + /* Initializes a fresh raster object which should have been allocated */ + /* by client applications. This function is also used to set the */ + /* object's render pool. It can be used repeatedly on a single */ + /* object if one wants to change the pool's address or size. */ + /* */ + /* Note that the render pool has no state and is only used during a */ + /* call to FT_Raster_Render(). It is thus theorically possible to */ + /* share it between several non-concurrent components of your */ + /* applications when memory is a scarce resource. */ + /* */ + /* */ + /* pool_size :: The render pool's size in bytes. This must be at */ + /* least 4 kByte. */ + /* */ + /* */ + /* raster :: A handle to the target raster object. */ + /* */ + /* pool_base :: The render pool's base address in memory. */ + /* */ + /* */ + /* An error condition, used as a FT_Error in the FreeType library. */ + /* 0 means success. */ + /* */ + EXPORT_FUNC + int FT_Raster_Init( FT_Raster raster, + const char* pool_base, + long pool_size ) + { +/* static const char default_palette[5] = { 0, 1, 2, 3, 4 }; */ + + /* check the object address */ + if ( !raster ) + return ErrRaster_Uninitialized_Object; + + /* check the render pool - we won't go under 4 Kb */ + if ( !pool_base || pool_size < 4096 ) + return ErrRaster_Invalid_Pool; + + /* save the pool */ + raster->pool = (PPos)pool_base; + raster->pool_size = raster->pool + pool_size / sizeof ( TPos ); + +#ifdef FT_RASTER_OPTION_ANTI_ALIAS + raster->gray_width = ANTI_ALIAS_BUFFER_SIZE/2; + /* clear anti-alias intermediate lines */ + { + char* p = raster->gray_lines; + char* limit = p + ANTI_ALIAS_BUFFER_SIZE; + + do *p++ = 0; while ( p < limit ); + } +#endif + +#if 0 + /* set the default palette: 5 levels = 0, 1, 2, 3, and 4 */ + FT_Raster_SetPalette( raster, 5, default_palette ); +#endif + + return ErrRaster_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster_SetPalette */ + /* */ + /* */ + /* Sets the pixmap rendering palette. Anti-aliasing modes are */ + /* implemented/possible, they differ from the number of entries in */ + /* the palette. */ + /* */ + /* */ + /* count :: The number of palette entries. Valid values are 2, 5, */ + /* and 17, which are the number of intermediate gray */ + /* levels supported. */ + /* */ + /* palette :: An array of `count' chars giving the 8-bit palette of */ + /* intermediate `gray' levels for anti-aliased rendering. */ + /* */ + /* In all modes, palette[0] corresponds to the background, */ + /* while palette[count-1] to the foreground. Hence, a */ + /* count of 2 corresponds to no anti-aliasing; a count of */ + /* 5 uses 3 intermediate levels between the background and */ + /* foreground, while a count of 17 uses 15 of them. */ + /* */ + /* */ + /* An error code, used as a FT_Error by the FreeType library. */ + /* */ + /* */ + /* By default, a new object uses mode 5, with a palette of 0, 1, 2, */ + /* 3, and 4. You don't need to set the palette if you don't need to */ + /* render pixmaps. */ + /* */ + EXPORT_FUNC + int FT_Raster_SetPalette( FT_Raster raster, + int count, + const char* palette ) + { + switch ( count ) + { +#ifdef FT_RASTER_OPTION_ANTI_ALIAS + + + /******************************/ + /* The case of 17 gray levels */ + /******************************/ + + case 17: +#ifdef FT_RASTER_ANTI_ALIAS_17 + { + int n; + + + raster->grays_count = count; + for ( n = 0; n < count; n++ ) + raster->grays[n] = (unsigned char)palette[n]; + Reset_Palette_17( RAS_VAR ); + break; + } +#else + return ErrRaster_Unimplemented; +#endif + + /*****************************/ + /* The case of 5 gray levels */ + /*****************************/ + + case 5: +#ifdef FT_RASTER_ANTI_ALIAS_5 + { + int n; + + + raster->grays_count = count; + for ( n = 0; n < count; n++ ) + raster->grays[n] = (unsigned char)palette[n]; + Reset_Palette_5( RAS_VAR ); + break; + } +#else + return ErrRaster_Unimplemented; +#endif + + +#endif /* FT_RASTER_OPTION_ANTI_ALIAS */ + default: + return ErrRaster_Bad_Palette_Count; + } + + return ErrRaster_Ok; + } + + FT_Raster_Interface ft_default_raster = + { + sizeof( struct FT_RasterRec_ ), + ft_glyph_format_outline, + + (FT_Raster_Init_Proc) FT_Raster_Init, + (FT_Raster_Set_Mode_Proc) 0, + (FT_Raster_Render_Proc) FT_Raster_Render + }; + + +/* END */ diff --git a/src/base/ftstream.c b/src/base/ftstream.c new file mode 100644 index 000000000..f373c663f --- /dev/null +++ b/src/base/ftstream.c @@ -0,0 +1,436 @@ +#include +#include + +#undef FT_COMPONENT +#define FT_COMPONENT trace_stream + + + BASE_FUNC + void FT_New_Memory_Stream( FT_Library library, + void* base, + unsigned long size, + FT_Stream stream ) + { + stream->memory = library->memory; + stream->base = (char*)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 )) + { + error = FT_Err_Invalid_Stream_Operation; + + FT_ERROR(( "FT_Seek_Stream:" )); + FT_ERROR(( " invalid i/o, pos = 0x%lx, size = 0x%lx\n", + pos, stream->size )); + } + else + error = FT_Err_Ok; + } + /* note that seeking to the first position after the file is valid */ + else if (pos > stream->size) + { + error = FT_Err_Invalid_Stream_Operation; + + FT_ERROR(( "FT_Seek_Stream:" )); + FT_ERROR(( " invalid i/o, pos = 0x%lx, size = 0x%lx\n", + pos, stream->size )); + } + + 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, + void* 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, + void* 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", + count, read_bytes )); + error = FT_Err_Invalid_Stream_Operation; + } + + return error; + } + + + + 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", + 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", + 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 ) + { + FT_Assert( stream && stream->cursor != 0 ); + + 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 && stream->cursor ); + + result = 0; + if (stream->cursor < stream->limit) + result = *stream->cursor++; + + return result; + } + + + BASE_FUNC + FT_Short FT_Get_Short( FT_Stream stream ) + { + char* 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_Long FT_Get_Offset( FT_Stream stream ) + { + char* 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 ) + { + char* 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_Char FT_Read_Char( FT_Stream stream, + FT_Error* error ) + { + char 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; + } + 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", + stream->pos, stream->size )); + return 0; + } + + + BASE_FUNC + FT_Short FT_Read_Short( FT_Stream stream, + FT_Error* error ) + { + char reads[2]; + char* 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); + stream->pos += 2; + } + } + else goto Fail; + + 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", + stream->pos, stream->size )); + return 0; + } + + + BASE_FUNC + FT_Long FT_Read_Offset( FT_Stream stream, + FT_Error* error ) + { + char reads[3]; + char* 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); + stream->pos += 3; + } + } + else goto Fail; + + 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", + stream->pos, stream->size )); + return 0; + } + + + BASE_FUNC + FT_Long FT_Read_Long( FT_Stream stream, + FT_Error* error ) + { + char reads[4]; + char* 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); + stream->pos += 4; + } + } + else goto Fail; + + return result; + + Fail: + *error = FT_Err_Invalid_Stream_Operation; + FT_ERROR(( "FT_Read_Long:" )); + FT_ERROR(( " invalid i/o, pos = 0x%lx, size = 0x%lx", + stream->pos, stream->size )); + return 0; + } + diff --git a/src/base/ftstream.h b/src/base/ftstream.h new file mode 100644 index 000000000..944795c75 --- /dev/null +++ b/src/base/ftstream.h @@ -0,0 +1,178 @@ +#ifndef FTSTREAM_H +#define FTSTREAM_H + +#include + + + /*************************************************************************/ + /* */ + /* 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)) + + + /*************************************************************************/ + /* */ + /* 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 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 ) + + + + BASE_DEF + void FT_New_Memory_Stream( FT_Library library, + void* base, + unsigned long 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, + void* buffer, + FT_ULong count ); + + BASE_DEF + FT_Error FT_Read_Stream_At( FT_Stream stream, + FT_ULong pos, + void* 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_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_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 ); + + +#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 ACCESS_Compressed_Frame( size ) \ + FT_SET_ERROR( FT_Access_Compressed_Frame( stream, size ) ) + + +#define FORGET_Frame() \ + FT_Forget_Frame( stream ) + + +#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_Char*)buffer, \ + count ) ) + +#define FILE_Read_At( position, buffer, count ) \ + FT_SET_ERROR( FT_Read_Stream_At( stream, \ + position, \ + (FT_Char*)buffer, \ + count ) ) + + + +#endif /* FTIO_H */ diff --git a/src/base/rules.mk b/src/base/rules.mk new file mode 100644 index 000000000..7e6473cbf --- /dev/null +++ b/src/base/rules.mk @@ -0,0 +1,136 @@ +#**************************************************************************** +#* * +#* Base layer Makefile * +#* * +#* Copyright 1996-1999 by * +#* David Turner, Robert Wilhelm, and Werner Lemberg. * +#* * +#* This file is part of the FreeType project, and may only be used * +#* modified and distributed under the terms of the FreeType project * +#* license, LICENSE.TXT. By continuing to use, modify, or distribute * +#* this file you indicate that you have read the license and * +#* understand and accept it fully. * +#* * +#**************************************************************************** + + +#**************************************************************************** +#* * +#* IMPORTANT NOTE: This Makefile is intended for GNU Make! * +#* If you provide Makefiles for other make utilities, * +#* please place them in `freetype/lib/arch/.' * +#* * +#* * +#* This file is to be included by the root FreeType sub-Makefile, usually * +#* named `freetype/lib/Makefile.lib.' Here is the list of the variables * +#* that must be defined to use it: * +#* * +#* BASE_DIR: The location of the base layer's directory. This is * +#* usually `freetype/lib/base.' * +#* * +#* ARCH_DIR: The location of the architecture-dependent directory. * +#* This is usually `freetype/lib/arch/.' * +#* * +#* OBJ_DIR: The location where the compiled object(s) file will be * +#* placed. * +#* * +#* FT_CFLAGS: A set of flags used for compilation of object files. * +#* This contains at least the include paths of the `arch' * +#* and `base' directories + optimization + warnings + * +#* ANSI compliance. * +#* * +#* FT_IFLAGS: The flag used to specify an include path on the compiler * +#* command line. For example, with GCC, this is `-I', while * +#* some other compilers use `/i=' or `-J', etc. * +#* * +#* FT_OBJ: The suffix of an object file for the platform. Can be * +#* `o', `obj', `coff', `tco', etc. * +#* * +#* FT_CC: The C compiler to use. * +#* * +#* * +#* It sets the following variables, which are used by the parent Makefile * +#* after the call: * +#* * +#* BASE_H: The list of base layer header files on which the rest * +#* of the library (i.e., drivers) rely. * +#* * +#* 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/lib/base' which are not compiled * +#* within the base layer proper. * +#* * +#**************************************************************************** + +INCLUDES += $(SRC_)base + +# Base layer sources +# +BASE_SRC := $(BASE_)ftstream.c \ + $(BASE_)ftcalc.c \ + $(BASE_)ftobjs.c \ + $(BASE_)ftextend.c \ + $(BASE_)ftlist.c + +# Base layer headers +# +BASE_H := $(BASE_)ftcalc.h \ + $(BASE_)ftobjs.h \ + $(BASE_)ftdriver.h \ + $(BASE_)ftextend.h \ + $(BASE_)ftlist.h + + +# 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_)ftbbox.c \ + $(BASE_)ftraster.c \ + $(BASE_)ftoutln.c + + +# Base layer extensions headers +# +BASE_EXT_H := $(BASE_EXT_SRC:%c=%h) + + +# 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 + + +# Default extensions objects +# +BASE_EXT_OBJ := $(BASE_EXT_SRC:$(BASE_)%.c=$(OBJ_)%.$O) + + +# Base layer root source file(s) +# +BASE_SRC_M := $(BASE_SRC) +BASE_SRC_S := $(BASE_)ftbase.c + + +# Multiple objects build + extensions +# +$(OBJ_)ft%.$O: $(BASE_)ft%.c $(PUBLIC_H) $(BASE_H) + $(FT_CC) $T$@ $< + + +# Base layer - single object build +# +$(BASE_OBJ_S): $(PUBLIC_H) $(BASE_H) $(BASE_SRC_S) $(BASE_SRC) + $(FT_CC) $T$@ $(BASE_SRC_S) + + +# END diff --git a/src/oldapi/Makefile b/src/oldapi/Makefile new file mode 100644 index 000000000..3b5858cd3 --- /dev/null +++ b/src/oldapi/Makefile @@ -0,0 +1,29 @@ +# +# The OldApi component had not been migrated to the new design yet +# please wait a few days for some updates. This file should be +# completely ignored during a BUILD !! +# +# +include drivers/shared/sfnt/Makefile + +OLDAPI_DIR := $(TOP_DIR)/oldapi + +OLDAPI_INCLUDES := $(FT_IFLAG)$(SFNT_DIR) \ + $(FT_IFLAG)$(OLDAPI_DIR) \ + $(FT_IFLAG)$(TT_DIR) + +OLDAPI_CFLAGS := $(FT_CFLAGS) $(OLDAPI_INCLUDES) + +OLDAPI_OBJ := $(OBJ_DIR)/ttapi.$(FT_OBJ) + +# FreeType-1.1 compatible interface +# +$(OLDAPI_OBJ): $(OLDAPI_DIR)/ttapi.c $(OLDAPI_DIR)/truetype.h \ + $(BASE_H) $(SFNT_H) $(TT_DRV_H) + $(FT_CC) $(OLDAPI_CFLAGS) $< -o $@ + +# update main driver object lists +# +DRV_OBJS_S += $(OLDAPI_OBJ) +DRV_OBJS_M += $(OLDAPI_OBJ) + diff --git a/src/oldapi/readme.txt b/src/oldapi/readme.txt new file mode 100644 index 000000000..da50fd70b --- /dev/null +++ b/src/oldapi/readme.txt @@ -0,0 +1,18 @@ +This directory is provided in order to compile a stand-alone +TrueType driver which should be backwards and binary compatible +with FreeType 1.1 + +Reason is some important design changes were introduced in FreeType +lately, in order to support several font formats transparently. + +The files are : + +"truetype.h" - a replacement for the old "freetype.h" file + that was included by client applications and + font servers of 1.1 + +"ttapi.c" - a front-end for the new TrueType driver, that + presents exactly the same interface as the one + in 1.1 + + diff --git a/src/oldapi/truetype.h b/src/oldapi/truetype.h new file mode 100644 index 000000000..fbde46901 --- /dev/null +++ b/src/oldapi/truetype.h @@ -0,0 +1,1709 @@ +/******************************************************************* + * + * truetype.h + * + * Backwards-compatible high-level interface for the TrueType + * driver. This file is a replacement for the old "freetype.h" + * from 1.0 and 1.1. It can be used to compile applications + * and tools using the old API.. + * + * Note that this (old) interface is now deprecated and won't + * be modified in the future. Developers will have to switch to + * the newer interface to get new features ( kerning, embedded + * bitmaps, etc.. ). + * + * + * + * Copyright 1996-1998 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.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 is the only file that should be included by client + * application sources. All other types and functions defined + * in the "tt*.h" files are library internals and should not be + * included. + * + ******************************************************************/ + +#ifndef TRUETYPE_H +#define TRUETYPE_H + +/* To make freetype.h independent from configuration files we check */ +/* whether EXPORT_DEF has been defined already. */ + +#ifndef EXPORT_DEF +#define EXPORT_DEF extern +#endif + +/* The same for TT_Text. If you define the HAVE_TT_TEXT macro, you */ +/* have to provide a typedef declaration for TT_Text before */ +/* including this file. */ + +#ifndef HAVE_TT_TEXT +#define HAVE_TT_TEXT + typedef char TT_Text; /* the data type to represent */ + /* file name string elements */ +#endif + +#ifdef __cplusplus + extern "C" { +#endif + + +/* The following types are also defined in "drivers/ttlib/ttobjs.h" */ +/* We use the _TRUETYPE_ macro to prevent their redefinition when */ +/* _compiling_ the backwards-compatible layer called "ttapi.c" */ +/* */ +#ifndef _TRUETYPE_ + + /*******************************************************************/ + /* */ + /* FreeType types definitions. */ + /* */ + /* All these begin with a 'TT_' prefix. */ + /* */ + /*******************************************************************/ + + typedef unsigned short TT_Bool; + + typedef signed long TT_Fixed; /* Signed Fixed 16.16 Float */ + + typedef signed short TT_FWord; /* Distance in FUnits */ + typedef unsigned short TT_UFWord; /* Unsigned distance */ + + typedef char TT_String; + typedef signed char TT_Char; + typedef unsigned char TT_Byte; + typedef signed short TT_Short; + typedef unsigned short TT_UShort; + typedef signed long TT_Long; + typedef unsigned long TT_ULong; + typedef int TT_Int; + + typedef signed short TT_F2Dot14; /* Signed fixed float 2.14 used for */ + /* unit vectors, with layout: */ + /* */ + /* s : 1 -- sign bit */ + /* m : 1 -- integer bit */ + /* f : 14 -- unsigned fractional */ + /* */ + /* 's:m' is the 2-bit signed int */ + /* value to which the positive */ + /* fractional part should be */ + /* added. */ + /* */ + + typedef signed long TT_F26Dot6; /* 26.6 fixed float, used for */ + /* glyph points pixel coordinates. */ + + typedef signed long TT_Pos; /* point position, expressed either */ + /* in fractional pixels or notional */ + /* units, depending on context. */ + /* For example, glyph coordinates */ + /* returned by TT_Load_Glyph are */ + /* expressed in font units when */ + /* scaling wasn't requested, and */ + /* in 26.6 fractional pixels if it */ + /* was. */ + + + struct TT_UnitVector_ /* guess what... */ + { + TT_F2Dot14 x; + TT_F2Dot14 y; + }; + + typedef struct TT_UnitVector_ TT_UnitVector; + + + struct TT_Vector_ /* Simple vector type */ + { + TT_F26Dot6 x; + TT_F26Dot6 y; + }; + + typedef struct TT_Vector_ TT_Vector; + + + /* A simple 2x2 matrix used for transformations. */ + /* You should use 16.16 fixed floats. */ + /* */ + /* x' = xx*x + xy*y */ + /* y' = yx*x + yy*y */ + /* */ + + struct TT_Matrix_ + { + TT_Fixed xx, xy; + TT_Fixed yx, yy; + }; + + typedef struct TT_Matrix_ TT_Matrix; + + + /* A structure used to describe a simple bounding box */ + + struct TT_BBox_ + { + TT_Pos xMin; + TT_Pos yMin; + TT_Pos xMax; + TT_Pos yMax; + }; + + typedef struct TT_BBox_ TT_BBox; + + + +#endif /* _TRUETYPE_ */ + + + + + /* A structure used to describe the source glyph to the renderer. */ + + struct TT_Outline_ + { + TT_Short n_contours; /* number of contours in glyph */ + TT_UShort n_points; /* number of points in the glyph */ + + TT_Vector* points; /* the outline's points */ + TT_Byte* flags; /* the points flags */ + TT_UShort* contours; /* the contour end points */ + + /* The following flag indicates that the outline owns the arrays it */ + /* refers to. Typically, this is true of outlines created from the */ + /* TT_New_Outline() API, while it isn't for those returned by */ + /* TT_Get_Glyph_Outline(). */ + + TT_Bool owner; /* the outline owns the coordinates, */ + /* flags and contours array it uses */ + + /* The following flags are set automatically by */ + /* TT_Get_Glyph_Outline(). Their meaning is the following: */ + /* */ + /* high_precision When true, the scan-line converter will use */ + /* a higher precision to render bitmaps (i.e. a */ + /* 1/1024 pixel precision). This is important for */ + /* small ppem sizes. */ + /* */ + /* second_pass When true, the scan-line converter performs */ + /* a second sweep phase dedicated to find */ + /* vertical drop-outs. If false, only horizontal */ + /* drop-outs will be checked during the first */ + /* vertical sweep (yes, this is a bit confusing */ + /* but it's really the way it should work). */ + /* This is important for small ppems too. */ + /* */ + /* dropout_mode Specifies the TrueType drop-out mode to */ + /* use for continuity checking. valid values */ + /* are 0 (no check), 1, 2, 4, and 5. */ + /* */ + /* Most of the engine's users will safely ignore these fields... */ + + TT_Bool high_precision; /* high precision rendering */ + TT_Bool second_pass; /* two sweeps rendering */ + TT_Char dropout_mode; /* dropout mode */ + }; + + typedef struct TT_Outline_ TT_Outline; + + + /* A structure used to return glyph metrics. */ + /* */ + /* The "bearingX" isn't called "left-side bearing" anymore because */ + /* it has different meanings depending on the glyph's orientation. */ + /* */ + /* The same is true for "bearingY", which is the top-side bearing */ + /* defined by the TT_Spec, i.e., the distance from the baseline to */ + /* the top of the glyph's bbox. According to our current convention, */ + /* this is always the same as "bbox.yMax" but we make it appear for */ + /* consistency in its proper field. */ + /* */ + /* The "advance" width is the advance width for horizontal layout, */ + /* and advance height for vertical layouts. */ + /* */ + /* Finally, the library (ver. 1.1) doesn't support vertical text yet */ + /* but these changes were introduced to accomodate it, as it will */ + /* most certainly be introduced in later releases. */ + + struct TT_Glyph_Metrics_ + { + TT_BBox bbox; /* glyph bounding box */ + + TT_Pos bearingX; /* left-side bearing */ + TT_Pos bearingY; /* top-side bearing, per se the TT spec */ + + TT_Pos advance; /* advance width (or height) */ + }; + + + /* A structure used to return horizontal _and_ vertical glyph */ + /* metrics. */ + /* */ + /* A glyph can be used either in a horizontal or vertical layout. */ + /* Its glyph metrics vary with orientation. The Big_Glyph_Metrics */ + /* structure is used to return _all_ metrics in one call. */ + /* */ + + struct TT_Big_Glyph_Metrics_ + { + TT_BBox bbox; /* glyph bounding box */ + + TT_Pos horiBearingX; /* left side bearing in horizontal layouts */ + TT_Pos horiBearingY; /* top side bearing in horizontal layouts */ + + TT_Pos vertBearingX; /* left side bearing in vertical layouts */ + TT_Pos vertBearingY; /* top side bearing in vertical layouts */ + + TT_Pos horiAdvance; /* advance width for horizontal layout */ + TT_Pos vertAdvance; /* advance height for vertical layout */ + + /* The following fields represent unhinted scaled metrics values. */ + /* They can be useful for applications needing to do some device */ + /* independent placement of glyphs. */ + /* */ + /* Applying these metrics to hinted glyphs will most surely ruin */ + /* the grid fitting performed by the bytecode interpreter. These */ + /* values are better used to compute accumulated positioning */ + /* distances. */ + + TT_Pos linearHoriBearingX; /* linearly scaled horizontal lsb */ + TT_Pos linearHoriAdvance; /* linearly scaled horizontal advance */ + + TT_Pos linearVertBearingY; /* linearly scaled vertical tsb */ + TT_Pos linearVertAdvance; /* linearly scaled vertical advance */ + }; + + typedef struct TT_Glyph_Metrics_ TT_Glyph_Metrics; + typedef struct TT_Big_Glyph_Metrics_ TT_Big_Glyph_Metrics; + + + /* A structure used to return instance metrics. */ + + struct TT_Instance_Metrics_ + { + TT_F26Dot6 pointSize; /* char. size in points (1pt = 1/72 inch) */ + + TT_UShort x_ppem; /* horizontal pixels per EM square */ + TT_UShort y_ppem; /* vertical pixels per EM square */ + + TT_Fixed x_scale; /* 16.16 to convert from EM units to 26.6 pix */ + TT_Fixed y_scale; /* 16.16 to convert from EM units to 26.6 pix */ + + TT_UShort x_resolution; /* device horizontal resolution in dpi */ + TT_UShort y_resolution; /* device vertical resolution in dpi */ + }; + + typedef struct TT_Instance_Metrics_ TT_Instance_Metrics; + + + /* Flow constants: */ + /* */ + /* The flow of a bitmap refers to the way lines are oriented */ + /* within the bitmap data, i.e., the orientation of the Y */ + /* coordinate axis. */ + + /* For example, if the first bytes of the bitmap pertain to */ + /* its top-most line, then the flow is 'down'. If these bytes */ + /* pertain to its lowest line, the the flow is 'up'. */ + +#define TT_Flow_Down -1 /* bitmap is oriented from top to bottom */ +#define TT_Flow_Up 1 /* bitmap is oriented from bottom to top */ +#define TT_Flow_Error 0 /* an error occurred during rendering */ + + + /* A structure used to describe the target bitmap or pixmap to the */ + /* renderer. Note that there is nothing in this structure that */ + /* gives the nature of the buffer. */ + + /* IMPORTANT NOTE: */ + /* */ + /* In the case of a pixmap, the 'width' and 'cols' fields must */ + /* have the _same_ values, and _must_ be padded to 32-bits, i.e., */ + /* be a multiple of 4. Clipping problems will arise otherwise, */ + /* if not even page faults! */ + /* */ + /* The typical settings are: */ + /* */ + /* - for an WxH bitmap: */ + /* */ + /* rows = H */ + /* cols = (W+7)/8 */ + /* width = W */ + /* flow = your_choice */ + /* */ + /* - for an WxH pixmap: */ + /* */ + /* rows = H */ + /* cols = (W+3) & ~3 */ + /* width = cols */ + /* flow = your_choice */ + + struct TT_Raster_Map_ + { + int rows; /* number of rows */ + int cols; /* number of columns (bytes) per row */ + int width; /* number of pixels per line */ + int flow; /* bitmap orientation */ + + void* bitmap; /* bit/pixmap buffer */ + long size; /* bit/pixmap size in bytes */ + }; + + typedef struct TT_Raster_Map_ TT_Raster_Map; + + + +/* The following tables are also defined in "drivers/ttlib/ttobjs.h" */ +/* We use the _TRUETYPE_ macro to prevent their redefinition when */ +/* _compiling_ the backwards-compatible layer called "oldapi.c" */ +/* */ +#ifndef _TRUETYPE_ + + /* ------- The font header TrueType table structure ----- */ + + struct TT_Header_ + { + TT_Fixed Table_Version; + TT_Fixed Font_Revision; + + TT_Long CheckSum_Adjust; + TT_Long Magic_Number; + + TT_UShort Flags; + TT_UShort Units_Per_EM; + + TT_Long Created [2]; + TT_Long Modified[2]; + + TT_FWord xMin; + TT_FWord yMin; + TT_FWord xMax; + TT_FWord yMax; + + TT_UShort Mac_Style; + TT_UShort Lowest_Rec_PPEM; + + TT_Short Font_Direction; + TT_Short Index_To_Loc_Format; + TT_Short Glyph_Data_Format; + }; + + typedef struct TT_Header_ TT_Header; + + + /* ------- The horizontal header TrueType table structure ----- */ + + /*******************************************************/ + /* This structure is the one defined by the TrueType */ + /* specification, plus two fields used to link the */ + /* font-units metrics to the header. */ + + struct TT_Horizontal_Header_ + { + TT_Fixed Version; + TT_FWord Ascender; + TT_FWord Descender; + TT_FWord Line_Gap; + + TT_UFWord advance_Width_Max; /* advance width maximum */ + + TT_FWord min_Left_Side_Bearing; /* minimum left-sb */ + TT_FWord min_Right_Side_Bearing; /* minimum right-sb */ + TT_FWord xMax_Extent; /* xmax extents */ + TT_FWord caret_Slope_Rise; + TT_FWord caret_Slope_Run; + + TT_Short caret_Offset; /* only used in vertical header */ + TT_Short Reserved[4]; + + TT_Short metric_Data_Format; + TT_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" or "VMTX" table. */ + + void* long_metrics; + void* short_metrics; + }; + + + /*******************************************************/ + /* This structure is the one defined by the TrueType */ + /* specification. Note that it has exactly the same */ + /* layout as the horizontal header (both are loaded */ + /* by the same function). */ + + struct TT_Vertical_Header_ + { + TT_Fixed Version; + TT_FWord Ascender; + TT_FWord Descender; + TT_FWord Line_Gap; + + TT_UFWord advance_Height_Max; /* advance height maximum */ + + TT_FWord min_Top_Side_Bearing; /* minimum left-sb or top-sb */ + TT_FWord min_Bottom_Side_Bearing; /* minimum right-sb or bottom-sb */ + TT_FWord yMax_Extent; /* xmax or ymax extents */ + TT_FWord caret_Slope_Rise; + TT_FWord caret_Slope_Run; + TT_FWord caret_Offset; + + TT_Short Reserved[4]; + + TT_Short metric_Data_Format; + TT_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; + }; + + + typedef struct TT_Horizontal_Header_ TT_Horizontal_Header; + typedef struct TT_Vertical_Header_ TT_Vertical_Header; + + + /* ----------- OS/2 Table ----------------------------- */ + + struct TT_OS2_ + { + TT_UShort version; /* 0x0001 */ + TT_FWord xAvgCharWidth; + TT_UShort usWeightClass; + TT_UShort usWidthClass; + TT_Short fsType; + TT_FWord ySubscriptXSize; + TT_FWord ySubscriptYSize; + TT_FWord ySubscriptXOffset; + TT_FWord ySubscriptYOffset; + TT_FWord ySuperscriptXSize; + TT_FWord ySuperscriptYSize; + TT_FWord ySuperscriptXOffset; + TT_FWord ySuperscriptYOffset; + TT_FWord yStrikeoutSize; + TT_FWord yStrikeoutPosition; + TT_Short sFamilyClass; + + TT_Byte panose[10]; + + TT_ULong ulUnicodeRange1; /* Bits 0-31 */ + TT_ULong ulUnicodeRange2; /* Bits 32-63 */ + TT_ULong ulUnicodeRange3; /* Bits 64-95 */ + TT_ULong ulUnicodeRange4; /* Bits 96-127 */ + + TT_Char achVendID[4]; + + TT_UShort fsSelection; + TT_UShort usFirstCharIndex; + TT_UShort usLastCharIndex; + TT_Short sTypoAscender; + TT_Short sTypoDescender; + TT_Short sTypoLineGap; + TT_UShort usWinAscent; + TT_UShort usWinDescent; + + /* only version 1 tables: */ + + TT_ULong ulCodePageRange1; /* Bits 0-31 */ + TT_ULong ulCodePageRange2; /* Bits 32-63 */ + }; + + typedef struct TT_OS2_ TT_OS2; + + + /* ----------- Postscript table ------------------------ */ + + struct TT_Postscript_ + { + TT_Fixed FormatType; + TT_Fixed italicAngle; + TT_FWord underlinePosition; + TT_FWord underlineThickness; + TT_ULong isFixedPitch; + TT_ULong minMemType42; + TT_ULong maxMemType42; + TT_ULong minMemType1; + TT_ULong maxMemType1; + + /* Glyph names follow in the file, but we don't */ + /* load them by default. See the ftxpost.c extension. */ + }; + + typedef struct TT_Postscript_ TT_Postscript; + + + /* ------------ horizontal device metrics "hdmx" ---------- */ + + struct TT_Hdmx_Record_ + { + TT_Byte ppem; + TT_Byte max_width; + TT_Byte* widths; + }; + + typedef struct TT_Hdmx_Record_ TT_Hdmx_Record; + + + struct TT_Hdmx_ + { + TT_UShort version; + TT_Short num_records; + TT_Hdmx_Record* records; + }; + + typedef struct TT_Hdmx_ TT_Hdmx; + + +#else + + typedef TT_HoriHeader TT_Horizontal_Header; + typedef TT_VertHeader TT_Vertical_Header; + +#endif /* _TRUETYPE_ */ + + + /* A structure used to describe face properties. */ + /* be aware that this is not the same structure as the one define */ + /* in "freetype/ttlib/ttdriver.h". A suitable conversion is performed */ + /* in "oldapi/ttapi.c" to build a binary driver that is backwards */ + /* compatible with FreeType 1.1, in the function TT_Get_Face_Properties */ + + struct TT_Face_Properties_ + { + TT_UShort num_Glyphs; /* number of glyphs in face */ + TT_UShort max_Points; /* maximum number of points in a glyph */ + TT_UShort max_Contours; /* maximum number of contours in a glyph */ + + TT_UShort num_CharMaps; /* number of charmaps in the face */ + TT_UShort num_Names; /* number of name records in the face */ + + TT_ULong num_Faces; /* 1 for normal TrueType files, and the */ + /* number of embedded faces for TrueType */ + /* collections */ + + TT_Header* header; /* TrueType header table */ + TT_Horizontal_Header* horizontal; /* TrueType horizontal header */ + TT_OS2* os2; /* TrueType OS/2 table */ + TT_Postscript* postscript; /* TrueType Postscript table */ + TT_Hdmx* hdmx; + TT_Vertical_Header* vertical; /* TT Vertical header, if present */ + }; + + typedef struct TT_Face_Properties_ TT_Face_Properties; + + + + /***********************************************************************/ + /* */ + /* TT_Engine */ + /* */ + /* */ + /* A handle to a TrueType driver/engine instance. Engine objects */ + /* can be created with the TT_New_Engine and TT_Build_Engine APIs */ + /* */ + /* TT_Done_Engine will destroy an engine, as well as all the */ + /* objects that were created within it. */ + /* */ + + typedef struct TT_EngineRec_ *TT_Engine; + + /* Note : The type TT_Engine is not defined in "drivers/ttlib/ttobjs.h" */ + + + + +/* The TT_Face type is already defined in "drivers/ttlib/ttobjs.h" */ +/* We use the _TRUETYPE_ macro to prevent their redefinition when */ +/* _compiling_ the backwards-compatible layer called "oldapi.c" */ +/* */ +#ifndef _TRUETYPE_ + + /***********************************************************************/ + /* */ + /* TT_Face */ + /* */ + /* */ + /* A handle to a TrueType face/font object. A TT_Face encapsulates */ + /* the resolution and scaling independent parts of a TrueType font */ + /* file. Instances (a.k.a. fontsizes) and glyph objects must be */ + /* created from them before a glyph can be loaded in memory. */ + /* */ + /* They are created through TT_New_Face and destroyed with */ + /* TT_Done_Face. This will destroy all instance and glyph objects */ + /* */ + + typedef struct TT_FaceRec_* TT_Face; + +#endif /* _TRUETYPE_ */ + + + /***********************************************************************/ + /* */ + /* TT_Instance */ + /* */ + /* */ + /* A handle to a TrueType instance/fontsize object. A TT_Instance */ + /* encapsulates all the resolution and scaling dependent part of */ + /* a given font size, but doesn't contain any glyph. They must be */ + /* used with glyph objects in order to load glyph objects from */ + /* a TT file. */ + /* */ + /* They are created from face objects with TT_New_Instance, and */ + /* destroyed with TT_Done_Instance */ + /* */ + /* A fresh new instance has a default resolution of 96x96 dpi, */ + /* and a default point size of 10 pt. Each of these can be changed */ + /* dynamically with various APIs defined below.. */ + /* */ + + typedef struct TT_InstanceRec_* TT_Instance; + + /* Note: The TT_Instance type is not defined in "drivers/ttlib/ttobjs.h" */ + + + /***********************************************************************/ + /* */ + /* TT_Glyph */ + /* */ + /* */ + /* A handle to a TrueType glyph object. A glyph object acts as a */ + /* container for any of the glyphs of a given face object. It */ + /* encapsulates glyph metrics as well as outline space sized large */ + /* enough to allow the loading of any glyph without further */ + /* allocation. A glyph object doesn't contain any bitmap or */ + /* pixmap data/buffer. */ + /* */ + /* They are created from face objects with TT_New_Glyph, and */ + /* destroyed with TT_Done_Glyph */ + /* */ + /* One can create several glyph objects per face, and use */ + /* a single instance to load multiple glyphs, even concurrently */ + /* in thread-safe and reentrant modes.. */ + /* */ + + typedef struct TT_GlyphRec_* TT_Glyph; + + /* Note: the TT_Glyph type is not defined in "drivers/ttlib/ttobjs.h" */ + + +/* The TT_CharMap type is already defined in "drivers/ttlib/ttobjs.h" */ +/* We use the _TRUETYPE_ macro to prevent their redefinition when */ +/* _compiling_ the backwards-compatible layer called "oldapi.c" */ +/* */ +#ifndef _TRUETYPE_ + + /***********************************************************************/ + /* */ + /* TT_CharMap */ + /* */ + /* */ + /* A handle to a TrueType character mapping object. These objects */ + /* are used to convert character codes in a specific locale or */ + /* encoding into font/face glyph indexes. */ + /* */ + /* The list of character maps found within a face can be */ + /* enumerated with API functions defined below. An CharMap object */ + /* is created with TT_New_CharMap. They are destroyed automatically */ + /* when their parent face objects are discarded. */ + /* */ + + typedef struct TT_CharMapRec_* TT_CharMap; + + typedef long TT_Error; + +#endif /* _TRUETYPE_ */ + + + + EXPORT_DEF + const TT_Instance TT_Null_Instance; + + + /*******************************************************************/ + /* */ + /* Postscript Names extension */ + /* */ + /*******************************************************************/ + +#define TT_Err_Invalid_Post_Table_Format 0x0B00 +#define TT_Err_Invalid_Post_Table 0x0B01 + + /* Initialise the Postscript Names extension */ + EXPORT_DEF + TT_Error TT_Init_Post_Extension( TT_Engine engine ); + + /* Load the Postscript Names table - notice that the 'post' parameter */ + /* will be ignored in 2.0. */ + EXPORT_DEF + TT_Error TT_Load_PS_Names( TT_Face face, + void* post ); + + /* Gets the postscript name of a single glyph */ + EXPORT_DEF + TT_Error TT_Get_PS_Name( TT_Face face, + TT_UShort index, + TT_String** PSname ); + + + /*******************************************************************/ + /* */ + /* Embedded Bitmaps (sbits) extension */ + /* */ + /*******************************************************************/ + +#ifndef _TRUETYPE_ + /*************************************************************/ + /* */ + /* 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" table. */ + /* */ + /* */ + /* height :: glyph height in pixels */ + /* width :: glyph width in pixels */ + /* */ + /* horiBearingX :: horizontal left bearing */ + /* horiBearingY :: horizontal top bearing */ + /* horiAdvance :: horizontal advance */ + /* */ + /* vertBearingX :: vertical left bearing */ + /* vertBearingY :: vertical top bearing */ + /* vertAdvance :: vertical advance */ + /* */ + typedef struct TT_SBit_Metrics_ + { + TT_Byte height; + TT_Byte width; + + TT_Char horiBearingX; + TT_Char horiBearingY; + TT_Byte horiAdvance; + + TT_Char vertBearingX; + TT_Char vertBearingY; + TT_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" table. */ + /* */ + /* */ + /* height :: glyph height in pixels */ + /* width :: glyph width in pixels */ + /* */ + /* bearingX :: left-side bearing */ + /* bearingY :: top-side bearing */ + /* advance :: advance width or height */ + /* */ + typedef struct TT_SBit_Small_Metrics_ + { + TT_Byte height; + TT_Byte width; + + TT_Char bearingX; + TT_Char bearingY; + TT_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 an horizontal or */ + /* vertical layout. */ + /* */ + /* */ + /* ascender :: ascender in pixels */ + /* descender :: descender in pixels */ + /* max_width :: maximum glyph width in pixels */ + /* */ + /* caret_slope_enumerator :: ? */ + /* caret_slope_denominator :: ? */ + /* caret_offset :: ? */ + /* */ + /* min_origin_SB :: ? */ + /* min_advance_SB :: ? */ + /* max_before_BL :: ? */ + /* min_after_BL :: ? */ + /* */ + typedef struct TT_SBit_Line_Metrics_ + { + TT_Char ascender; + TT_Char descender; + TT_Byte max_width; + TT_Char caret_slope_numerator; + TT_Char caret_slope_denominator; + TT_Char caret_offset; + TT_Char min_origin_SB; + TT_Char min_advance_SB; + TT_Char max_before_BL; + TT_Char min_after_BL; + TT_Char pads[2]; + + } TT_SBit_Line_Metrics; + + + + /*************************************************************/ + /* */ + /* TT_SBit_Range */ + /* */ + /* */ + /* A TrueType/OpenType subIndexTable as defined in the */ + /* "EBLC" or "bloc" tables. */ + /* */ + /* */ + /* */ + /* first_glyph :: first glyph index in range */ + /* last_glyph :: last glyph index in range */ + /* */ + /* index_format :: format of index table. valid */ + /* values are 1 to 5. */ + /* */ + /* image_format :: format of 'EBDT' image data */ + /* image_offset :: offset to image data in 'EBDT' */ + /* */ + /* image_size :: for index formats 2 and 5. This is */ + /* the size in bytes of each glyph bitmap */ + /* 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 :: offset of index table in 'EBLC' table */ + /* only used during strike loading.. */ + /* */ + typedef struct TT_SBit_Range + { + TT_UShort first_glyph; + TT_UShort last_glyph; + + TT_UShort index_format; + TT_UShort image_format; + TT_ULong image_offset; + + TT_ULong image_size; + TT_SBit_Metrics metrics; + TT_ULong num_glyphs; + + TT_ULong* glyph_offsets; + TT_UShort* glyph_codes; + + TT_ULong table_offset; + + } TT_SBit_Range; + + + /*************************************************************/ + /* */ + /* TT_SBit_Strike */ + /* */ + /* */ + /* A structure used describe a given bitmap strike in the */ + /* "EBLC" or "bloc" tables. */ + /* */ + /* */ + /* */ + /* num_index_ranges :: number of index ranges */ + /* index_ranges :: array of glyph index ranges */ + /* */ + /* color_ref :: unused. color reference ?? */ + /* hori :: line metrics for horizontal layouts. */ + /* vert :: line metrics for vertical layouts. */ + /* */ + /* start_glyph :: lowest glyph index for this strike. */ + /* end_glyph :: higher glyph index for this strike. */ + /* */ + /* x_ppem :: horizontal pixels per EM */ + /* y_ppem :: vertical pixels per EM */ + /* bit_depth :: bit depth. valid values are 1, 2, 4 & 8 */ + /* flags :: vertical or horizontal ? */ + /* */ + typedef struct TT_SBit_Strike_ + { + TT_Int num_ranges; + TT_SBit_Range* sbit_ranges; + TT_ULong ranges_offset; + + TT_ULong color_ref; + + TT_SBit_Line_Metrics hori; + TT_SBit_Line_Metrics vert; + + TT_UShort start_glyph; + TT_UShort end_glyph; + + TT_Byte x_ppem; + TT_Byte y_ppem; + TT_Byte bit_depth; + TT_Char flags; + + } TT_SBit_Strike; + + + + + /*************************************************************/ + /* */ + /* TT_SBit_Component */ + /* */ + /* */ + /* A simple structure to describe a compound sbit element */ + /* */ + /* */ + /* glyph_code :: element's glyph index */ + /* x_offset :: element's left bearing */ + /* y_offset :: element's top bearing */ + /* */ + typedef struct TT_SBit_Component_ + { + TT_UShort glyph_code; + TT_Char x_offset; + TT_Char y_offset; + + } TT_SBit_Component; + + + + /*************************************************************/ + /* */ + /* TT_SBit_Scale */ + /* */ + /* */ + /* A structure used describe a given bitmap scaling */ + /* table, asdefined for the "EBSC" table. */ + /* */ + /* */ + /* */ + /* hori :: horizontal line metrics */ + /* vert :: vertical line metrics */ + /* */ + /* x_ppem :: horizontal pixels per EM */ + /* y_ppem :: vertical pixels per EM */ + /* */ + /* x_ppem_substitute :: substitution x_ppem */ + /* y_ppem_substitute :: substitution y_ppem */ + /* */ + typedef struct TT_SBit_Scale_ + { + TT_SBit_Line_Metrics hori; + TT_SBit_Line_Metrics vert; + TT_Byte x_ppem; + TT_Byte y_ppem; + TT_Byte x_ppem_substitute; + TT_Byte y_ppem_substitute; + + } TT_SBit_Scale; +#endif /* _TRUETYPE_ */ + + + /*************************************************************/ + /* */ + /* TT_SBit_Image */ + /* */ + /* */ + /* A structure used to describe a given embedded bitmap */ + /* image. */ + /* */ + /* */ + /* map :: bitmap descriptor */ + /* bit_depth :: pixel bit depth */ + /* metrics :: glyph metrics for the bitmap */ + /* */ + typedef struct TT_SBit_Image_ + { + TT_Raster_Map map; + int bit_depth; + TT_Big_Glyph_Metrics metrics; + + } TT_SBit_Image; + + + + /*************************************************************/ + /* */ + /* TT_EBLC */ + /* */ + /* */ + /* A structure used to describe the "EBLC" table from */ + /* a TrueTYpe font. */ + /* */ + /* */ + /* */ + /* version :: version number of the EBLC table */ + /* */ + /* num_strikes :: the number of strikes, i.e. bitmap */ + /* sizes, present in this font */ + /* */ + /* strikes :: array of strikes */ + /* */ + typedef struct TT_EBLC_ + { + TT_ULong version; + TT_ULong num_strikes; + TT_SBit_Strike* strikes; + + } TT_EBLC; + + + /*************************************************************/ + /* */ + /* */ + /* TT_Init_SBit_Extension */ + /* */ + /* */ + /* Initialise the embedded bitmaps extension for the */ + /* FreeType engine. */ + /* */ + /* */ + /* engine :: handle to current FreeType library instance */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + EXPORT_DEF + TT_Error TT_Init_SBit_Extension( TT_Engine engine ); + + + /*************************************************************/ + /* */ + /* */ + /* TT_Get_Face_Bitmaps */ + /* */ + /* */ + /* Loads the "EBLC" table from a font file, if any. */ + /* */ + /* */ + /* face :: handle to the source TrueType font/face */ + /* */ + /* */ + /* eblc_table :: a descriptor for the EBLC table */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + /* */ + /* This function returns TT_Err_Table_Missing when the */ + /* font contains no embedded bitmaps. All fields in */ + /* "eblc_table" will then be set to 0. */ + /* */ + EXPORT_DEF + TT_Error TT_Get_Face_Bitmaps( TT_Face face, + TT_EBLC *eblc_table ); + + /*************************************************************/ + /* */ + /* */ + /* TT_New_SBit_Image */ + /* */ + /* */ + /* Allocates a new embedded bitmap container */ + /* */ + /* */ + /* image :: sbit image */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + EXPORT_DEF + TT_Error TT_New_SBit_Image( TT_SBit_Image* *image ); + + + /*************************************************************/ + /* */ + /* */ + /* TT_Done_SBit_Image */ + /* */ + /* */ + /* Releases an embedded bitmap container */ + /* */ + /* */ + /* image :: sbit image */ + /* */ + EXPORT_DEF + void TT_Done_SBit_Image( TT_SBit_Image* image ); + + + /*************************************************************/ + /* */ + /* */ + /* TT_Load_Glyph_Bitmap */ + /* */ + /* */ + /* Loads a given glyph embedded bitmap */ + /* */ + /* */ + /* face :: handle to the source TrueType font/face */ + /* instance :: current size/transform instance */ + /* glyph_index :: index of source glyph */ + /* bitmap :: target embedded bitmap descriptor */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + /* */ + /* This function returns an error if there is no */ + /* embedded bitmap for the glyph at the given */ + /* instance. */ + /* */ + EXPORT_DEF + TT_Error TT_Load_Glyph_Bitmap( TT_Face face, + TT_Instance instance, + TT_UShort glyph_index, + TT_SBit_Image* bitmap ); + + + /*******************************************************************/ + /* */ + /* FreeType API */ + /* */ + /* All these begin with a 'TT_' prefix. */ + /* */ + /* Most of them are implemented in the 'ttapi.c' source file. */ + /* */ + /*******************************************************************/ + + /* Initialize the engine. */ + + EXPORT_DEF + TT_Error TT_Init_FreeType( TT_Engine* engine ); + + + /* Finalize the engine, and release all allocated objects. */ + + EXPORT_DEF + TT_Error TT_Done_FreeType( TT_Engine engine ); + + + /* Set the gray level palette. This is an array of 5 bytes used */ + /* to produce the font smoothed pixmaps. By convention: */ + /* */ + /* palette[0] = background (white) */ + /* palette[1] = light */ + /* palette[2] = medium */ + /* palette[3] = dark */ + /* palette[4] = foreground (black) */ + /* */ + + EXPORT_DEF + TT_Error TT_Set_Raster_Gray_Palette( TT_Engine engine, + const TT_Byte* palette ); + + + /* ----------------------- face management ----------------------- */ + + /* Open a new TrueType font file, and returns a handle for */ + /* it in variable '*face'. */ + + /* Note: The file can be either a TrueType file (*.ttf) or */ + /* a TrueType collection (*.ttc, in this case, only */ + /* the first face is opened). The number of faces in */ + /* the same collection can be obtained in the face's */ + /* properties, using TT_Get_Face_Properties() and the */ + /* 'max_Faces' field. */ + + EXPORT_DEF + TT_Error TT_Open_Face( TT_Engine engine, + const TT_Text* fontPathName, + TT_Face* face ); + + + /* Open a TrueType font file located inside a collection. */ + /* The font is assigned by its index in 'fontIndex'. */ + + EXPORT_DEF + TT_Error TT_Open_Collection( TT_Engine engine, + const TT_Text* collectionPathName, + TT_ULong fontIndex, + TT_Face* face ); + + + /* Return face properties in the 'properties' structure. */ + + EXPORT_DEF + TT_Error TT_Get_Face_Properties( TT_Face face, + TT_Face_Properties* properties ); + + + /* Set a face object's generic pointer */ + + EXPORT_DEF + TT_Error TT_Set_Face_Pointer( TT_Face face, + void* data ); + + + /* Get a face object's generic pointer */ + + EXPORT_DEF + void* TT_Get_Face_Pointer( TT_Face face ); + + + /* Close a face's file handle to save system resources. The file */ + /* will be re-opened automatically on the next disk access. */ + + EXPORT_DEF + TT_Error TT_Flush_Face( TT_Face face ); + + /* Get a face's glyph metrics expressed in font units. Returns any */ + /* number of arrays. Set the fields to NULL if you're not interested */ + /* by a given array. */ + + EXPORT_DEF + TT_Error TT_Get_Face_Metrics( TT_Face face, + TT_UShort firstGlyph, + TT_UShort lastGlyph, + TT_Short* leftBearings, + TT_UShort* widths, + TT_Short* topBearings, + TT_UShort* heights ); + + /* Close a given font object, destroying all associated */ + /* instances. */ + + EXPORT_DEF + TT_Error TT_Close_Face( TT_Face face ); + + + /* Get font or table data. */ + + EXPORT_DEF + TT_Error TT_Get_Font_Data( TT_Face face, + TT_ULong tag, + TT_Long offset, + void* buffer, + TT_Long* length ); + + +/* A simple macro to build table tags from ASCII chars */ + +#define MAKE_TT_TAG( _x1, _x2, _x3, _x4 ) \ + (((TT_ULong)_x1 << 24) | \ + ((TT_ULong)_x2 << 16) | \ + ((TT_ULong)_x3 << 8) | \ + (TT_ULong)_x4) + + + + /* ----------------------- instance management -------------------- */ + + /* Open a new font instance and returns an instance handle */ + /* for it in '*instance'. */ + + EXPORT_DEF + TT_Error TT_New_Instance( TT_Face face, + TT_Instance* instance ); + + + /* Set device resolution for a given instance. The values are */ + /* given in dpi (Dots Per Inch). Default is 96 in both directions. */ + + EXPORT_DEF + TT_Error TT_Set_Instance_Resolutions( TT_Instance instance, + TT_UShort xResolution, + TT_UShort yResolution ); + + + /* Set the pointsize for a given instance. Default is 10pt. */ + + EXPORT_DEF + TT_Error TT_Set_Instance_CharSize( TT_Instance instance, + TT_F26Dot6 charSize ); + + EXPORT_DEF + TT_Error TT_Set_Instance_CharSizes( TT_Instance instance, + TT_F26Dot6 charWidth, + TT_F26Dot6 charHeight ); + +#define TT_Set_Instance_PointSize( ins, ptsize ) \ + TT_Set_Instance_CharSize( ins, ptsize*64 ) + + EXPORT_DEF + TT_Error TT_Set_Instance_PixelSizes( TT_Instance instance, + TT_UShort pixelWidth, + TT_UShort pixelHeight, + TT_F26Dot6 pointSize ); + + + /* This function has been deprecated !! Do not use it, as it */ + /* doesn't work reliably. You can perfectly control hinting */ + /* yourself when loading glyphs, then apply transforms as usual */ + + EXPORT_DEF + TT_Error TT_Set_Instance_Transform_Flags( TT_Instance instance, + TT_Bool rotated, + TT_Bool stretched ); + + + /* Return instance metrics in 'metrics'. */ + + EXPORT_DEF + TT_Error TT_Get_Instance_Metrics( TT_Instance instance, + TT_Instance_Metrics* metrics ); + + + /* Set an instance's generic pointer. */ + + EXPORT_DEF + TT_Error TT_Set_Instance_Pointer( TT_Instance instance, + void* data ); + + + /* Get an instance's generic pointer. */ + + EXPORT_DEF + void* TT_Get_Instance_Pointer( TT_Instance instance ); + + + /* Close a given instance object, destroying all associated data. */ + + EXPORT_DEF + TT_Error TT_Done_Instance( TT_Instance instance ); + + + + /* ----------------------- glyph management ----------------------- */ + + /* Create a new glyph object related to the given 'face'. */ + + EXPORT_DEF + TT_Error TT_New_Glyph( TT_Face face, + TT_Glyph* glyph ); + + + /* Discard (and destroy) a given glyph object. */ + + EXPORT_DEF + TT_Error TT_Done_Glyph( TT_Glyph glyph ); + + +#define TTLOAD_SCALE_GLYPH 1 +#define TTLOAD_HINT_GLYPH 2 + +#define TTLOAD_DEFAULT (TTLOAD_SCALE_GLYPH | TTLOAD_HINT_GLYPH) + + + /* Load and process (scale/transform and hint) a glyph from the */ + /* given 'instance'. The glyph and instance handles must be */ + /* related to the same face object. The glyph index can be */ + /* computed with a call to TT_Char_Index(). */ + + /* The 'load_flags' argument is a combination of the macros */ + /* TTLOAD_SCALE_GLYPH and TTLOAD_HINT_GLYPH. Hinting will be */ + /* applied only if the scaling is selected. */ + + /* When scaling is off (i.e., load_flags = 0), the returned */ + /* outlines are in EM square coordinates (also called FUnits), */ + /* extracted directly from the font with no hinting. */ + /* Other glyph metrics are also in FUnits. */ + + /* When scaling is on, the returned outlines are in fractional */ + /* pixel units (i.e. TT_F26Dot6 = 26.6 fixed floats). */ + + /* NOTE: The glyph index must be in the range 0..num_glyphs-1 */ + /* where 'num_glyphs' is the total number of glyphs in */ + /* the font file (given in the face properties). */ + + EXPORT_DEF + TT_Error TT_Load_Glyph( TT_Instance instance, + TT_Glyph glyph, + TT_UShort glyphIndex, + TT_UShort loadFlags ); + + + /* Return glyph outline pointers in 'outline'. Note that the returned */ + /* pointers are owned by the glyph object, and will be destroyed with */ + /* it. The client application should _not_ change the pointers. */ + + EXPORT_DEF + TT_Error TT_Get_Glyph_Outline( TT_Glyph glyph, + TT_Outline* outline ); + + + /* Copy the glyph metrics into 'metrics'. */ + + EXPORT_DEF + TT_Error TT_Get_Glyph_Metrics( TT_Glyph glyph, + TT_Glyph_Metrics* metrics ); + + + /* Copy the glyph's big metrics into 'metrics'. */ + /* Necessary to obtain vertical metrics. */ + + EXPORT_DEF + TT_Error TT_Get_Glyph_Big_Metrics( TT_Glyph glyph, + TT_Big_Glyph_Metrics* metrics ); + + + /* Render the glyph into a bitmap, with given position offsets. */ + + /* Note: Only use integer pixel offsets to preserve the fine */ + /* hinting of the glyph and the 'correct' anti-aliasing */ + /* (where vertical and horizontal stems aren't grayed). */ + /* This means that xOffset and yOffset must be multiples */ + /* of 64! */ + + EXPORT_DEF + TT_Error TT_Get_Glyph_Bitmap( TT_Glyph glyph, + TT_Raster_Map* map, + TT_F26Dot6 xOffset, + TT_F26Dot6 yOffset ); + + + /* Render the glyph into a pixmap, with given position offsets. */ + + /* Note : Only use integer pixel offsets to preserve the fine */ + /* hinting of the glyph and the 'correct' anti-aliasing */ + /* (where vertical and horizontal stems aren't grayed). */ + /* This means that xOffset and yOffset must be multiples */ + /* of 64! */ + + EXPORT_DEF + TT_Error TT_Get_Glyph_Pixmap( TT_Glyph glyph, + TT_Raster_Map* map, + TT_F26Dot6 xOffset, + TT_F26Dot6 yOffset ); + + + + /* ----------------------- outline support ------------------------ */ + + /* Allocate a new outline. Reserve space for 'numPoints' and */ + /* 'numContours'. */ + + EXPORT_DEF + TT_Error TT_New_Outline( TT_UShort numPoints, + TT_Short numContours, + TT_Outline* outline ); + + + /* Release an outline. */ + + EXPORT_DEF + TT_Error TT_Done_Outline( TT_Outline* outline ); + + + /* Copy an outline into another one. */ + + EXPORT_DEF + TT_Error TT_Copy_Outline( TT_Outline* source, + TT_Outline* target ); + + + /* Render an outline into a bitmap. */ + + EXPORT_DEF + TT_Error TT_Get_Outline_Bitmap( TT_Engine engine, + TT_Outline* outline, + TT_Raster_Map* map ); + + + /* Render an outline into a pixmap -- note that this function uses */ + /* a different pixel scale, where 1.0 pixels = 128 XXXX */ + + EXPORT_DEF + TT_Error TT_Get_Outline_Pixmap( TT_Engine engine, + TT_Outline* outline, + TT_Raster_Map* map ); + + + /* Return an outline's bounding box -- this function is slow as it */ + /* performs a complete scan-line process, without drawing, to get */ + /* the most accurate values. XXXX */ + + EXPORT_DEF + TT_Error TT_Get_Outline_BBox( TT_Outline* outline, + TT_BBox* bbox ); + + + /* Apply a transformation to a glyph outline. */ + + EXPORT_DEF + void TT_Transform_Outline( TT_Outline* outline, + TT_Matrix* matrix ); + + + /* Apply a translation to a glyph outline. */ + + EXPORT_DEF + void TT_Translate_Outline( TT_Outline* outline, + TT_F26Dot6 xOffset, + TT_F26Dot6 yOffset ); + + + /* Apply a transformation to a vector. */ + + EXPORT_DEF + void TT_Transform_Vector( TT_F26Dot6* x, + TT_F26Dot6* y, + TT_Matrix* matrix ); + + + /* Multiply a matrix with another -- computes "b := a*b". */ + + EXPORT_DEF + void TT_Matrix_Multiply( TT_Matrix* a, + TT_Matrix* b ); + + + /* Invert a transformation matrix. */ + + EXPORT_DEF + TT_Error TT_Matrix_Invert( TT_Matrix* matrix ); + + + /* Compute A*B/C with 64 bits intermediate precision. */ + + EXPORT_DEF + TT_Long TT_MulDiv( TT_Long A, TT_Long B, TT_Long C ); + + + /* Compute A*B/0x10000 with 64 bits intermediate precision. */ + /* Useful to multiply by a 16.16 fixed float value. */ + + EXPORT_DEF + TT_Long TT_MulFix( TT_Long A, TT_Long B ); + + + + /* ----------------- character mappings support ------------- */ + + /* Return the number of character mappings found in this file. */ + /* Returns -1 in case of failure (invalid face handle). */ + /* */ + /* DON'T USE THIS FUNCTION! IT HAS BEEN DEPRECATED! */ + /* */ + /* It is retained for backwards compatibility only and will */ + /* fail on 16bit systems. */ + /* */ + /* You can now get the charmap count in the "num_CharMaps" */ + /* field of a face's properties. */ + /* */ + + EXPORT_DEF + int TT_Get_CharMap_Count( TT_Face face ); + + + /* Return the ID of charmap number 'charmapIndex' of a given face */ + /* used to enumerate the charmaps present in a TrueType file. */ + + EXPORT_DEF + TT_Error TT_Get_CharMap_ID( TT_Face face, + TT_UShort charmapIndex, + TT_UShort* platformID, + TT_UShort* encodingID ); + + + /* Look up the character maps found in 'face' and return a handle */ + /* for the one matching 'platformID' and 'platformEncodingID' */ + /* (see the TrueType specs relating to the 'cmap' table for */ + /* information on these ID numbers). Returns an error code. */ + /* In case of failure, the handle is set to NULL and is invalid. */ + + EXPORT_DEF + TT_Error TT_Get_CharMap( TT_Face face, + TT_UShort charmapIndex, + TT_CharMap* charMap ); + + + /* Translate a character code through a given character map */ + /* and return the corresponding glyph index to be used in */ + /* a TT_Load_Glyph call. This function returns 0 in case of */ + /* failure. */ + + EXPORT_DEF + TT_UShort TT_Char_Index( TT_CharMap charMap, + TT_UShort charCode ); + + + + /* --------------------- names table support ------------------- */ + + /* Return the number of name strings found in the name table. */ + /* Returns -1 in case of failure (invalid face handle). */ + /* */ + /* DON'T USE THIS FUNCTION! IT HAS BEEN DEPRECATED! */ + /* */ + /* It is retained for backwards compatibility only and will */ + /* fail on 16bit systems. */ + /* */ + /* You can now get the number of name strings in a face with */ + /* the "num_Names" field of its properties.. */ + /* */ + + EXPORT_DEF + int TT_Get_Name_Count( TT_Face face ); + + + /* Return the ID of the name number 'nameIndex' of a given face */ + /* used to enumerate the charmaps present in a TrueType file. */ + + EXPORT_DEF + TT_Error TT_Get_Name_ID( TT_Face face, + TT_UShort nameIndex, + TT_UShort* platformID, + TT_UShort* encodingID, + TT_UShort* languageID, + TT_UShort* nameID ); + + + /* Return the address and length of the name number 'nameIndex' */ + /* of a given face. The string is part of the face object and */ + /* shouldn't be written to or released. */ + + /* Note that if for an invalid platformID a null pointer will */ + /* be returned. */ + + EXPORT_DEF + TT_Error TT_Get_Name_String( TT_Face face, + TT_UShort nameIndex, + TT_String** stringPtr, /* pointer address */ + TT_UShort* length ); /* string length + address */ + + + +#ifdef __cplusplus + } +#endif + +#endif /* TRUETYPE_H */ + + +/* END */ diff --git a/src/oldapi/ttapi.c b/src/oldapi/ttapi.c new file mode 100644 index 000000000..ae31f02dd --- /dev/null +++ b/src/oldapi/ttapi.c @@ -0,0 +1,2267 @@ +/******************************************************************* + * + * ttapi.c + * + * High-level interface implementation + * + * Copyright 1996-1998 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.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: + * + * This file is used to implement most of the functions that are + * defined in the file "freetype.h". However, two functions are + * implemented elsewhere : + * + ******************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#define _TRUETYPE_ +#include /* backwards compatible interface */ + + + +/* required by the tracing mode */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_ttapi + + +#define RENDER_POOL_SIZE 64000 + + static + const FT_DriverInterface* tt_interface = &tt_driver_interface; + + static + const TT_DriverInterface* tt_extension = &tt_format_interface; + + + /***********************************************************************/ + /* */ + /* TT_Init_FreeType */ + /* */ + /* */ + /* Creates a new TrueType driver/engine object. */ + /* */ + /* */ + /* engine :: handle to the new engine object */ + /* */ + /* */ + /* TrueType error code. 0 means success */ + /* */ + /* */ + /* No. */ + /* */ + /* */ + /* This function is provided for stand-alone compiles of the */ + /* TrueType driver. */ + /* */ + + EXPORT_FUNC + TT_Error TT_Init_FreeType( TT_Engine* engine ) + { + FT_Library library; + FT_System system; + TT_Error error; + + *engine = 0; + + error = FT_New_System( &system ); + if (error) return error; + + error = FT_New_Library( system, &library ); + if (!error) + /* Now create a new TrueType driver object */ + error = FT_Add_Driver( library, + (FT_DriverInterface*)&tt_driver_interface ); + if (error) + FT_Done_Library(library); + else + *engine = (TT_Engine)library; + + return error; + } + + + /***********************************************************************/ + /* */ + /* TT_Done_FreeType */ + /* */ + /* */ + /* Destroys a given TrueType engine object created with */ + /* TT_Init_FreeType. All associated objects, (i.e. faces, outlines */ + /* and charmaps) will be destroyed.. */ + /* */ + /* */ + /* engine :: handle to the engine object */ + /* */ + /* */ + /* TrueType error code. 0 means success */ + /* */ + /* */ + /* No. */ + /* */ + /* */ + /* This function is provided for stand-alone compiles of the */ + /* TrueType driver. The FreeType library uses the TT_Done_Engine */ + /* API. */ + /* */ + + EXPORT_FUNC + TT_Error TT_Done_FreeType( TT_Engine engine ) + { + FT_Library library = (FT_Library)engine; + + FT_Done_FreeType( library ); + return FT_Err_Ok; + } + + + /***********************************************************************/ + /* */ + /* TT_Set_Raster_Gray_Palette */ + /* */ + /* */ + /* Sets the raster's gray 5-levels palette. Entry 0 correspond to */ + /* the background, Entry 4 to the foreground. Intermediate entries */ + /* correspond to gray levels.. */ + /* */ + /* */ + /* engine :: handle to the engine object */ + /* palette :: an array of 5 bytes used to render 8-bit pixmaps */ + /* */ + /* */ + /* TrueType error code. 0 means success */ + /* */ + /* */ + /* No. */ + /* */ + /* */ + /* This function is provided for stand-alone compiles of the */ + /* TrueType driver. The FreeType library accesses directly the */ + /* raster object to set the palette. */ + /* */ + /* This function ONLY supports 5 levels of grays. */ + /* */ + + EXPORT_FUNC + TT_Error TT_Set_Raster_Gray_Palette( TT_Engine engine, + const TT_Byte* palette ) + { + FT_Library library; + + if (!engine) + return TT_Err_Invalid_Engine; + + library = (FT_Library)engine; + return FT_Set_Raster_Palette( library, 5, (unsigned char*)palette ); + } + + + /***********************************************************************/ + /* */ + /* TT_Open_Face */ + /* */ + /* */ + /* Creates a new face object from a given resource. The file can */ + /* be either a TrueType file (ttf) or a TrueType collection (ttc). */ + /* In the latter case, only the first face is opened. The number */ + /* of faces in a collection can be obtained in the face's */ + /* properties field "num_Faces". Other faces can be opened with */ + /* TT_Open_Collection (see below). */ + /* */ + /* */ + /* engine :: the parent engine object where to create the face */ + /* object. */ + /* */ + /* pathname :: pathname for the font file. */ + /* */ + /* */ + /* face :: a handle to the fresh face object. */ + /* */ + /* */ + /* TrueType error code. 0 means success.. */ + /* */ + /* */ + /* Yes. */ + /* */ + /* */ + /* This API is provided fro backwards compatibility. Please use */ + /* the functions TT_New_Face/TT_Done_Face now to create and */ + /* discard face objects.. */ + /* */ + + + static + TT_Error open_face( FT_Library library, + const TT_Text* pathname, + TT_Int face_index, + TT_Face *aface ) + { + TT_Error error; + FT_Resource resource; + + *aface = 0; + + error = FT_New_Resource( library, pathname, &resource ); + if (error) return error; + +#if 0 + error = FT_Add_Resource( library, resource ); + if (error) goto Fail_Install; +#endif + error = FT_New_Face( resource, face_index, (FT_Face*)aface ); + + /* Destroy glyph slot to comply with the 1.x API */ + if (!error) + FT_Done_GlyphSlot( (*aface)->root.slot ); + + if (error) + FT_Done_Resource(resource); + + return error; + } + + + EXPORT_DEF + TT_Error TT_Open_Face( TT_Engine engine, + const TT_Text* pathname, + TT_Face* aface ) + { + if (!engine) + return TT_Err_Invalid_Driver_Handle; + + return open_face( (FT_Library)engine, pathname, 0, aface ); + } + + + /***********************************************************************/ + /* */ + /* TT_Open_Collection */ + /* */ + /* */ + /* Loads a given face within a collection. */ + /* */ + /* */ + /* engine :: TrueType engine object where to load the face */ + /* pathname :: the collection's pathname */ + /* fontIndex :: index of face within the collection. first is 0 */ + /* */ + /* */ + /* face :: handle to the new face object. Always set to NULL */ + /* in case of error */ + /* */ + /* TrueType error code. 0 means success */ + /* */ + /* */ + /* Yes. */ + /* */ + /* */ + /* This API is provided for backwards compatibility. Please use */ + /* the functions TT_New_Collection/TT_Done_Face now to create and */ + /* discard face/collection objects. */ + /* */ + + EXPORT_DEF + TT_Error TT_Open_Collection( TT_Engine engine, + const TT_Text* pathname, + TT_ULong fontIndex, + TT_Face* aface ) + { + if (!engine) + return TT_Err_Invalid_Driver_Handle; + + return open_face( (FT_Library)engine, pathname, fontIndex, aface ); + } + + + /***********************************************************************/ + /* */ + /* TT_Close_Face */ + /* */ + /* */ + /* Destroys a given face object opened through either TT_Open_Face */ + /* of TT_Open_Collection. */ + /* */ + /* */ + /* face :: handle to the target face object */ + /* */ + /* */ + /* TrueType error code. 0 means success */ + /* */ + /* */ + /* No. */ + /* */ + /* */ + /* This API is provided for backwards compatibility. Please use */ + /* the functions TT_New_Face/TT_Done_Face now to create and */ + /* discard face/collection objects. */ + /* */ + + EXPORT_DEF + TT_Error TT_Close_Face( TT_Face face ) + { + FT_Resource resource; + + if (!face) + return TT_Err_Invalid_Face_Handle; + + resource = face->root.resource; + FT_Done_Face( (FT_Face)face ); + + /* uninstall corresponding resource */ + FT_Done_Resource( resource ); + + return TT_Err_Ok; + } + + + /***********************************************************************/ + /***********************************************************************/ + /***********************************************************************/ + /***********************************************************************/ + /*********** ***********/ + /*********** End of backwards compatible APIs.. ***********/ + /*********** ***********/ + /***********************************************************************/ + /***********************************************************************/ + /***********************************************************************/ + /***********************************************************************/ + + + /***********************************************************************/ + /* */ + /* TT_Get_Face_Properties */ + /* */ + /* */ + /* Return a given face's properties to the caller. */ + /* */ + /* */ + /* face :: handle to the source face object */ + /* */ + /* */ + /* properties :: target properties structure */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + /* */ + /* Yes. */ + /* */ + + EXPORT_FUNC + TT_Error TT_Get_Face_Properties( TT_Face face, + TT_Face_Properties* props ) + { + props->num_Glyphs = (TT_UShort)face->root.num_glyphs; + props->max_Points = (TT_UShort)face->root.max_points; + props->max_Contours = (TT_UShort)face->root.max_contours; + props->num_CharMaps = (TT_UShort)face->root.num_charmaps; + props->num_Faces = face->root.num_faces; + props->num_Names = face->num_names; + props->header = &face->header; + props->horizontal = &face->horizontal; + + /* The driver supports old Mac fonts where there are no OS/2 */ + /* tables present in the file. However, this is not true of */ + /* FreeType 1.1. For the sake of backwards compatibility, we */ + /* always return the address of the face's os2 table, even if */ + /* it is empty (in which case, the 'props.os2' field is set */ + /* to NULL.. */ + /* */ + /* Note however, that the 'os2->version' field is set to */ + /* 0xFFFF to indicate a missing table though... */ + /* */ + + props->os2 = &face->os2; + + props->postscript = &face->postscript; + props->hdmx = &face->hdmx; + props->vertical = ( face->vertical_info ? &face->vertical : 0 ); + + return TT_Err_Ok; + } + + + /***********************************************************************/ + /* */ + /* TT_Set_Face_Pointer. */ + /* */ + /* */ + /* Each face object contains a typeless pointer, which use is left */ + /* to client applications (or the high-level library). This API is */ + /* used to set this generic pointer. It is ignored by the driver. */ + /* */ + /* */ + /* face :: target face object */ + /* data :: generic pointer's value */ + /* */ + /* */ + /* TrueType error code. 0 means success */ + /* */ + /* */ + /* No. */ + /* */ + /* */ + /* The generic pointer is used by the HLib when using the driver */ + /* within the FreeType library. */ + /* */ + + EXPORT_FUNC + TT_Error TT_Set_Face_Pointer( TT_Face face, + void* data ) + { + if ( !face ) + return TT_Err_Invalid_Face_Handle; + else + face->root.generic.data = data; + + return TT_Err_Ok; + } + + + /***********************************************************************/ + /* */ + /* TT_Get_Face_Pointer */ + /* */ + /* */ + /* Each face object contains a typeless pointer, which use is left */ + /* to client applications (or the high-level library). This API is */ + /* used to retrieve this generic pointer, which is ignored by the */ + /* driver. */ + /* */ + /* */ + /* face :: handle to source face object */ + /* */ + /* */ + /* generic pointer value. NULL if the face handle is invalid.. */ + /* */ + /* */ + /* No. */ + /* */ + + EXPORT_FUNC + void* TT_Get_Face_Pointer( TT_Face face ) + { + return ( face ? face->root.generic.data : NULL ); + } + + /***********************************************************************/ + /* */ + /* TT_Get_Face_Metrics */ + /* */ + /* */ + /* Get the metrics of a given array of glyphs. Returns any number */ + /* of metrics arrays. */ + /* */ + /* */ + /* face :: handle to the source face object */ + /* firstGlyph :: index of first glyph in the array */ + /* lastGlyph :: index of last glyph in the array */ + /* */ + /* */ + /* leftBearings :: target array of shorts for the glyph left side */ + /* bearings. Set this field to NULL if you're not */ + /* interested in these metrics. */ + /* */ + /* widths :: target array of unsigned shorts for the glyph advance */ + /* widths. Set this field to NULL if you're not */ + /* interested in these metrics. */ + /* */ + /* topBearings :: target array of shorts for the glyph top side */ + /* bearings. Set this field to NULL if you're not */ + /* interested in these metrics. */ + /* */ + /* heights :: target array of unsigned shorts for the glyph advance */ + /* heights. Set this field to NULL if you're not */ + /* interested in these metrics. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + /* */ + /* No. */ + /* */ + + /********************************************************/ + /* Return 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). */ + /* */ + /* This function will much probably move to another */ + /* component in the short future, but I haven't decided */ + /* which yet... */ + + static + void get_metrics( TT_HoriHeader* header, + TT_Int index, + TT_Short* bearing, + TT_UShort* advance ) + { + TT_LongMetrics* longs_m; + + TT_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; + } + } + + + + EXPORT_FUNC + TT_Error TT_Get_Face_Metrics( TT_Face face, + TT_UShort firstGlyph, + TT_UShort lastGlyph, + TT_Short* leftBearings, + TT_UShort* widths, + TT_Short* topBearings, + TT_UShort* heights ) + { + TT_UShort num; + + if ( !face ) + return TT_Err_Invalid_Face_Handle; + + /* Check the glyph range */ + if ( lastGlyph >= face->root.num_glyphs || firstGlyph > lastGlyph ) + return TT_Err_Invalid_Argument; + + num = lastGlyph - firstGlyph; /* number of elements-1 in each array */ + + /* store the left side bearings and advance widths first */ + { + TT_UShort n; + TT_Short left_bearing; + TT_UShort advance_width; + + + for ( n = 0; n <= num; n++ ) + { + get_metrics( &face->horizontal, + firstGlyph + n, &left_bearing, &advance_width ); + + if ( leftBearings ) leftBearings[n] = left_bearing; + if ( widths ) widths[n] = advance_width; + } + } + + /* check for vertical data if topBearings or heights is non-NULL */ + if ( !topBearings && !heights ) + return TT_Err_Ok; + + if ( !face->vertical_info ) + return TT_Err_No_Vertical_Data; + + /* store the top side bearings */ + { + TT_UShort n; + TT_Short top_bearing; + TT_UShort advance_height; + + for ( n = 0; n <= num; n++ ) + { + get_metrics( (TT_HoriHeader*)&face->vertical, + firstGlyph + n, &top_bearing, &advance_height ); + + if ( topBearings ) topBearings[n] = top_bearing; + if ( heights ) heights[n] = advance_height; + } + } + + return TT_Err_Ok; + } + + + /***********************************************************************/ + /* */ + /* TT_New_Instance */ + /* */ + /* */ + /* Creates a new instance object from a given face */ + /* */ + /* */ + /* face :: handle to source/parent face object */ + /* */ + /* */ + /* instance :: handle to fresh object. Set to NULL in case of */ + /* error. */ + /* */ + /* */ + /* TrueType error code. 0 means success */ + /* */ + /* */ + /* Yes. */ + /* */ + /* */ + /* Any new instance uses a default resolution of 96x96 dpi, and */ + /* a default point size of 10 pts. You can change these anytime */ + /* with TT_Set_Instance_Resolutions/CharSize/CharSizes/PixelSizes */ + /* (see below). */ + /* */ + + EXPORT_FUNC + TT_Error TT_New_Instance( TT_Face face, + TT_Instance* instance ) + { + return FT_New_Size( (FT_Face)face, (FT_Size*)instance ); + } + + + /***********************************************************************/ + /* */ + /* TT_Set_Instance_Resolutions */ + /* */ + /* */ + /* Sets an instance resolutions in dot-per-inches. Default values */ + /* for "new" instances are 96x96 dpi, but these can be changed any */ + /* time by calling this API. */ + /* */ + /* */ + /* instance :: handle to target instance object */ + /* xResolution :: horizontal device resolution in dpi. */ + /* yResolution :: vertical device resolution in dpi. */ + /* */ + /* */ + /* TrueType error code. 0 means success */ + /* */ + /* */ + /* You should set the charsize or pixel size immediately after */ + /* call in multi-htreaded programs. This will force the instance */ + /* data to be resetted. Otherwise, you may encounter corruption */ + /* when loading two glyphs from the same instance concurrently! */ + /* */ + /* Happily, 99.99% will do just that :-) */ + /* */ + /* */ + /* */ + + EXPORT_FUNC + TT_Error TT_Set_Instance_Resolutions( TT_Instance ins, + TT_UShort xResolution, + TT_UShort yResolution ) + { + return FT_Set_Resolutions( (FT_Size)ins, xResolution, yResolution ); + } + + /***********************************************************************/ + /* */ + /* TT_Set_Instance_CharSizes */ + /* */ + /* */ + /* Same as TT_Set_Instance_CharSize, but used to specify distinct */ + /* horizontal and vertical coordinates. */ + /* */ + /* */ + /* instance :: handle to target instance object */ + /* charWidth :: horizontal character size (26.6 points) */ + /* charHeight :: vertical character size (26.6 points) */ + /* */ + /* */ + /* TrueType error code. 0 means success */ + /* */ + /* */ + /* No. */ + /* */ + /* */ + /* There is no check for overflow; with other words, the product */ + /* of glyph dimensions times the device resolution must have */ + /* reasonable values. */ + /* */ + + EXPORT_FUNC + TT_Error TT_Set_Instance_CharSizes( TT_Instance ins, + TT_F26Dot6 charWidth, + TT_F26Dot6 charHeight ) + { + return FT_Set_Char_Sizes( (FT_Size)ins, charWidth, charHeight ); + } + + + /***********************************************************************/ + /* */ + /* TT_Set_Instance_CharSize */ + /* */ + /* */ + /* Sets an instance's character size. The size is in fractional */ + /* (26.6) point units. This function sets the horizontal and */ + /* vertical sizes to be equal. Use TT_Set_Instance_CharSizes */ + /* for distinct X and Y char sizes. */ + /* */ + /* The default charsize of a new instance object is 10 pts. */ + /* */ + /* */ + /* instance :: handle to target instance object */ + /* charSize :: character size expressed in 26.6 fixed float */ + /* points. 1 point = 1/72 dpi. */ + /* */ + /* */ + /* TrueType error code. 0 means success */ + /* */ + /* */ + /* No. */ + /* */ + + EXPORT_FUNC + TT_Error TT_Set_Instance_CharSize( TT_Instance instance, + TT_F26Dot6 charSize ) + { + return TT_Set_Instance_CharSizes( instance, charSize, charSize ); + } + + + /***********************************************************************/ + /* */ + /* TT_Set_Instance_PixelSizes */ + /* */ + /* */ + /* This function is used to set an instance's pixel sizes directly */ + /* It ignores the instance's resolutions fields, and you'll have to */ + /* specify the corresponding pointsize in 26.6 fixed float point */ + /* units. The latter is a requirement of the TrueType bytecode */ + /* interpreter but can be ignored (or more safely, set to the */ + /* maximum pixel size multiplied by 64). */ + /* */ + /* */ + /* instance :: handle to target instance object */ + /* pixelWidth :: horizontal pixel width (integer value) */ + /* pixelHeight :: vertical pixel height (integer value) */ + /* pointSize :: corresponding point size (26.6 points) */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + /* */ + /* No. */ + /* */ + + EXPORT_FUNC + TT_Error TT_Set_Instance_PixelSizes( TT_Instance ins, + TT_UShort pixelWidth, + TT_UShort pixelHeight, + TT_F26Dot6 pointSize ) + { + /* The point size is now ignored by the driver */ + (void)pointSize; + + return FT_Set_Pixel_Sizes( (FT_Size)ins, pixelWidth, pixelHeight ); + } + + /***********************************************************************/ + /* */ + /* TT_Get_Instance_Metrics */ + /* */ + /* */ + /* Returns an instance's metrics into caller space. */ + /* */ + /* */ + /* instance :: handle to source instance object */ + /* */ + /* */ + /* metrics :: target instance metrics structure */ + /* */ + /* */ + /* TrueType error code. 0 means success */ + /* */ + /* */ + /* No. */ + /* */ + /* */ + /* The TT_Instance_Metrics structure differs slightly from the */ + /* FT_Instance_Metrics one, which is why we re-implement this */ + /* function, rather than call a driver method for this.. */ + /* */ + + EXPORT_FUNC + TT_Error TT_Get_Instance_Metrics( TT_Instance ins, + TT_Instance_Metrics* metrics ) + { + TT_Size size = (TT_Size)ins; + + if (!ins) + return TT_Err_Invalid_Instance_Handle; + + metrics->x_scale = size->root.metrics.x_scale; + metrics->y_scale = size->root.metrics.y_scale; + metrics->x_resolution = size->root.metrics.x_resolution; + metrics->y_resolution = size->root.metrics.y_resolution; + metrics->x_ppem = size->root.metrics.x_ppem; + metrics->y_ppem = size->root.metrics.y_ppem; + + metrics->pointSize = size->root.metrics.pointSize; + return TT_Err_Ok; + } + + + /***********************************************************************/ + /* */ + /* TT_Set_Instance_Pointer */ + /* */ + /* */ + /* Each instance object contains a typeless pointer, which use is */ + /* left to client applications (or the high-level library). This */ + /* API is used to set this generic pointer. It is ignored by the */ + /* driver. */ + /* */ + /* */ + /* instance :: handle to the target instance object */ + /* data :: value of the generic pointer */ + /* */ + /* */ + /* TrueType error code. 0 means success */ + /* */ + /* */ + /* No. */ + /* */ + + EXPORT_FUNC + TT_Error TT_Set_Instance_Pointer( TT_Instance ins, + void* data ) + { + if ( !ins ) + return TT_Err_Invalid_Instance_Handle; + else + ((FT_Size)ins)->generic.data = data; + + return TT_Err_Ok; + } + + + /***********************************************************************/ + /* */ + /* TT_Get_Instance_Pointer */ + /* */ + /* */ + /* Each instance object contains a typeless pointer, which use is */ + /* left to client applications (or the high-level library). This */ + /* API is used to retrieve this generic pointer. It is ignored by */ + /* the driver. */ + /* */ + /* */ + /* instance :: handle to source instance object */ + /* */ + /* */ + /* value of generic pointer. NULL if invalid instance */ + /* */ + /* */ + /* No. */ + + EXPORT_FUNC + void* TT_Get_Instance_Pointer( TT_Instance instance ) + { + if ( !instance ) + return NULL; + else + return ((FT_Size)instance)->generic.data; + } + + + /***********************************************************************/ + /* */ + /* TT_Done_Instance */ + /* */ + /* */ + /* Destroys a given instance object. All instances are destroyed */ + /* automatically when their parent face object is discarded. */ + /* However, this API can be used to save memory. */ + /* */ + /* */ + /* instance :: handle to target instance object */ + /* */ + /* */ + /* TrueType error code. 0 means success */ + /* */ + /* */ + /* No. */ + + EXPORT_FUNC + TT_Error TT_Done_Instance( TT_Instance ins ) + { + FT_Done_Size( (FT_Size)ins ); + return TT_Err_Ok; + } + + + /***********************************************************************/ + /* */ + /* TT_Set_Instance_Transform_Flags */ + /* */ + /* */ + /* Nothing. This function has been deprecated... */ + /* */ + /* */ + /* instance :: handle to target instance object */ + /* rotated :: 'rotation' flag.. */ + /* stretched :: 'stretch' flag.. */ + /* */ + /* */ + /* Always 0. */ + /* */ + /* */ + /* This function has been deprecated !! Do not use it, it doesn't */ + /* do anything now.. */ + /* */ + + EXPORT_FUNC + TT_Error TT_Set_Instance_Transform_Flags( TT_Instance instance, + TT_Bool rotated, + TT_Bool stretched ) + { + (void)instance; /* the parameters are unused, the (void) prevents */ + (void)rotated; /* warnings from pedantic compilers.. */ + (void)stretched; + + return TT_Err_Ok; + } + + + + /***********************************************************************/ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* TrueType error code. 0 means success */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ +/******************************************************************* + * + * Function : TT_New_Glyph + * + * Description : Creates a new glyph object related to a given + * face. + * + * Input : face the face handle + * glyph address of target glyph handle + * + * Output : Error code. + * + * MT-Safe : YES! + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_New_Glyph( TT_Face face, + TT_Glyph* aglyph ) + { + return FT_New_GlyphSlot( (FT_Face)face, (FT_GlyphSlot*)aglyph ); + } + + +/******************************************************************* + * + * Function : TT_Done_Glyph + * + * Description : Destroys a given glyph object. + * + * Input : glyph the glyph handle + * + * Output : Error code. + * + * MT-Safe : YES! + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Done_Glyph( TT_Glyph glyph ) + { + FT_Done_GlyphSlot( (FT_GlyphSlot)glyph ); + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Load_Glyph + * + * Description : Loads a glyph. + * + * Input : instance the instance handle + * glyph the glyph handle + * glyphIndex the glyph index + * loadFlags flags controlling how to load the glyph + * (none, scaled, hinted, both) + * + * Output : Error code. + * + * MT-Safe : YES! + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Load_Glyph( TT_Instance instance, + TT_Glyph glyph, + TT_UShort glyphIndex, + TT_UShort loadFlags ) + { + TT_Int result, flags; + + flags = 0; + + /* Convert load flags */ + if ( (loadFlags & TTLOAD_SCALE_GLYPH) == 0 ) + flags = FT_LOAD_NO_SCALE; + + else if ( (loadFlags & TTLOAD_HINT_GLYPH) == 0 ) + flags = FT_LOAD_NO_HINTING; + + else + flags = FT_LOAD_DEFAULT; + + flags |= FT_LOAD_NO_BITMAP | /* prevent bitmap loading for */ + FT_LOAD_LINEAR; /* compatibility purposes.. */ + + return FT_Load_Glyph( (FT_GlyphSlot)glyph, + (FT_Size)instance, + glyphIndex, + flags, + &result ); + } + + +/******************************************************************* + * + * Function : TT_Get_Glyph_Outline + * + * Description : Returns the glyph's outline data. + * + * Input : glyph the glyph handle + * outline address where the glyph outline will be returned + * + * Output : Error code. + * + * MT-Safe : YES! Reads only semi-permanent data. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Get_Glyph_Outline( TT_Glyph glyph, + TT_Outline* outline ) + { + FT_GlyphSlot slot = (FT_GlyphSlot)glyph; + + if (!glyph) + return TT_Err_Invalid_Glyph_Handle; + + /* the structures TT_Outline and FT_Outline are equivalent */ + *((FT_Outline*)outline) = slot->outline; + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Get_Glyph_Metrics + * + * Description : Extracts the glyph's horizontal metrics information. + * + * Input : glyph glyph object handle + * metrics address where metrics will be returned + * + * Output : Error code. + * + * MT-Safe : NO! Glyph containers can't be shared. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Get_Glyph_Metrics( TT_Glyph glyph, + TT_Glyph_Metrics* metrics ) + { + FT_GlyphSlot slot = (FT_GlyphSlot)glyph; + + if (!glyph) + return TT_Err_Invalid_Glyph_Handle; + + /* TT_Glyph_Metrics and FT_Glyph_Metrics are slightly different */ + metrics->bbox.xMin = slot->metrics.horiBearingX; + + metrics->bbox.xMax = slot->metrics.horiBearingX + + slot->metrics.width; + + metrics->bbox.yMax = slot->metrics.horiBearingY; + + metrics->bbox.yMin = slot->metrics.horiBearingY - + slot->metrics.height; + + metrics->bearingX = slot->metrics.horiBearingX; + metrics->bearingY = slot->metrics.horiBearingY; + metrics->advance = slot->metrics.horiAdvance; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Get_Big_Glyph_Metrics + * + * Description : Extracts the glyph's big metrics information. + * + * Input : glyph glyph object handle + * metrics address where big metrics will be returned + * + * Output : Error code. + * + * MT-Safe : NO! Glyph containers can't be shared. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Get_Glyph_Big_Metrics( TT_Glyph glyph, + TT_Big_Glyph_Metrics* metrics ) + { + FT_GlyphSlot slot = (FT_GlyphSlot)glyph; + FT_Glyph_Metrics* met; + FT_Glyph_Metrics* met2; + + if (!glyph) + return TT_Err_Invalid_Glyph_Handle; + + met = &slot->metrics; + met2 = &slot->metrics2; + + metrics->bbox.xMin = met->horiBearingX; + metrics->bbox.xMax = met->horiBearingX + met->width; + metrics->bbox.yMin = met->horiBearingY - met->height; + metrics->bbox.yMax = met->horiBearingY; + + metrics->horiBearingX = met->horiBearingX; + metrics->horiBearingY = met->horiBearingY; + metrics->horiAdvance = met->horiAdvance; + + metrics->vertBearingX = met->vertBearingX; + metrics->vertBearingY = met->vertBearingY; + metrics->vertAdvance = met->vertAdvance; + + metrics->linearHoriAdvance = met2->horiAdvance; + metrics->linearHoriBearingX = met2->horiBearingX; + + metrics->linearVertAdvance = met2->vertAdvance; + metrics->linearVertBearingY = met2->vertBearingY; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Get_Glyph_Bitmap + * + * Description : Produces a bitmap from a glyph outline. + * + * Input : glyph the glyph container's handle + * map target pixmap description block + * xOffset x offset in fractional pixels (26.6 format) + * yOffset y offset in fractional pixels (26.6 format) + * + * Output : Error code. + * + * Note : Only use integer pixel offsets if you want to preserve + * the fine hints applied to the outline. This means that + * xOffset and yOffset must be multiples of 64! + * + * MT-Safe : NO! Glyph containers can't be shared. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Get_Glyph_Bitmap( TT_Glyph glyph, + TT_Raster_Map* map, + TT_F26Dot6 xOffset, + TT_F26Dot6 yOffset ) + { + FT_Library library; + TT_Error error; + FT_GlyphSlot slot = (FT_GlyphSlot)glyph; + FT_Outline outline; + FT_Raster_Map bitmap; + + if ( !glyph ) + return TT_Err_Invalid_Glyph_Handle; + + library = slot->face->resource->library; + outline = slot->outline; + + /* XXX : For now, use only dropout mode 2 */ + /* outline.dropout_mode = _glyph->scan_type; */ + outline.dropout_mode = 2; + + bitmap.width = map->width; + bitmap.rows = map->rows; + bitmap.cols = map->cols; + bitmap.flow = map->flow; + bitmap.pix_bits = 1; + bitmap.buffer = map->bitmap; + + FT_Translate_Outline( &outline, xOffset, yOffset ); + + error = FT_Get_Outline_Bitmap( library, &outline, &bitmap ); + + FT_Translate_Outline( &outline, -xOffset, -yOffset ); + + return error; + } + + +/******************************************************************* + * + * Function : TT_Get_Glyph_Pixmap + * + * Description : Produces a grayscaled pixmap from a glyph + * outline. + * + * Input : glyph the glyph container's handle + * map target pixmap description block + * xOffset x offset in fractional pixels (26.6 format) + * yOffset y offset in fractional pixels (26.6 format) + * + * Output : Error code. + * + * Note : Only use integer pixel offsets to preserve the fine + * hinting of the glyph and the 'correct' anti-aliasing + * (where vertical and horizontal stems aren't grayed). + * This means that xOffset and yOffset must be multiples + * of 64! + * + * You can experiment with offsets of +32 to get 'blurred' + * versions of the glyphs (a nice effect at large sizes that + * some graphic designers may appreciate :) + * + * MT-Safe : NO! Glyph containers can't be shared. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Get_Glyph_Pixmap( TT_Glyph glyph, + TT_Raster_Map* map, + TT_F26Dot6 xOffset, + TT_F26Dot6 yOffset ) + { + FT_Library library; + TT_Error error; + FT_GlyphSlot slot = (FT_GlyphSlot)glyph; + FT_Outline outline; + FT_Raster_Map bitmap; + + if ( !glyph ) + return TT_Err_Invalid_Glyph_Handle; + + library = slot->face->resource->library; + outline = slot->outline; + + /* XXX : For now, use only dropout mode 2 */ + /* outline.dropout_mode = _glyph->scan_type; */ + outline.dropout_mode = 2; + + bitmap.width = map->width; + bitmap.rows = map->rows; + bitmap.cols = map->cols; + bitmap.flow = map->flow; + bitmap.pix_bits = 8; + bitmap.buffer = map->bitmap; + + FT_Translate_Outline( &outline, xOffset, yOffset ); + + error = FT_Get_Outline_Bitmap( library, &outline, &bitmap ); + + FT_Translate_Outline( &outline, -xOffset, -yOffset ); + + return error; + } + + + + /***********************************************************************/ + /* */ + /* TT_Get_Outline_Bitmap */ + /* */ + /* */ + /* Renders an outline within a bitmap. The outline's image is */ + /* simply or-ed to the target bitmap. */ + /* */ + /* */ + /* engine :: handle to the TrueType driver object */ + /* outline :: pointer to the source outline descriptor */ + /* raster :: pointer to the target bitmap descriptor */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + /* */ + /* Yes. */ + /* */ + + EXPORT_FUNC + TT_Error TT_Get_Outline_Bitmap( TT_Engine engine, + TT_Outline* outline, + TT_Raster_Map* map ) + { + FT_Library library = (FT_Library)engine; + FT_Raster_Map bitmap; + + if ( !engine ) + return TT_Err_Invalid_Engine; + + if ( !outline || !map ) + return TT_Err_Invalid_Argument; + + bitmap.width = map->width; + bitmap.rows = map->rows; + bitmap.cols = map->cols; + bitmap.flow = map->flow; + bitmap.pix_bits = 1; + bitmap.buffer = map->bitmap; + + return FT_Get_Outline_Bitmap( library, (FT_Outline*)outline, &bitmap ); + } + + + /***********************************************************************/ + /* */ + /* TT_Get_Outline_Pixmap */ + /* */ + /* */ + /* Renders an outline within a pixmap. The outline's image is */ + /* simply or-ed to the target pixmap. */ + /* */ + /* */ + /* engine :: handle to the TrueType driver object */ + /* outline :: pointer to the source outline descriptor */ + /* raster :: pointer to the target pixmap descriptor */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + /* */ + /* Yes. */ + /* */ + + EXPORT_FUNC + TT_Error TT_Get_Outline_Pixmap( TT_Engine engine, + TT_Outline* outline, + TT_Raster_Map* map ) + { + FT_Library library = (FT_Library)engine; + FT_Raster_Map bitmap; + + if ( !engine ) + return TT_Err_Invalid_Engine; + + if ( !outline || !map ) + return TT_Err_Invalid_Argument; + + bitmap.width = map->width; + bitmap.rows = map->rows; + bitmap.cols = map->cols; + bitmap.flow = map->flow; + bitmap.pix_bits = 8; + bitmap.buffer = map->bitmap; + + return FT_Get_Outline_Bitmap( library, (FT_Outline*)outline, &bitmap ); + } + + + + + /***********************************************************************/ + /* */ + /* TT_New_Outline */ + /* */ + /* */ + /* Creates a new outline of a given size. */ + /* */ + /* */ + /* numPoints :: maximum number of points within the outline */ + /* */ + /* numContours :: maximum number of contours within the outline */ + /* */ + /* */ + /* outline :: target outline descriptor. */ + /* */ + /* */ + /* TrueType error code. 0 means success */ + /* */ + /* */ + /* Yes. */ + /* */ + /* */ + /* This function uses 'malloc' to allocate the outline's array, */ + /* _unlike_ all other functions in the TrueType API. This means */ + /* that the outline won't be destroyed when the TrueType engine */ + /* is finalized.. */ + /* */ + /* It is provided for backwards compatibility ONLY. Use the new */ + /* FT_New_Outline function defined in "ftoutln.h" instead if you're */ + /* working with the FreeType 2.0 API. */ + /* */ + +#include /* for malloc and free */ + + static TT_Outline null_api_outline = { 0, 0, NULL, NULL, NULL, + 0, 0, 0, 0 }; + + EXPORT_FUNC + TT_Error TT_New_Outline( TT_UShort numPoints, + TT_Short numContours, + TT_Outline* outline ) + { + if ( !outline ) + return TT_Err_Invalid_Argument; + + *outline = null_api_outline; + + if ( numPoints > 0 && numContours > 0 ) + { + outline->points = (TT_Vector*)malloc( numPoints * sizeof(TT_Vector) ); + outline->flags = (TT_Byte*) malloc( numPoints * sizeof(TT_Char) ); + outline->contours = (TT_UShort*)malloc( numPoints * sizeof(TT_UShort) ); + + if ( !outline->points || !outline->flags || !outline->contours ) + goto Fail; + + outline->n_points = numPoints; + outline->n_contours = numContours; + outline->owner = TRUE; + } + return TT_Err_Ok; + + Fail: + outline->owner = TRUE; + TT_Done_Outline( outline ); + return TT_Err_Out_Of_Memory; + } + + + /***********************************************************************/ + /* */ + /* TT_Done_Outline */ + /* */ + /* */ + /* Destroys an outline created with FT_New_Outline */ + /* */ + /* */ + /* outline :: */ + /* pointer to the outline destructor to discard. This function */ + /* doesn't destroy the TT_Outline sturcture, only the data it */ + /* contains/own. */ + /* */ + /* */ + /* TrueType error code. 0 means success */ + /* */ + /* */ + /* No. */ + /* */ + /* */ + /* This function uses 'free' to discard the outline's arrays. */ + /* You should only discard outline allocated with TT_New_Outline. */ + /* */ + /* It is provided for backwards compatibility ONLY. Use the new */ + /* FT_Done_Outline function defined in "ftoutln.h" instead if you're*/ + /* working with the FreeType 2.0 API. */ + /* */ + + EXPORT_FUNC + TT_Error TT_Done_Outline( TT_Outline* outline ) + { + if ( outline ) + { + if ( outline->owner ) + { + free( outline->points ); + free( outline->flags ); + free( outline->contours ); + } + *outline = null_api_outline; + return TT_Err_Ok; + } + else + return TT_Err_Invalid_Argument; + } + + + + /***********************************************************************/ + /* */ + /* TT_Copy_Outline */ + /* */ + /* */ + /* Copy an outline into another one. Both objects must have */ + /* the same sizes ( num. points & num. contours ) when this */ + /* function is called.. */ + /* */ + /* */ + /* source :: handle to source outline */ + /* target :: handle to target outline */ + /* */ + /* */ + /* TrueType error code. 0 means success */ + /* */ + + EXPORT_FUNC + TT_Error TT_Copy_Outline( TT_Outline* source, + TT_Outline* target ) + { + return FT_Copy_Outline( (FT_Outline*)source, + (FT_Outline*)target ); + } + + +/******************************************************************* + * + * Function : TT_Transform_Outline + * + * Description : Applies a simple transformation to an outline. + * + * Input : outline the glyph's outline. Can be extracted + * from a glyph container through + * TT_Get_Glyph_Outline(). + * + * matrix simple matrix with 16.16 fixed floats + * + * Output : Error code (always TT_Err_Ok). + * + * MT-Safe : YES! + * + ******************************************************************/ + + EXPORT_FUNC + void TT_Transform_Outline( TT_Outline* outline, + TT_Matrix* matrix ) + { + FT_Transform_Outline( (FT_Outline*)outline, (FT_Matrix*)matrix ); + } + +/******************************************************************* + * + * Function : TT_Transform_Vector + * + * Description : Apply a simple transform to a vector + * + * Input : x, y the vector. + * + * matrix simple matrix with 16.16 fixed floats + * + * Output : None. + * + * MT-Safe : YES! + * + ******************************************************************/ + + EXPORT_FUNC + void TT_Transform_Vector( TT_F26Dot6* x, + TT_F26Dot6* y, + TT_Matrix* matrix ) + { + FT_Transform_Vector( x, y, (FT_Matrix*) matrix ); + } + + +/******************************************************************* + * + * Function : TT_Translate_Outline + * + * Description : Applies a simple translation. + * + * Input : outline no comment :) + * xOffset + * yOffset + * + * Output : Error code. + * + * MT-Safe : YES! + * + ******************************************************************/ + + EXPORT_FUNC + void TT_Translate_Outline( TT_Outline* outline, + TT_F26Dot6 xOffset, + TT_F26Dot6 yOffset ) + { + FT_Translate_Outline( (FT_Outline*)outline, xOffset, yOffset ); + } + + +/******************************************************************* + * + * Function : TT_Get_Outline_BBox + * + * Description : Returns an outline's bounding box. + * + * Input : outline no comment :) + * bbox address where the bounding box is returned + * + * Output : Error code. + * + * MT-Safe : YES! + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Get_Outline_BBox( TT_Outline* outline, + TT_BBox* bbox ) + { + return FT_Get_Outline_CBox( (FT_Outline*)outline, (FT_BBox*)bbox ); + } + + /***********************************************************************/ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* Compute A*B/C with 64 bits intermediate precision. */ + + EXPORT_FUNC + TT_Long TT_MulDiv( TT_Long A, TT_Long B, TT_Long C ) + { + return FT_MulDiv( A, B, C ); + } + + + /***********************************************************************/ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* Compute A*B/0x10000 with 64 bits intermediate precision. */ + /* Useful to multiply by a 16.16 fixed float value. */ + + EXPORT_FUNC + TT_Long TT_MulFix( TT_Long A, TT_Long B ) + { + return FT_MulFix( A, B ); + } + + /* ----------------- character mappings support ------------- */ + +/******************************************************************* + * + * Function : TT_Get_CharMap_Count + * + * Description : Returns the number of charmaps in a given face. + * + * Input : face face object handle + * + * Output : Number of tables. -1 in case of error (bad handle). + * + * Note : DON'T USE THIS FUNCTION! IT HAS BEEN DEPRECATED! + * + * It is retained for backwards compatibility only and will + * fail on 16bit systems. + * + * MT-Safe : YES ! + * + ******************************************************************/ + + EXPORT_FUNC + int TT_Get_CharMap_Count( TT_Face face ) + { + FT_Face _face = (FT_Face)face; + + return ( _face ? _face->num_charmaps : -1 ); + } + + +/******************************************************************* + * + * Function : TT_Get_CharMap_ID + * + * Description : Returns the ID of a given charmap. + * + * Input : face face object handle + * charmapIndex index of charmap in directory + * platformID address of returned platform ID + * encodingID address of returned encoding ID + * + * Output : error code + * + * MT-Safe : YES ! + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Get_CharMap_ID( TT_Face face, + TT_UShort charmapIndex, + TT_UShort* platformID, + TT_UShort* encodingID ) + { + TT_CharMap cmap; + + if ( !face ) + return TT_Err_Invalid_Face_Handle; + + if ( charmapIndex >= face->num_charmaps ) + return TT_Err_Bad_Argument; + + cmap = (TT_CharMap)face->charmaps + charmapIndex; + + *platformID = cmap->root.platform_id; + *encodingID = cmap->root.encoding_id; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Get_CharMap + * + * Description : Looks up a charmap. + * + * Input : face face object handle + * charmapIndex index of charmap in directory + * charMap address of returned charmap handle + * + * Output : Error code. + * + * MT-Safe : YES! + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Get_CharMap( TT_Face face, + TT_UShort charmapIndex, + TT_CharMap* charMap ) + { + if ( !face ) + return TT_Err_Invalid_Face_Handle; + + if ( charmapIndex >= face->num_charmaps ) + return TT_Err_Bad_Argument; + + *charMap = (TT_CharMap)face->charmaps + charmapIndex; + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Char_Index + * + * Description : Returns the glyph index corresponding to + * a given character code defined for the 'charmap'. + * + * Input : charMap charmap handle + * charcode character code + * + * Output : glyph index. + * + * Notes : Character code 0 is the unknown glyph, which should never + * be displayed. + * + * MT-Safe : YES! + * + ******************************************************************/ + + EXPORT_FUNC + TT_UShort TT_Char_Index( TT_CharMap charMap, + TT_UShort charCode ) + { + return tt_interface->get_char_index( (FT_CharMap)charMap, charCode ); + } + + +/******************************************************************* + * + * Function : TT_Get_Name_Count + * + * Description : Returns the number of strings found in the + * name table. + * + * Input : face face handle + * + * Output : number of strings. + * + * Notes : Returns -1 on error (invalid handle). + * + * DON'T USE THIS FUNCTION! IT HAS BEEN DEPRECATED! + * + * It is retained for backwards compatibility only and will + * fail on 16bit systems. + * + * MT-Safe : YES! + * + ******************************************************************/ + + EXPORT_FUNC + int TT_Get_Name_Count( TT_Face face ) + { + if ( !face ) + return -1; + + return face->num_names; + } + + +/******************************************************************* + * + * Function : TT_Get_Name_ID + * + * Description : Returns the IDs of the string number 'nameIndex' + * in the name table of a given face. + * + * Input : face face handle + * nameIndex index of string. First is 0 + * platformID addresses of returned IDs + * encodingID + * languageID + * nameID + * + * Output : Error code. + * + * Notes : Some files have a corrupt or unusual name table, with some + * entries having a platformID > 3. These can usually + * be ignored by a client application. + * + * MT-Safe : YES! + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Get_Name_ID( TT_Face face, + TT_UShort nameIndex, + TT_UShort* platformID, + TT_UShort* encodingID, + TT_UShort* languageID, + TT_UShort* nameID ) + { + TT_NameRec* name; + + if (!face) + return TT_Err_Invalid_Face_Handle; + + if ( nameIndex >= face->num_names ) + return TT_Err_Bad_Argument; + + name = face->name_table.names + nameIndex; + + *platformID = name->platformID; + *encodingID = name->encodingID; + *languageID = name->languageID; + *nameID = name->nameID; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Get_Name_String + * + * Description : Returns the address and length of a given + * string found in the name table. + * + * Input : face face handle + * nameIndex string index + * stringPtr address of returned pointer to string + * length address of returned string length + * + * Output : Error code. + * + * Notes : If the string's platformID is invalid, + * stringPtr is NULL, and length is 0. + * + * MT-Safe : YES! + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Get_Name_String( TT_Face face, + TT_UShort nameIndex, + TT_String** stringPtr, + TT_UShort* length ) + { + TT_NameRec* name; + + if (!face) + return TT_Err_Invalid_Face_Handle; + + if ( nameIndex >= face->num_names ) + return TT_Err_Bad_Argument; + + name = face->name_table.names + nameIndex; + + *stringPtr = (TT_String*)name->string; + *length = name->stringLength; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Get_Font_Data + * + * Description : Loads any font table in client memory. Used by + * the TT_Get_Font_Data(). + * + * Input : face Face object to look for. + * + * tag 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 Starting offset in the table (or the file + * if tag == 0). + * + * buffer Address of target buffer + * + * length Address of decision variable: + * + * if length == NULL: + * Load the whole table. Returns an + * an error if 'offset' != 0. + * + * if *length == 0 : + * Exit immediately, returning the + * length of the given table, or of + * the font file, depending on the + * value of 'tag'. + * + * if *length != 0 : + * Load the next 'length' bytes of + * table or font, starting at offset + * 'offset' (in table or font too). + * + * Output : Error code. + * + * MT-Safe : YES! + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Get_Font_Data( TT_Face face, + TT_ULong tag, + TT_Long offset, + void* buffer, + TT_Long* length ) + { + return tt_extension->get_font_data( face, tag, offset, buffer, length ); + } + + + + + + + + /*******************************************************************/ + /* */ + /* */ + /* */ + /* Postscript Names extension */ + /* */ + /* */ + /* */ + /*******************************************************************/ + + /* Initialise the Postscript Names extension */ + EXPORT_FUNC + TT_Error TT_Init_Post_Extension( TT_Engine engine ) + { + (void)engine; + return TT_Err_Ok; + } + + /* Load the Postscript Names table - notice that the 'post' parameter */ + /* will be ignored in 2.0. */ + EXPORT_DEF + TT_Error TT_Load_PS_Names( TT_Face face, + void* post ) + { + (void)post; + (void)face; + + /* the names are now loaded on demand in 2.0 */ + return TT_Err_Ok; + } + + + /* The following is directly implemented in the TrueType driver */ +#if 0 + /* Gets the postscript name of a single glyph */ + EXPORT_DEF + TT_Error TT_Get_PS_Name( TT_Face face, + TT_UShort index, + TT_String** PSname ); +#endif + + + + + /*******************************************************************/ + /* */ + /* */ + /* */ + /* Embedded Bitmap (sbits) extension */ + /* */ + /* */ + /* */ + /*******************************************************************/ + + + /*************************************************************/ + /* */ + /* */ + /* TT_Init_SBit_Extension */ + /* */ + /* */ + /* Initialise the embedded bitmaps extension for the */ + /* FreeType engine. */ + /* */ + /* */ + /* engine :: handle to current FreeType library instance */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + EXPORT_FUNC + TT_Error TT_Init_SBit_Extension( TT_Engine engine ) + { + (void)engine; + return TT_Err_Ok; + } + + + /*************************************************************/ + /* */ + /* */ + /* TT_Get_Face_Bitmaps */ + /* */ + /* */ + /* Loads the "EBLC" table from a font file, if any. */ + /* */ + /* */ + /* face :: handle to the source TrueType font/face */ + /* */ + /* */ + /* eblc_table :: a descriptor for the EBLC table */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + /* */ + /* This function returns TT_Err_Table_Missing when the */ + /* font contains no embedded bitmaps. All fields in */ + /* "eblc_table" will then be set to 0. */ + /* */ + EXPORT_FUNC + TT_Error TT_Get_Face_Bitmaps( TT_Face face, + TT_EBLC *eblc_table ) + { + if (!face) + return FT_Err_Invalid_Face_Handle; + + eblc_table->num_strikes = face->num_sbit_strikes; + eblc_table->strikes = face->sbit_strikes; + + if ( face->num_sbit_strikes > 0 ) + { + eblc_table->version = 0x00002000; + return TT_Err_Ok; + } + + eblc_table->version = 0; + return TT_Err_Table_Missing; + } + + + /*************************************************************/ + /* */ + /* */ + /* TT_New_SBit_Image */ + /* */ + /* */ + /* Allocates a new embedded bitmap container */ + /* */ + /* */ + /* image :: sbit image */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + EXPORT_DEF + TT_Error TT_New_SBit_Image( TT_SBit_Image* *image ) + { + *image = (TT_SBit_Image*)malloc( sizeof(**image) ); + if ( !*image ) + return TT_Err_Out_Of_Memory; + + MEM_Set( *image, sizeof(**image), 0 ); + return TT_Err_Ok; + } + + + /*************************************************************/ + /* */ + /* */ + /* TT_Done_SBit_Image */ + /* */ + /* */ + /* Releases an embedded bitmap container */ + /* */ + /* */ + /* image :: sbit image */ + /* */ + EXPORT_DEF + void TT_Done_SBit_Image( TT_SBit_Image* image ) + { + free( image->map.bitmap ); + free( image ); + } + + + /*************************************************************/ + /* */ + /* */ + /* TT_Load_Glyph_Bitmap */ + /* */ + /* */ + /* Loads a given glyph embedded bitmap */ + /* */ + /* */ + /* face :: handle to the source TrueType font/face */ + /* instance :: current size/transform instance */ + /* glyph_index :: index of source glyph */ + /* bitmap :: target embedded bitmap descriptor */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + /* */ + /* This function returns an error if there is no */ + /* embedded bitmap for the glyph at the given */ + /* instance. */ + /* */ + EXPORT_FUNC + TT_Error TT_Load_Glyph_Bitmap( TT_Face face, + TT_Instance instance, + TT_UShort glyph_index, + TT_SBit_Image* bitmap ) + { + FT_GlyphSlot slot; + TT_Error error; + + error = FT_New_GlyphSlot( (FT_Face)face, &slot ); + if (error) goto Exit; + + error = FT_Load_Glyph( slot, (FT_Size)instance, glyph_index, + FT_LOAD_NO_OUTLINE, 0 ); + if (!error) + { + /* copy bitmap */ + bitmap->map.width = slot->bitmap.width; + bitmap->map.rows = slot->bitmap.rows; + bitmap->map.cols = slot->bitmap.cols; + bitmap->map.flow = slot->bitmap.flow; + bitmap->bit_depth = slot->bitmap.pix_bits; + bitmap->map.bitmap = slot->bitmap.buffer; + + /* copy metrics */ + bitmap->metrics.bbox.xMin = slot->metrics.horiBearingX >> 6; + bitmap->metrics.bbox.xMax = bitmap->metrics.bbox.xMin + + (slot->metrics.width >> 6); + bitmap->metrics.bbox.yMax = slot->metrics.horiBearingY >> 6; + bitmap->metrics.bbox.yMin = bitmap->metrics.bbox.yMax - + (slot->metrics.height >> 6); + + bitmap->metrics.horiBearingX = bitmap->metrics.bbox.xMin; + bitmap->metrics.horiBearingY = bitmap->metrics.bbox.yMax; + bitmap->metrics.horiAdvance = slot->metrics.horiAdvance >> 6; + + bitmap->metrics.vertBearingX = slot->metrics.vertBearingX >> 6; + bitmap->metrics.vertBearingY = slot->metrics.vertBearingY >> 6; + bitmap->metrics.vertAdvance = slot->metrics.vertAdvance >> 6; + + slot->bitmap.buffer = 0; + } + + FT_Done_GlyphSlot( slot ); + Exit: + return error; + } + +/* END */ diff --git a/src/sfnt/rules.mk b/src/sfnt/rules.mk new file mode 100644 index 000000000..2aa008b57 --- /dev/null +++ b/src/sfnt/rules.mk @@ -0,0 +1,172 @@ +#**************************************************************************** +#* * +#* SFNT driver Makefile * +#* * +#* Copyright 1996-1999 by * +#* David Turner, Robert Wilhelm, and Werner Lemberg. * +#* * +#* This file is part of the FreeType project, and may only be used * +#* modified and distributed under the terms of the FreeType project * +#* license, LICENSE.TXT. By continuing to use, modify, or distribute * +#* this file you indicate that you have read the license and * +#* understand and accept it fully. * +#* * +#**************************************************************************** + + +#**************************************************************************** +#* * +#* IMPORTANT NOTE: This Makefile is intended for GNU Make! * +#* If you provide Makefiles for other make utilities, * +#* please place them in `freetype/lib/arch/'. * +#* * +#* * +#* This file is to be included by the FreeType Makefile.lib, located in * +#* the `freetype/lib' directory. Here is the list of the variables that * +#* must be defined to use it: * +#* * +#* * +#* BASE_DIR: The location of the base layer's directory. This is * +#* usually `freetype/lib/base'. * +#* * +#* ARCH_DIR: The location of the architecture-dependent directory. * +#* This is usually `freetype/lib/arch/'. * +#* * +#* DRIVERS_DIR: The location of the font driver sub-dirs, usually * +#* `freetype/lib/drivers'. * +#* * +#* OBJ_DIR: The location where the compiled object(s) file will be * +#* placed. * +#* * +#* BASE_H: A list of pathnames to the base layer's header files on * +#* which the driver depends. * +#* * +#* FT_CFLAGS: A set of flags used for compilation of object files. * +#* This contains at least the include paths of the arch * +#* and base directories + optimization + warnings + ANSI * +#* compliance. * +#* * +#* FT_IFLAG: The flag used to specify an include path on the * +#* compiler command line. For example, with GCC, this is * +#* `-I', while some other compilers use `/i=' or `-J', * +#* etc. * +#* * +#* FT_OBJ: The suffix of an object file for the platform; can be * +#* `o', `obj', `coff', `tco', etc. depending on the * +#* platform. * +#* * +#* * +#* It also updates the following variables defined and used in the main * +#* Makefile: * +#* * +#* DRV_OBJ_S: The list of driver object files in * +#* single-object mode. * +#* * +#* DRV_OBJ_M: The list of driver object files in * +#* multiple-objects mode. * +#* * +#* FTINIT_DRIVER_PATHS: The list of include paths used to compile the * +#* `ftinit' component which registers all font * +#* drivers in the FT_Init_FreeType() function. * +#* * +#* FTINIT_DRIVER_H: The list of header dependencies used to * +#* compile the `ftinit' component. * +#* * +#* FTINIT_DRIVER_MACROS: The list of macros to be defined when * +#* compiling the `ftinit' component. * +#* * +#* `Single-object compilation' means that each font driver is compiled * +#* into a single object file. This is useful to get rid of all * +#* driver-specific entries. * +#* * +#**************************************************************************** + +ifndef SFNT_INCLUDE +SFNT_INCLUDED := 1 + +include $(SRC_)shared/rules.mk + +# SFNT driver directory +# +SFNT_DIR := $(SRC_)sfnt +SFNT_DIR_ := $(SFNT_DIR)$(SEP) + +# additional include flags used when compiling the driver +# +SFNT_INCLUDE := $(SHARED) $(SFNT_DIR) + + +# compilation flags for the driver +# +SFNT_CFLAGS := $(SFNT_INCLUDE:%=$I%) +SFNT_COMPILE := $(FT_CC) $(SFNT_CFLAGS) + + +# TrueType 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_)sfdriver.c \ + + +# TrueType driver headers +# +SFNT_DRV_H := $(SHARED_H) \ + $(SFNT_DIR_)sfconfig.h \ + $(SFNT_DIR_)ttload.h \ + $(SFNT_DIR_)ttsbit.h \ + $(SFNT_DIR_)ttcmap.h \ + $(SFNT_DIR_)ttpost.h + + +# driver object(s) +# +# SFNT_DRV_OBJ_M is used during `debug' builds +# SFNT_DRV_OBJ_S is used during `release' builds +# +SFNT_DRV_OBJ_M := $(SFNT_DRV_SRC:$(SFNT_DIR_)%.c=$(OBJ_)%.$O) +SFNT_DRV_OBJ_S := $(OBJ_)sfnt.$O + + +# driver root source file(s) +# +SFNT_DRV_SRC_M := $(SFNT_DRV_SRC) +SFNT_DRV_SRC_S := $(SFNT_DIR_)sfnt.c + + +# driver - single object +# +# the driver is recompiled if any of the header or source files is changed +# as well as any of the shared source files found in `shared/sfnt' +# +$(SFNT_DRV_OBJ_S): $(BASE_H) $(SHARED_H) $(SFNT_DRV_H) $(SFNT_DRV_SRC) $(SFNT_DRV_SRC_S) + $(SFNT_COMPILE) $T$@ $(SFNT_DRV_SRC_S) + + + +# driver - multiple objects +# +# All objects are recompiled if any of the header files is changed +# +$(OBJ_)tt%.$O: $(SFNT_DIR_)tt%.c $(BASE_H) $(SHARED_H) $(SFNT_DRV_H) + $(SFNT_COMPILE) $T$@ $< + +$(OBJ_)sf%.$O: $(SFNT_DIR_)sf%.c $(BASE_H) $(SHARED_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) + + +# update `ftinit' variables +# +FTINIT_DRIVER_PATHS += $(SFNT_DIR) $(SHARED) +FTINIT_DRIVER_H += $(SFNT_DRV_H) +FTINIT_DRIVER_MACROS += FT_SUPPORT_SFNT + +endif +# END diff --git a/src/sfnt/sfconfig.h b/src/sfnt/sfconfig.h new file mode 100644 index 000000000..0c16b9d5f --- /dev/null +++ b/src/sfnt/sfconfig.h @@ -0,0 +1,51 @@ +/***************************************************************************/ +/* */ +/* sfconfig.h */ +/* */ +/* the `sfnt' driver configuration file. */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 configure various aspects of the TrueType */ + /* driver. */ + /* */ + /*************************************************************************/ + + +#ifndef SFCONFIG_H +#define SFCONFIG_H + + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_EMBEDDED_BITMAPS if you want to support */ + /* embedded bitmaps in the TrueType/OpenType driver. */ + /* */ +#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. */ + /* */ +#define TT_CONFIG_OPTION_POSTSCRIPT_NAMES + + +#endif /* SFCONFIG_H */ + + +/* END */ diff --git a/src/sfnt/sfdriver.c b/src/sfnt/sfdriver.c new file mode 100644 index 000000000..0f173fa34 --- /dev/null +++ b/src/sfnt/sfdriver.c @@ -0,0 +1,72 @@ +#include +#include +#include +#include +#include +#include +#include + + static const SFNT_Interface sfnt_interface = + { + TT_Goto_Table, + + TT_Load_Any, + 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, + +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + /* see `ttsbit.h' */ + TT_Load_SBit_Strikes, + TT_Load_SBit_Image, + TT_Free_SBit_Strikes, +#else + 0, + 0, + 0, +#endif + + /* see `ttpost.h' */ +#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES + TT_Get_PS_Name, + TT_Free_Post_Names, +#else + 0, + 0, +#endif + + /* see `ttcmap.h' */ + TT_CharMap_Load, + TT_CharMap_Free, + }; + + + EXPORT_FUNC + const FT_DriverInterface sfnt_driver_interface = + { + sizeof(FT_DriverRec), + 0, + 0, + 0, + + "sfnt", /* driver name */ + 1, /* driver version */ + 2, /* driver requires FreeType 2 or above */ + + (void*)&sfnt_interface + }; + diff --git a/src/sfnt/sfdriver.h b/src/sfnt/sfdriver.h new file mode 100644 index 000000000..fd10d88a6 --- /dev/null +++ b/src/sfnt/sfdriver.h @@ -0,0 +1,83 @@ +/***************************************************************************/ +/* */ +/* sfdriver.h */ +/* */ +/* High-level SFNT driver interface (specification). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 +#include + + EXPORT_DEF + const FT_DriverInterface sfnt_driver_interface; + + + +/************************************************************************* + * + * Here is a template of the code that should appear in each + * font driver's _interface_ file (the one included by "ftinit.c"). + * + * It is used to build, at compile time, a simple linked list of + * the interfaces of the drivers which have been #included in + * "ftinit.c". See the source code of the latter file for details + * + * (Note that this is only required when you want your driver included + * in the set of default drivers loaded by FT_Init_FreeType. Other + * drivers can still be added manually at runtime with FT_Add_Driver. + * + * { + * #ifdef FTINIT_DRIVER_CHAIN + * + * static + * const FT_DriverChain ftinit__driver_chain = + * { + * FT_INIT_LAST_DRIVER_CHAIN, + * &_driver_interface + * }; + * + * #undef FT_INIT_LAST_DRIVER_CHAIN + * #define FT_INIT_LAST_DRIVER_CHAIN &ftinit__driver_chain + * + * #endif + * } + * + * replace with your driver's prefix + * + *************************************************************************/ + + +#ifdef FTINIT_DRIVER_CHAIN + + static + const FT_DriverChain ftinit_sfnt_driver_chain = + { + FT_INIT_LAST_DRIVER_CHAIN, + &sfnt_driver_interface + }; + +#undef FT_INIT_LAST_DRIVER_CHAIN +#define FT_INIT_LAST_DRIVER_CHAIN &ftinit_sfnt_driver_chain + +#endif /* FTINIT_DRIVER_CHAIN */ + + + +#endif /* SFDRIVER_H */ + + +/* END */ diff --git a/src/sfnt/sfnt.c b/src/sfnt/sfnt.c new file mode 100644 index 000000000..d8eb06b72 --- /dev/null +++ b/src/sfnt/sfnt.c @@ -0,0 +1,15 @@ +#include +#include +#include + +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS +#include +#endif + +#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES +#include +#endif + +#include + + diff --git a/src/sfnt/ttcmap.c b/src/sfnt/ttcmap.c new file mode 100644 index 000000000..1187e4ef6 --- /dev/null +++ b/src/sfnt/ttcmap.c @@ -0,0 +1,508 @@ +/***************************************************************************/ +/* */ +/* ttcmap.c */ +/* */ +/* TrueType character mapping table (cmap) support (body). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 + +/* required by the tracing mode */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_ttcmap + + + static TT_UInt code_to_index0( TT_CMapTable* charmap, TT_ULong char_code ); + static TT_UInt code_to_index2( TT_CMapTable* charmap, TT_ULong char_code ); + static TT_UInt code_to_index4( TT_CMapTable* charmap, TT_ULong char_code ); + static TT_UInt code_to_index6( TT_CMapTable* charmap, TT_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. */ + /* */ + /* */ + /* 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 + TT_Error TT_CharMap_Load( TT_Face face, + TT_CMapTable* cmap, + FT_Stream stream ) + { + TT_Error error; + FT_Memory memory; + TT_UShort num_SH, num_Seg, i; + + TT_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( (void*)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, TT_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, TT_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, TT_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; + 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, + TT_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. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + LOCAL_FUNC + TT_Error TT_CharMap_Free( TT_Face face, + TT_CMapTable* cmap ) + { + FT_Memory memory; + + + if ( !cmap ) + return TT_Err_Ok; + + memory = face->root.driver->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 + TT_UInt code_to_index0( TT_CMapTable* cmap, + TT_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 + TT_UInt code_to_index2( TT_CMapTable* cmap, + TT_ULong charCode ) + { + TT_UInt result, index1, offset; + TT_UInt char_lo; + TT_ULong char_hi; + TT_CMap2SubHeader* sh2; + TT_CMap2* cmap2; + + cmap2 = &cmap->c.cmap2; + result = 0; + char_lo = (TT_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 wether 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 + TT_UInt code_to_index4( TT_CMapTable* cmap, + TT_ULong charCode ) + { + TT_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; + + for ( ; seg4 < limit; seg4++ ) + { + if ( charCode <= seg4->endCount ) + { + /* the ranges are sorted in increasing order, if we're out of */ + /* the range here, the char code isn't in the charmap, so exit */ + if ( charCode < seg4->startCount ) + break; + + /* when 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) + - (segCount-1); + + if ( index1 < cmap4->numGlyphId && + cmap4->glyphIdArray[index1] != 0 ) + { + result = (cmap4->glyphIdArray[index1] + seg4->idDelta) & 0xFFFF; + } + } + break; + } + } + + 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 + TT_UInt code_to_index6( TT_CMapTable* cmap, + TT_ULong charCode ) + { + TT_CMap6* cmap6; + TT_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/src/sfnt/ttcmap.h b/src/sfnt/ttcmap.h new file mode 100644 index 000000000..d5da24000 --- /dev/null +++ b/src/sfnt/ttcmap.h @@ -0,0 +1,84 @@ +/***************************************************************************/ +/* */ +/* ttcmap.h */ +/* */ +/* TrueType character mapping table (cmap) support (specification). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 + + + /*************************************************************************/ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* cmap :: A pointer to a cmap object. */ + /* */ + /* */ + /* 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_DEF + TT_Error TT_CharMap_Load( TT_Face face, + TT_CMapTable* cmap, + FT_Stream input ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_CharMap_Free */ + /* */ + /* */ + /* Destroys a character mapping table. */ + /* */ + /* */ + /* face :: A handle to the parent face object. */ + /* cmap :: A handle to a cmap object. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + LOCAL_DEF + TT_Error TT_CharMap_Free( TT_Face face, + TT_CMapTable* cmap ); + +#ifdef __cplusplus + } +#endif + +#endif /* TTCMAP_H */ + + +/* END */ diff --git a/src/sfnt/ttload.c b/src/sfnt/ttload.c new file mode 100644 index 000000000..dbdde79ca --- /dev/null +++ b/src/sfnt/ttload.c @@ -0,0 +1,1477 @@ +/***************************************************************************/ +/* */ +/* ttload.c */ +/* */ +/* TrueType tables loader (body). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/* */ +/* WARNING: This file should not be compiled directly; it is meant to be */ +/* included in the source of several font drivers (i.e., the TTF */ +/* and OTF drivers). */ +/* */ +/***************************************************************************/ + + +#include + +#include +#include +#include +#include + +/* required by the tracing mode */ +#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. */ + /* */ + /* */ + /* pointer to table directory entry. 0 if not found.. */ + /* */ + EXPORT_FUNC + TT_Table* TT_LookUp_Table( TT_Face face, + TT_ULong tag ) + { + TT_Table* entry; + TT_Table* limit; + + FT_TRACE4(( "TT_LookUp_Table( %08lx, %c%c%c%c )\n", + (TT_Long)face, + (TT_Char)(tag >> 24), + (TT_Char)(tag >> 16), + (TT_Char)(tag >> 8), + (TT_Char)(tag) )); + + entry = face->dir_tables; + limit = entry + face->num_tables; + for ( ; entry < limit; entry++ ) + { + if ( entry->Tag == tag ) + return entry; + } + FT_TRACE4(( " 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 */ + /* */ + /* */ + /* pointer to table directory entry. 0 if not found.. */ + /* */ + EXPORT_FUNC + TT_Error TT_Goto_Table( TT_Face face, + TT_ULong tag, + FT_Stream stream, + TT_ULong *length ) + { + TT_Table* table; + TT_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_Directory */ + /* */ + /* */ + /* Loads the table directory into a face object. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: The input stream. */ + /* faceIndex :: The index of the TrueType font, if we're opening a */ + /* collection. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + /* */ + /* The stream cursor must be at the font file's origin */ + /* */ + LOCAL_FUNC + TT_Error TT_Load_Directory( TT_Face face, + FT_Stream stream, + TT_Long faceIndex ) + { + TT_Error error; + FT_Memory memory = stream->memory; + + TT_TableDir tableDir; + TT_ULong tag; + + TT_Table *entry, *limit; + + + FT_TRACE2(( "TT_Load_Directory( %08lx, %ld )\n", + (TT_Long)face, faceIndex )); + + face->ttc_header.Tag = 0; + face->ttc_header.version = 0; + face->ttc_header.DirCount = 0; + + face->num_tables = 0; + + /* first of all, read the first 4 bytes. If it's `ttcf', then the */ + /* file is a TrueType collection, otherwise it must be a normal */ + /* TrueType file.. */ + + if ( READ_ULong(tag) ) + goto Exit; + + if ( tag == TTAG_ttcf ) + { + TT_Int n; + + FT_TRACE4(( "TT_Load_Directory: file is a collection\n" )); + + /* it's a TrueType collection, i.e. a file containing several */ + /* font files. Read the font directory now */ + /* */ + if ( ACCESS_Frame( 8 ) ) goto Exit; + + face->ttc_header.version = GET_Long(); + face->ttc_header.DirCount = GET_Long(); + + FORGET_Frame(); + + /* now read the offsets of each font in the file */ + /* */ + if ( ALLOC_ARRAY( face->ttc_header.TableDirectory, + face->ttc_header.DirCount, + TT_ULong ) || + ACCESS_Frame( face->ttc_header.DirCount * 4L ) ) + goto Exit; + + for ( n = 0; n < face->ttc_header.DirCount; n++ ) + face->ttc_header.TableDirectory[n] = GET_ULong(); + + FORGET_Frame(); + + /* check face index */ + if (faceIndex >= face->ttc_header.DirCount) + { + error = TT_Err_Bad_Argument; + goto Exit; + } + + /* if we're checking the font format, exit immediately */ + if (faceIndex < 0) + goto Exit; + + /* seek to the appropriate TrueType file, then read tag */ + if ( FILE_Skip( face->ttc_header.TableDirectory[faceIndex] - 12 ) || + READ_Long( tableDir.version ) ) + goto Exit; + } + else + { + FT_TRACE6(( "TT_Load_Directory: file is not a collection\n" )); + /* the file isn't a collection, exit if we're asking for a */ + /* collected font.. */ + if (faceIndex > 0) + { + error = TT_Err_File_Is_Not_Collection; + goto Exit; + } + + tableDir.version = tag; + } + + if ( ACCESS_Frame( 8L ) ) + goto Exit; + + tableDir.numTables = GET_UShort(); + + tableDir.searchRange = GET_UShort(); + tableDir.entrySelector = GET_UShort(); + tableDir.rangeShift = GET_UShort(); + + FORGET_Frame(); + + FT_TRACE2(( "-- Tables count : %12u\n", tableDir.numTables )); + FT_TRACE2(( "-- Format version : %08lx\n", tableDir.version )); + + /* Check that we have a `sfnt' format there */ + /* We must also be able to accept Mac/GX fonts, as well as OT ones */ + + if ( tableDir.version != 0x00010000 && /* MS fonts */ + tableDir.version != TTAG_true && /* Mac fonts */ + tableDir.version != TTAG_OTTO ) /* OT-Type2 fonts */ + { + FT_TRACE2(( "[not a valid TTF or OTF font]" )); + error = TT_Err_Invalid_File_Format; + goto Exit; + } + + /* if we're performing a font format check, exit immediately */ + /* with success */ + if ( faceIndex < 0 ) + goto Exit; + + face->num_tables = tableDir.numTables; + + 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", + (TT_Char)(entry->Tag >> 24), + (TT_Char)(entry->Tag >> 16), + (TT_Char)(entry->Tag >> 8 ), + (TT_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. Used by the */ + /* TT_Get_Font_Data() API function. */ + /* */ + /* */ + /* 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. */ + /* */ + LOCAL_FUNC + TT_Error TT_Load_Any( TT_Face face, + TT_ULong tag, + TT_Long offset, + void* buffer, + TT_Long* length ) + { + TT_Error error; + FT_Stream stream; + TT_Table* table; + TT_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 use want 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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_FUNC + TT_Error TT_Load_Header( TT_Face face, + FT_Stream stream ) + { + TT_Error error; + TT_Header* header; + + + FT_TRACE2(( "Load_TT_Header( %08lx )\n", (TT_Long)face )); + + error = face->goto_table( face, TTAG_head, stream, 0 ); + if ( error ) + { + FT_TRACE0(( "Font Header is missing!\n" )); + goto Exit; + } + + if ( ACCESS_Frame( 54L ) ) + goto Exit; + + header = &face->header; + + header->Table_Version = GET_ULong(); + header->Font_Revision = GET_ULong(); + + header->CheckSum_Adjust = GET_Long(); + header->Magic_Number = GET_Long(); + + header->Flags = GET_UShort(); + header->Units_Per_EM = GET_UShort(); + + header->Created [0] = GET_Long(); + header->Created [1] = GET_Long(); + header->Modified[0] = GET_Long(); + header->Modified[1] = GET_Long(); + + header->xMin = GET_Short(); + header->yMin = GET_Short(); + header->xMax = GET_Short(); + header->yMax = GET_Short(); + + header->Mac_Style = GET_UShort(); + header->Lowest_Rec_PPEM = GET_UShort(); + + header->Font_Direction = GET_Short(); + header->Index_To_Loc_Format = GET_Short(); + header->Glyph_Data_Format = GET_Short(); + + FORGET_Frame(); + + 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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_FUNC + TT_Error TT_Load_MaxProfile( TT_Face face, + FT_Stream stream ) + { + TT_Error error; + TT_MaxProfile* maxProfile = &face->max_profile; + + + FT_TRACE2(( "Load_TT_MaxProfile( %08lx )\n", (TT_Long)face )); + + error = face->goto_table( face, TTAG_maxp, stream, 0 ); + if (error) goto Exit; + + if ( ACCESS_Frame( 32L ) ) + goto Exit; + + /* read frame data into face table */ + maxProfile->version = GET_ULong(); + maxProfile->numGlyphs = GET_UShort(); + + maxProfile->maxPoints = GET_UShort(); + maxProfile->maxContours = GET_UShort(); + maxProfile->maxCompositePoints = GET_UShort(); + maxProfile->maxCompositeContours = GET_UShort(); + + maxProfile->maxZones = GET_UShort(); + maxProfile->maxTwilightPoints = GET_UShort(); + + maxProfile->maxStorage = GET_UShort(); + maxProfile->maxFunctionDefs = GET_UShort(); + maxProfile->maxInstructionDefs = GET_UShort(); + maxProfile->maxStackElements = GET_UShort(); + maxProfile->maxSizeOfInstructions = GET_UShort(); + maxProfile->maxComponentElements = GET_UShort(); + maxProfile->maxComponentDepth = GET_UShort(); + + FORGET_Frame(); + + /* 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 = (TT_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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + static + TT_Error TT_Load_Metrics( TT_Face face, + FT_Stream stream, + TT_Bool vertical ) + { + TT_Error error; + FT_Memory memory = stream->memory; + + TT_ULong table_len; + TT_Long num_shorts, num_longs, num_shorts_checked; + + TT_LongMetrics** longs; + TT_ShortMetrics** shorts; + + FT_TRACE2(( "TT_Load_%s_Metrics( %08lx )\n", + vertical ? "Vertical" : "Horizontal", (TT_Long)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 the 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(( "!! more metrics than glyphs!\n" )); + 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, nothing serious will happen */ + if ( num_shorts > num_shorts_checked && num_shorts_checked > 0 ) + { + TT_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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_FUNC + TT_Error TT_Load_Metrics_Header( TT_Face face, + FT_Stream stream, + TT_Bool vertical ) + { + TT_Error error; + TT_HoriHeader* header; + + 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 ( ACCESS_Frame( 36L ) ) + goto Exit; + + header->Version = GET_ULong(); + header->Ascender = GET_Short(); + header->Descender = GET_Short(); + header->Line_Gap = GET_Short(); + + header->advance_Width_Max = GET_UShort(); + + header->min_Left_Side_Bearing = GET_Short(); + header->min_Right_Side_Bearing = GET_Short(); + header->xMax_Extent = GET_Short(); + header->caret_Slope_Rise = GET_Short(); + header->caret_Slope_Run = GET_Short(); + + header->Reserved[0] = GET_Short(); /* this is caret_Offset for + vertical headers */ + header->Reserved[1] = GET_Short(); + header->Reserved[2] = GET_Short(); + header->Reserved[3] = GET_Short(); + header->Reserved[4] = GET_Short(); + + header->metric_Data_Format = GET_Short(); + header->number_Of_HMetrics = GET_UShort(); + + FORGET_Frame(); + + 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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_FUNC + TT_Error TT_Load_Names( TT_Face face, FT_Stream stream ) + { + TT_Error error; + FT_Memory memory = stream->memory; + + TT_ULong table_pos, table_len; + TT_ULong storageSize; + + TT_NameTable* names; + + + 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(); + + if ( ACCESS_Frame( 6L ) ) + goto Exit; + + names = &face->name_table; + + /* Load the initial names data. */ + names->format = GET_UShort(); + names->numNameRecords = GET_UShort(); + names->storageOffset = GET_UShort(); + + FORGET_Frame(); + + /* 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 ++ ) + { + TT_ULong upper; + + cur->platformID = GET_UShort(); + cur->encodingID = GET_UShort(); + cur->languageID = GET_UShort(); + cur->nameID = GET_UShort(); + cur->stringLength = GET_UShort(); + cur->stringOffset = GET_UShort(); + + upper = (TT_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, + (void*)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++ ) + { + TT_UInt j; + + FT_TRACE2(( "%d %d %x %d ", + 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++ ) + { + TT_Char c = *(cur->string + j); + + if ( (TT_Byte)c < 128 ) + FT_TRACE2(( "%c", c )); + } + } + } + FT_TRACE2(( "\n" )); +#endif + } + FT_TRACE2(( "loaded\n" )); + + 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->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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_FUNC + TT_Error TT_Load_CMap( TT_Face face, + FT_Stream stream ) + { + TT_Error error; + FT_Memory memory = stream->memory; + TT_Long off, cur_off, table_start; + TT_CMapDir cmap_dir; + + 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 ( ACCESS_Frame( 4L ) ) /* 4 bytes cmap header */ + goto Exit; + + cmap_dir.tableVersionNumber = GET_UShort(); + cmap_dir.numCMaps = GET_UShort(); + + FORGET_Frame(); + + off = FILE_Pos(); /* save offset to cmapdir[] which follows */ + + /* save 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; + + for ( ; charmap < limit; charmap++ ) + { + TT_CMapTable* cmap; + + charmap->root.face = (FT_Face)face; + cmap = &charmap->cmap; + + if ( FILE_Seek( off ) || + ACCESS_Frame( 8L ) ) + goto Exit; + + cmap->loaded = FALSE; + cmap->platformID = GET_UShort(); + cmap->platformEncodingID = GET_UShort(); + + cur_off = GET_Long(); + + FORGET_Frame(); + + off = FILE_Pos(); + + if ( FILE_Seek( table_start + cur_off ) || + ACCESS_Frame( 6L ) ) + goto Exit; + + cmap->format = GET_UShort(); + cmap->length = GET_UShort(); + cmap->version = GET_UShort(); + + FORGET_Frame(); + + cmap->offset = FILE_Pos(); + charmap++; + } + } + + 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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_FUNC + TT_Error TT_Load_OS2( TT_Face face, + FT_Stream stream ) + { + TT_Error error; + TT_Int j; + TT_OS2* os2; + + + 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; + } + + if ( ACCESS_Frame( 78L ) ) + goto Exit; + + os2 = &face->os2; + + os2->version = GET_UShort(); + os2->xAvgCharWidth = GET_Short(); + os2->usWeightClass = GET_UShort(); + os2->usWidthClass = GET_UShort(); + os2->fsType = GET_Short(); + os2->ySubscriptXSize = GET_Short(); + os2->ySubscriptYSize = GET_Short(); + os2->ySubscriptXOffset = GET_Short(); + os2->ySubscriptYOffset = GET_Short(); + os2->ySuperscriptXSize = GET_Short(); + os2->ySuperscriptYSize = GET_Short(); + os2->ySuperscriptXOffset = GET_Short(); + os2->ySuperscriptYOffset = GET_Short(); + os2->yStrikeoutSize = GET_Short(); + os2->yStrikeoutPosition = GET_Short(); + os2->sFamilyClass = GET_Short(); + + for ( j = 0; j < 10; j++ ) + os2->panose[j] = GET_Byte(); + + os2->ulUnicodeRange1 = GET_ULong(); + os2->ulUnicodeRange2 = GET_ULong(); + os2->ulUnicodeRange3 = GET_ULong(); + os2->ulUnicodeRange4 = GET_ULong(); + + for ( j = 0; j < 4; j++ ) + os2->achVendID[j] = GET_Byte(); + + os2->fsSelection = GET_UShort(); + os2->usFirstCharIndex = GET_UShort(); + os2->usLastCharIndex = GET_UShort(); + os2->sTypoAscender = GET_Short(); + os2->sTypoDescender = GET_Short(); + os2->sTypoLineGap = GET_Short(); + os2->usWinAscent = GET_UShort(); + os2->usWinDescent = GET_UShort(); + + FORGET_Frame(); + + os2->ulCodePageRange1 = 0; + os2->ulCodePageRange2 = 0; + + if ( os2->version >= 0x0001 ) + { + /* only version 1 tables */ + + if ( ACCESS_Frame( 8L ) ) /* read into frame */ + goto Exit; + + os2->ulCodePageRange1 = GET_ULong(); + os2->ulCodePageRange2 = GET_ULong(); + + FORGET_Frame(); + } + + 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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_FUNC + TT_Error TT_Load_PostScript( TT_Face face, + FT_Stream stream ) + { + TT_Error error; + TT_Postscript* post = &face->postscript; + + FT_TRACE2(( "PostScript " )); + + error = face->goto_table( face, TTAG_post, stream, 0 ); + if (error) + return TT_Err_Post_Table_Missing; + + if ( ACCESS_Frame( 32L ) ) + return error; + + /* read frame data into face table */ + + post->FormatType = GET_ULong(); + post->italicAngle = GET_ULong(); + post->underlinePosition = GET_Short(); + post->underlineThickness = GET_Short(); + post->isFixedPitch = GET_ULong(); + post->minMemType42 = GET_ULong(); + post->maxMemType42 = GET_ULong(); + post->minMemType1 = GET_ULong(); + post->maxMemType1 = GET_ULong(); + + FORGET_Frame(); + + /* we don't load the glyph names, we do that in another */ + /* module (ttpost). */ + FT_TRACE2(( "loaded\n" )); + + return TT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Gasp */ + /* */ + /* */ + /* Loads the `GASP' table into a face object. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_FUNC + TT_Error TT_Load_Gasp( TT_Face face, + FT_Stream stream ) + { + TT_Error error; + FT_Memory memory = stream->memory; + + TT_UInt j,num_ranges; + TT_GaspRange* gaspranges; + + + FT_TRACE2(( "TT_Load_Gasp( %08lx )\n", (TT_Long)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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_FUNC + TT_Error TT_Load_Kern( TT_Face face, + FT_Stream stream ) + { + TT_Error error; + FT_Memory memory = stream->memory; + + TT_UInt n, num_tables, version; + + /* the kern table is optional. exit silently if it's 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++ ) + { + TT_UInt coverage; + TT_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 ) + { + TT_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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_FUNC + TT_Error TT_Load_Hdmx( TT_Face face, + FT_Stream stream ) + { + TT_Error error; + FT_Memory memory = stream->memory; + + TT_Hdmx* hdmx = &face->hdmx; + TT_Long num_glyphs; + TT_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 ) + { + TT_Int n; + FT_Memory memory = face->root.driver->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/src/sfnt/ttload.h b/src/sfnt/ttload.h new file mode 100644 index 000000000..c9ea0a7f0 --- /dev/null +++ b/src/sfnt/ttload.h @@ -0,0 +1,382 @@ +/***************************************************************************/ +/* */ +/* ttload.h */ +/* */ +/* Load the basic TrueType tables, i.e., tables that can be either in */ +/* TTF or OTF font (specification). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 +/* +#include +*/ + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /* */ + /* */ + /* TT_LookUp_Table */ + /* */ + /* */ + /* Looks for a TrueType table by name. */ + /* */ + /* */ + /* face :: A face object handle. */ + /* tag :: The searched tag. */ + /* */ + /* */ + /* pointer to table directory entry. 0 if not found.. */ + /* */ + EXPORT_DEF + TT_Table* TT_LookUp_Table( TT_Face face, + TT_ULong tag ); + + + /*************************************************************************/ + /* */ + /* */ + /* 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 */ + /* */ + /* */ + /* pointer to table directory entry. 0 if not found.. */ + /* */ + EXPORT_DEF + TT_Error TT_Goto_Table( TT_Face face, + TT_ULong tag, + FT_Stream stream, + TT_ULong *length ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Directory */ + /* */ + /* */ + /* Loads the table directory into a face object. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: The input stream. */ + /* faceIndex :: The index of the TrueType font, if we're opening a */ + /* collection. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + /* */ + /* The stream cursor must be at the font file's origin */ + /* */ + LOCAL_DEF + TT_Error TT_Load_Directory( TT_Face face, + FT_Stream stream, + TT_Long faceIndex ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Any */ + /* */ + /* */ + /* Loads any font table into client memory. Used by the */ + /* TT_Get_Font_Data() API function. */ + /* */ + /* */ + /* 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. */ + /* */ + LOCAL_DEF + TT_Error TT_Load_Any( TT_Face face, + TT_ULong tag, + TT_Long offset, + void* buffer, + TT_Long* length ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Header */ + /* */ + /* */ + /* Loads the TrueType font header. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_DEF + TT_Error TT_Load_Header( TT_Face face, + FT_Stream stream ); + + + /*************************************************************************/ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_DEF + TT_Error TT_Load_Metrics_Header( TT_Face face, + FT_Stream stream, + TT_Bool vertical ); + + + LOCAL_DEF + TT_Error TT_Load_CMap( TT_Face face, + FT_Stream stream ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_MaxProfile */ + /* */ + /* */ + /* Loads the maximum profile into a face object. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_DEF + TT_Error TT_Load_MaxProfile( TT_Face face, + FT_Stream stream ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Names */ + /* */ + /* */ + /* Loads the name records. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_DEF + TT_Error TT_Load_Names( TT_Face face, + FT_Stream stream ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_OS2 */ + /* */ + /* */ + /* Loads the OS2 table. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: A handle to the input stream. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_DEF + TT_Error TT_Load_OS2( TT_Face face, + FT_Stream stream ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Postscript */ + /* */ + /* */ + /* Loads the Postscript table. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: A handle to the input stream. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_DEF + TT_Error TT_Load_PostScript( TT_Face face, + FT_Stream stream ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Hdmx */ + /* */ + /* */ + /* Loads the horizontal device metrics table. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: A handle to the input stream. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_DEF + TT_Error TT_Load_Hdmx( TT_Face face, + FT_Stream stream ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Free_Names */ + /* */ + /* */ + /* Frees the name records. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_DEF + void TT_Free_Names( TT_Face face ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Free_Hdmx */ + /* */ + /* */ + /* Frees the horizontal device metrics table. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_DEF + void TT_Free_Hdmx ( TT_Face face ); + + + /*************************************************************************/ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_DEF + TT_Error TT_Load_Kern( TT_Face face, + FT_Stream stream ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Gasp */ + /* */ + /* */ + /* Loads the `GASP' table into a face object. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_DEF + TT_Error TT_Load_Gasp( TT_Face face, + FT_Stream stream ); + + +#endif /* TTLOAD_H */ + + +/* END */ diff --git a/src/sfnt/ttpost.c b/src/sfnt/ttpost.c new file mode 100644 index 000000000..953118ff3 --- /dev/null +++ b/src/sfnt/ttpost.c @@ -0,0 +1,700 @@ +/***************************************************************************/ +/* */ +/* ttpost.c */ +/* */ +/* Postscript names table processing (body). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 +#include +#include + + /* the 258 default Mac PS glyph names */ + + const TT_String* TT_Mac_Postscript_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", + }; + + + static + TT_Error Load_Format_20( TT_Face face, + FT_Stream stream ) + { + FT_Memory memory = stream->memory; + TT_Error error; + + TT_Int num_glyphs; + TT_Int num_names; + + TT_UShort* glyph_indices = 0; + TT_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 */ + { + TT_Int n; + + if ( ALLOC_ARRAY ( glyph_indices, num_glyphs, TT_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 */ + { + TT_Int n; + + num_names = 0; + + for ( n = 0; n < num_glyphs; n++ ) + { + TT_Int index; + + index = glyph_indices[n]; + if ( index >= 258 ) + { + index -= 257; + if ( index > num_names ) + num_names = index; + } + } + } + + /* now load the name strings */ + { + TT_Int n; + + if ( ALLOC_ARRAY( name_strings, num_names, TT_Char* ) ) + goto Fail; + + for ( n = 0; n < num_names; n++ ) + { + TT_UInt len; + + if ( READ_Byte ( len ) || + ALLOC_ARRAY( name_strings[n], len+1, TT_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: + { + TT_Int n; + + for ( n = 0; n < num_names; n++ ) + FREE( name_strings[n] ); + } + + Fail: + FREE( name_strings ); + FREE( glyph_indices ); + + Exit: + return error; + } + + + static + TT_Error Load_Format_25( TT_Face face, + FT_Stream stream ) + { + FT_Memory memory = stream->memory; + TT_Error error; + + TT_Int num_glyphs; + TT_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 */ + { + TT_Int n; + + + for ( n = 0; n < num_glyphs; n++ ) + { + TT_Long index = (TT_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 + TT_Error Load_Post_Names( TT_Face face ) + { + FT_Stream stream; + TT_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 0x00020000: + error = Load_Format_20( face, stream ); + break; + + case 0x00028000: + 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 0x00020000: + { + TT_Post_20* table = &names->names.format_20; + TT_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 0x00028000: + { + 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. */ + /* */ + /* */ + /* 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! */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + EXPORT_FUNC + TT_Error TT_Get_PS_Name( TT_Face face, + TT_UInt index, + TT_String** PSname ) + { + TT_Error error; + TT_Post_Names* names; + + if ( !face ) + return TT_Err_Invalid_Face_Handle; + + if ( index >= (TT_UInt)face->root.num_glyphs ) + return TT_Err_Invalid_Glyph_Index; + + names = &face->postscript_names; + + /* `.notdef' by default */ + *PSname = (TT_String*)TT_Mac_Postscript_Names[0]; + + switch ( face->postscript.FormatType ) + { + case 0x00010000: + if ( index < 258 ) /* paranoid checking */ + *PSname = (TT_String*)TT_Mac_Postscript_Names[index]; + break; + + case 0x00020000: + { + TT_Post_20* table = &names->names.format_20; + + + if ( !names->loaded ) + { + error = Load_Post_Names( face ); + if ( error ) + break; + } + + if ( index < table->num_glyphs ) + { + TT_UShort name_index = table->glyph_indices[index]; + + + if ( name_index < 258 ) + *PSname = (TT_String*)TT_Mac_Postscript_Names[name_index]; + else + *PSname = (TT_String*)table->glyph_names[name_index - 258]; + } + } + break; + + case 0x00028000: + { + 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 = (TT_String*)TT_Mac_Postscript_Names[index]; + } + } + break; + + case 0x00030000: + break; /* nothing to do */ + } + + return TT_Err_Ok; + } + + +/* END */ diff --git a/src/sfnt/ttpost.h b/src/sfnt/ttpost.h new file mode 100644 index 000000000..eeb0bf1a5 --- /dev/null +++ b/src/sfnt/ttpost.h @@ -0,0 +1,87 @@ +/***************************************************************************/ +/* */ +/* ttpost.h */ +/* */ +/* Postcript name table processing for TrueType and OpenType fonts */ +/* (specification). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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. */ + /* */ + /*************************************************************************/ + + +#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 + +#if 0 + /* the 258 standard Mac glyph names, used for format 1.0 and 2.5 */ + LOCAL_DEF + const TT_String* TT_Mac_Postscript_Names[]; +#endif + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Get_PS_Name */ + /* */ + /* */ + /* 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! */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + EXPORT_DEF + TT_Error TT_Get_PS_Name( TT_Face face, + TT_UInt index, + TT_String** PSname ); + + + LOCAL_DEF + void TT_Free_Post_Names( TT_Face face ); + + +#ifdef __cplusplus +} +#endif + + +#endif /* TTPOST_H */ + + +/* END */ diff --git a/src/sfnt/ttsbit.c b/src/sfnt/ttsbit.c new file mode 100644 index 000000000..b7020bbd4 --- /dev/null +++ b/src/sfnt/ttsbit.c @@ -0,0 +1,1437 @@ +/***************************************************************************/ +/* */ +/* ttsbit.c */ +/* */ +/* TrueType and OpenType embedded bitmap support (body). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/* */ +/* WARNING: This file should not be compiled directly, it is meant to be */ +/* included in the source of several font drivers (i.e., the TTF */ +/* and OTF drivers). */ +/* */ +/***************************************************************************/ + + +#include + +#include +#include +#include + + + /*************************************************************************/ + /* */ + /* */ + /* 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, + char* 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; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Small_SBit_Metrics */ + /* */ + /* */ + /* Loads a small bitmap metrics record. */ + /* */ + /* */ + /* stream :: The input stream. */ + /* */ + /* */ + /* metrics :: A small metrics structure. */ + /* */ + static + void TT_Load_Small_SBit_Metrics( TT_SBit_Small_Metrics* metrics, + FT_Stream stream ) + { + metrics->height = GET_Byte(); + metrics->width = GET_Byte(); + metrics->bearingX = GET_Char(); + metrics->bearingY = GET_Char(); + metrics->advance = GET_Byte(); + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_SBit_Metrics */ + /* */ + /* */ + /* Loads a bitmap metrics record. */ + /* */ + /* */ + /* stream :: The input stream. */ + /* */ + /* */ + /* metrics :: A metrics structure. */ + /* */ + static + void TT_Load_SBit_Metrics( TT_SBit_Metrics* metrics, + FT_Stream stream ) + { + metrics->height = GET_Byte(); + metrics->width = GET_Byte(); + + metrics->horiBearingX = GET_Char(); + metrics->horiBearingY = GET_Char(); + metrics->horiAdvance = GET_Byte(); + + metrics->vertBearingX = GET_Char(); + metrics->vertBearingY = GET_Char(); + metrics->vertAdvance = GET_Byte(); + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_SBit_Line_Metrics */ + /* */ + /* */ + /* Loads a bitmap line metrics record. */ + /* */ + /* */ + /* stream :: The input stream. */ + /* */ + /* */ + /* metrics :: A line metrics structure. */ + /* */ + static + void TT_Load_SBit_Line_Metrics( TT_SBit_Line_Metrics* metrics, + FT_Stream stream ) + { + metrics->ascender = GET_Char(); + metrics->descender = GET_Char(); + metrics->max_width = GET_Byte(); + + metrics->caret_slope_numerator = GET_Char(); + metrics->caret_slope_denominator = GET_Char(); + metrics->caret_offset = GET_Char(); + + metrics->min_origin_SB = GET_Char(); + metrics->min_advance_SB = GET_Char(); + metrics->max_before_BL = GET_Char(); + metrics->min_after_BL = GET_Char(); + metrics->pads[0] = GET_Char(); + metrics->pads[1] = GET_Char(); + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_SBit_Const_Metrics */ + /* */ + /* */ + /* Loads the metrics for `EBLC' index tables format 2 and 5. */ + /* */ + /* */ + /* range :: The target range. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + static + TT_Error Load_SBit_Const_Metrics( TT_SBit_Range* range, + FT_Stream stream ) + { + TT_Error error; + + if ( !ACCESS_Frame( 12L ) ) + { + range->image_size = GET_ULong(); + TT_Load_SBit_Metrics( &range->metrics, stream ); + + FORGET_Frame(); + } + + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + static + TT_Error Load_SBit_Range_Codes( TT_SBit_Range* range, + FT_Stream stream, + TT_Bool load_offsets ) + { + TT_Error error; + TT_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, TT_ULong ) ) + goto Exit; + + size = count * 4L; + } + else + size = count * 2L; + + /* Allocate glyph codes table and access frame */ + if ( ALLOC_ARRAY ( range->glyph_codes, count, TT_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] = (TT_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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + static + TT_Error Load_SBit_Range( TT_SBit_Range* range, + FT_Stream stream ) + { + TT_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 */ + { + TT_ULong num_glyphs, n; + TT_Int size_elem; + TT_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, TT_ULong ) || + + ACCESS_Frame( num_glyphs * size_elem ) ) + goto Exit; + + for ( n = 0; n < num_glyphs; n++ ) + range->glyph_offsets[n] = (TT_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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_FUNC + TT_Error TT_Load_SBit_Strikes( TT_Face face, + FT_Stream stream ) + { + TT_Error error = 0; + FT_Memory memory = stream->memory; + TT_Fixed version; + TT_ULong num_strikes; + TT_ULong table_base; + + + /* this table is optional */ + error = face->goto_table( face, TTAG_EBLC, stream, 0 ); + { + 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 != 0x00020000 || + num_strikes >= 0x10000 ) + { + 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; + TT_ULong count = num_strikes; + + if ( ACCESS_Frame( 48L * num_strikes ) ) + goto Exit; + + while ( count > 0 ) + { + TT_ULong indexTablesSize; + + + strike->ranges_offset = GET_ULong(); + indexTablesSize = GET_ULong(); /* don't save */ + + strike->num_ranges = GET_ULong(); + strike->color_ref = GET_ULong(); + + TT_Load_SBit_Line_Metrics( &strike->hori, stream ); + TT_Load_SBit_Line_Metrics( &strike->vert, stream ); + + strike->start_glyph = GET_UShort(); + strike->end_glyph = GET_UShort(); + strike->x_ppem = GET_Byte(); + strike->y_ppem = GET_Byte(); + strike->bit_depth = GET_Byte(); + strike->flags = GET_Char(); + + count--; + strike++; + } + + FORGET_Frame(); + } + + /* allocate the index ranges for each strike table */ + { + TT_SBit_Strike* strike = face->sbit_strikes; + TT_ULong count = num_strikes; + + + while ( count > 0 ) + { + TT_SBit_Range* range; + TT_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. */ + /* */ + /* */ + /* TrueType error code. 0 means the glyph index was found. */ + /* */ + static + TT_Error Find_SBit_Range( TT_UInt glyph_index, + TT_SBit_Strike* strike, + TT_SBit_Range** arange, + TT_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 ) + { + TT_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: + { + TT_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; + break; + } + } + } + + /* fall-through */ + default: + goto Fail; + } + + /* 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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. Returns */ + /* TT_Err_Invalid_Argument if no sbit exist for the requested glyph. */ + /* */ + static + TT_Error Find_SBit_Image( TT_Face face, + TT_UInt glyph_index, + TT_Int x_ppem, + TT_Int y_ppem, + + TT_SBit_Range** arange, + TT_SBit_Strike** astrike, + TT_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 ) + { + TT_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. */ + /* */ + /* */ + /* TrueType 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 + TT_Error Load_SBit_Metrics( FT_Stream stream, + TT_SBit_Range* range, + TT_SBit_Metrics* metrics ) + { + TT_Error error = TT_Err_Ok; + + + switch ( range->index_format ) + { + case 1: /* variable metrics */ + case 3: + case 4: + { + switch ( range->image_format ) + { + case 1: /* small metrics */ + case 2: + case 8: + { + TT_SBit_Small_Metrics smetrics; + + + /* read small metrics */ + if ( ACCESS_Frame( 5L ) ) + goto Exit; + TT_Load_Small_SBit_Metrics( &smetrics, stream ); + FORGET_Frame(); + + /* 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; + + default: /* big metrics */ + if ( ACCESS_Frame( 8L ) ) + goto Exit; + TT_Load_SBit_Metrics( metrics, stream ); + FORGET_Frame(); + } + } + break; + + default: /* constant metrics */ + *metrics = range->metrics; + } + + 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. */ + /* */ + /* --------- */ + /* | | ----- */ + /* | *** | |***| */ + /* | * | | * | */ + /* | * | ------> | * | */ + /* | * | | * | */ + /* | * | | * | */ + /* | *** | |***| */ + /* --------- ----- */ + /* */ + /***********************************************************************/ + + TT_Int rows, count; + TT_Long line_len; + TT_Byte* line; + + + /***********************************************************************/ + /* */ + /* first of all, checks the top-most lines of the bitmap, and removes */ + /* them if they're empty. */ + /* */ + { + line = (TT_Byte*)map->buffer; + rows = map->rows; + line_len = map->pitch; + + + for ( count = 0; count < rows; count++ ) + { + TT_Byte* cur = line; + TT_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 = (TT_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 = (TT_Byte*)map->buffer + (rows - 1) * line_len; + + for ( count = 0; count < rows; count++ ) + { + TT_Byte* cur = line; + TT_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 + { + TT_Byte* limit; + + + line = (TT_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 = (TT_Byte*)map->buffer; + limit = line + rows * line_len; + + for ( ; line < limit; line += line_len ) + { + TT_Int n, width = map->width; + TT_Byte old; + TT_Byte* cur = line; + + + old = cur[0] << 1; + for ( n = 8; n < width; n += 8 ) + { + TT_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 + { + TT_Int right = map->width-1; + TT_Byte* limit; + TT_Byte mask; + + + line = (TT_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 + TT_Error Load_SBit_Single( FT_Bitmap* map, + TT_Int x_offset, + TT_Int y_offset, + TT_Int pix_bits, + TT_UShort image_format, + TT_SBit_Metrics* metrics, + FT_Stream stream ) + { + TT_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; + } + + { + TT_Int glyph_width = metrics->width; + TT_Int glyph_height = metrics->height; + TT_Int glyph_size; + TT_Int line_bits = pix_bits * glyph_width; + TT_Bool pad_bytes = 0; + + + /* compute size of glyph image */ + switch ( image_format ) + { + case 1: /* byte-padded formats */ + case 6: + { + TT_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, stream->cursor, line_bits, pad_bytes, + x_offset * pix_bits, y_offset ); + + FORGET_Frame(); + } + + Exit: + return error; + } + + + static + TT_Error Load_SBit_Image( TT_SBit_Strike* strike, + TT_SBit_Range* range, + TT_ULong ebdt_pos, + TT_ULong glyph_offset, + FT_Bitmap* map, + TT_Int x_offset, + TT_Int y_offset, + FT_Stream stream, + TT_SBit_Metrics* metrics ) + { + FT_Memory memory = stream->memory; + TT_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 ) + { + TT_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 */ + case 9: + break; + + default: /* invalid image format */ + return TT_Err_Invalid_File_Format; + } + + /* All right, we're in a compound format. First of all, read */ + /* the array of elements */ + { + TT_SBit_Component* components; + TT_SBit_Component* comp; + TT_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; + TT_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. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* */ + /* map :: The target pixmap. */ + /* metrics :: A big sbit metrics structure for the glyph image. */ + /* */ + /* */ + /* TrueType 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 + TT_Error TT_Load_SBit_Image( TT_Face face, + TT_Int x_ppem, + TT_Int y_ppem, + TT_UInt glyph_index, + FT_Stream stream, + FT_Bitmap* map, + TT_SBit_Metrics* metrics ) + { + TT_Error error; + FT_Memory memory = stream->memory; + TT_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) goto Exit; + + ebdt_pos = FILE_Pos(); + + /* clear the bitmap & load the 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; + + /* 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; + + metrics->vertBearingX = -metrics->width / 2; + metrics->vertBearingY = advance / 10; + metrics->vertAdvance = advance * 12 / 10; + } + + /* Crop the bitmap now */ + Crop_Bitmap( map, metrics ); + + Exit: + return error; + } + + +/* END */ diff --git a/src/sfnt/ttsbit.h b/src/sfnt/ttsbit.h new file mode 100644 index 000000000..414ceaed7 --- /dev/null +++ b/src/sfnt/ttsbit.h @@ -0,0 +1,104 @@ +/***************************************************************************/ +/* */ +/* ttsbit.h */ +/* */ +/* TrueType and OpenType embedded bitmap support (specification). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef TTSBIT_H +#define TTSBIT_H + +#include + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_SBit_Strikes */ + /* */ + /* */ + /* Loads the table of embedded bitmap sizes for this face. */ + /* */ + /* */ + /* face :: The target face object. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_DEF + TT_Error TT_Load_SBit_Strikes( TT_Face face, + FT_Stream stream ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Free_SBit_Strikes */ + /* */ + /* */ + /* Releases the embedded bitmap tables. */ + /* */ + /* */ + /* face :: The target face object. */ + /* */ + LOCAL_DEF + void TT_Free_SBit_Strikes( TT_Face face ); + + + /*************************************************************************/ + /* */ + /* */ + /* 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. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* */ + /* map :: The target pixmap. */ + /* metrics :: A big sbit metrics structure for the glyph image. */ + /* */ + /* */ + /* TrueType 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_DEF + TT_Error TT_Load_SBit_Image( TT_Face face, + TT_Int x_ppem, + TT_Int y_ppem, + TT_UInt glyph_index, + FT_Stream stream, + FT_Bitmap* map, + TT_SBit_Metrics* metrics ); + + +#endif /* TTSBIT_H */ + + +/* END */ diff --git a/src/shared/otlayout/otlayout.h b/src/shared/otlayout/otlayout.h new file mode 100644 index 000000000..e606cfb1a --- /dev/null +++ b/src/shared/otlayout/otlayout.h @@ -0,0 +1,372 @@ +/***************************************************************************/ +/* */ +/* otlayout.h */ +/* */ +/* OpenType layout type definitions (specification only). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 OTLAYOUT_H +#define OTLAYOUT_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + + /*************************************************************************/ + /* */ + /* */ + /* OTL_LangSys */ + /* */ + /* */ + /* An OTL LangSys record. */ + /* */ + /* */ + /* lang_tag :: The language tag. */ + /* lang_offset :: The offset of the langsys data in the + /* resource. */ + /* */ + /* lookup_order :: Always 0 for OTL 1.0. */ + /* req_feature_index :: The `required feature' index. */ + /* num_feature_indices :: The number of feature indices. */ + /* feature_indices :: An array of feature indices. */ + /* */ + typedef struct OTL_LangSys_ + { + TT_ULong lang_tag; + TT_ULong lang_offset; + + TT_UShort lookup_order; /* always 0 for TT Open 1.0 */ + TT_UShort req_feature_index; /* required FeatureIndex */ + TT_UShort num_feature_indices; /* number of Feature indices */ + TT_UShort* feature_indices; /* array of Feature indices */ + + } OTL_LangSys; + + + /*************************************************************************/ + /* */ + /* */ + /* OTL_Script */ + /* */ + /* */ + /* An OTL Script record. */ + /* */ + /* */ + /* script_tag :: The script tag. */ + /* script_offset :: The offset of the script data in the resource. */ + /* */ + /* num_langsys :: The number of langsys records. */ + /* langsys :: An array of langsys records. */ + /* langsys_default :: A pointer to the default langsys table for this */ + /* script. */ + /* */ + typedef struct OTL_Script_ + { + TT_ULong script_tag; + TT_ULong script_offset; + + TT_UShort num_langsys; + OTL_LangSys* langsys; + OTL_LangSys* langsys_default; + + } OTL_Script; + + + /*************************************************************************/ + /* */ + /* */ + /* OTL_Script_List */ + /* */ + /* */ + /* An OTL Script List record. */ + /* */ + /* */ + /* num_scripts :: The number of scripts records. */ + /* scripts :: An array of script records. */ + /* */ + typedef struct OTL_Script_List_ + { + TT_UShort num_scripts; + OTL_Script* scripts; + + } OTL_Script_List; + + + /*************************************************************************/ + /* */ + /* */ + /* OTL_Feature */ + /* */ + /* */ + /* An OTL Feature record. */ + /* */ + /* */ + /* feature_tag :: The feature tag. */ + /* feature_offset :: The offset of the feature data in the resource. */ + /* */ + /* feature_params :: Always 0 for OpenType Layout 1.0. */ + /* num_lookups :: The number of lookup indices. */ + /* lookups :: An array of lookup indices. */ + /* */ + typedef struct OTL_Feature_ + { + TT_ULong feature_tag; + TT_ULong feature_offset; + + TT_UShort feature_params; /* always 0 for OpenType Layout 1.0 */ + TT_UShort num_lookups; + TT_UShort* lookups; + + } OTL_Feature; + + + /*************************************************************************/ + /* */ + /* */ + /* OTL_Feature_List */ + /* */ + /* */ + /* An OTL Feature List record. */ + /* */ + /* */ + /* num_features :: The number of features. */ + /* features :: An array of features. */ + /* */ + typedef struct OTL_Feature_List_ + { + TT_UShort num_features; + OTL_Feature* features; + + } OTL_Feature_List; + + + /*************************************************************************/ + /* */ + /* */ + /* OTL_Lookup */ + /* */ + /* */ + /* An OTL Lookup record. */ + /* */ + /* */ + /* lookup_offset :: The offset of the lookup data in the resource. */ + /* lookup_type :: The lookup type. */ + /* lookup_flag :: The lookup bit flags. */ + /* */ + /* num_subtables :: The number of subtables. */ + /* subtable_offsets :: An array of offsets to the subtables. */ + /* subtables :: An array of pointers to the subtable records. */ + /* */ + /* */ + /* The format of each lookup sub-table is determined by the parent */ + /* OpenType table, and cannot be known here. */ + /* */ + /* The `subtable_offsets' array is filled when the lookup table is */ + /* loaded the first time. It is up to OT table handlers to read the */ + /* corresponding sub-table records and store them in the `subtables' */ + /* array. */ + /* */ + typedef struct OTL_Lookup_ + { + TT_ULong lookup_offset; + TT_UShort lookup_type; + TT_UShort lookup_flag; + + TT_UShort num_subtables; + TT_ULong* subtable_offsets; + void** subtables; + + } OTL_Lookup; + + + /*************************************************************************/ + /* */ + /* */ + /* OTL_Lookup_List */ + /* */ + /* */ + /* An OTL Lookup List record. */ + /* */ + /* */ + /* num_lookups :: The number of lookups. */ + /* lookups :: An array of lookups. */ + /* */ + typedef struct OTL_Lookup_List_ + { + TT_UShort num_lookups; + OTL_Lookup* lookups; + + } OTL_Lookup_List; + + +#define OTL_LOOKUP_FLAG_RIGHT_TO_LEFT 1 +#define OTL_LOOKUP_FLAG_IGNORE_BASE_GLYPHS 2 +#define OTL_LOOKUP_FLAG_IGNORE_LIGATURES 4 +#define OTL_LOOKUP_FLAG_IGNORE_MARKS 8 + + + /*************************************************************************/ + /* */ + /* */ + /* OTL_SubTable1 */ + /* */ + /* */ + /* The first generic OTL sub-table format. */ + /* */ + /* */ + /* num_indices :: The number of indices. */ + /* indices :: An array of indices. */ + /* data :: A generic value. */ + /* */ + typedef struct OTL_SubTable1_ + { + TT_UShort num_indices; + TT_UShort* indices; + TT_UShort data; + + } OTL_SubTable1; + + + /*************************************************************************/ + /* */ + /* */ + /* OTL_SubTable2_Rec */ + /* */ + /* */ + /* A record for the second generic OTL sub-table format. */ + /* */ + /* */ + /* start :: The first element in the range. */ + /* end :: The last element in the range. */ + /* data :: A generic value. */ + /* */ + typedef struct OTL_SubTable2_Rec_ + { + TT_UShort start; + TT_UShort end; + TT_UShort data; + + } OTL_SubTable2_Rec; + + + /*************************************************************************/ + /* */ + /* */ + /* OTL_SubTable2 */ + /* */ + /* */ + /* The second generic OTL sub-table format. */ + /* */ + /* */ + /* num_ranges :: The number of ranges. */ + /* ranges :: An array of ranges. */ + /* */ + typedef struct OTL_SubTable2_ + { + TT_UShort num_ranges; + OTL_SubTable2_Rec* ranges; + + } OTL_SubTable2; + + + /*************************************************************************/ + /* */ + /* */ + /* OTL_SubTable */ + /* */ + /* */ + /* A generic OTL sub-table which is a union of two possible formats */ + /* just defined. */ + /* */ + /* */ + /* format :: The format of the sub-table. */ + /* set :: A union of `format1' and `format2', representing */ + /* sub-tables. */ + /* */ + typedef struct OTL_SubTable_ + { + TT_UShort format; + + union + { + OTL_SubTable1 format1; + OTL_SubTable2 format2; + + } set; + + } OTL_SubTable; + + + /*************************************************************************/ + /* */ + /* */ + /* OTL_Coverage */ + /* */ + /* */ + /* An OTL Coverage sub-table. */ + /* */ + typedef OTL_SubTable OTL_Coverage; + typedef OTL_SubTable1 OTL_Coverage1; + typedef OTL_SubTable2 OTL_Coverage2; + typedef OTL_SubTable2_Rec OTL_Coverage2_Rec; + + + /*************************************************************************/ + /* */ + /* */ + /* OTL_Class_Def */ + /* */ + /* */ + /* An OTL Class Definition sub-table. */ + /* */ + typedef OTL_SubTable OTL_Class_Def; + typedef OTL_SubTable1 OTL_Class_Def1; + typedef OTL_SubTable2 OTL_Class_Def2; + typedef OTL_SubTable2_Rec OTL_Class_Def2_Rec; + + + /*************************************************************************/ + /* */ + /* */ + /* OTL_Device */ + /* */ + /* */ + /* An OTL Device sub-table */ + /* */ + /* */ + /* start_size :: The smallest size to correct. */ + /* end_size :: The largest size to correct. */ + /* delta_format :: The format of the `delta_values' array. */ + /* delta_values :: An array of compressed delta values. */ + typedef struct OTL_Device_ + { + TT_UShort start_size; + TT_UShort end_size; + TT_UShort delta_format; + TT_UShort* delta_values; + + } OTL_Device; + + +#ifdef __cplusplus +} +#endif + +#endif /* OTLAYOUT_H */ + + +/* END */ diff --git a/src/shared/otlayout/otload.c b/src/shared/otlayout/otload.c new file mode 100644 index 000000000..786beb381 --- /dev/null +++ b/src/shared/otlayout/otload.c @@ -0,0 +1,890 @@ +/***************************************************************************/ +/* */ +/* otload.c */ +/* */ +/* OpenType Layout loader (body). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 + + + /*************************** + * Script related functions + ***************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* OTL_Free_Script_List */ + /* */ + /* */ + /* Releases a given OpenType Script list. */ + /* */ + /* */ + /* list :: The target script list. */ + /* system :: The current system object. */ + /* */ + LOCAL_FUNC + void OTL_Free_Script_List( OTL_Script_List* list, + FT_System system ) + { + if ( list ) + { + if ( list->scripts ) + { + OTL_Script* script = list->scripts; + OTL_Script* script_limit = script + list->num_scripts; + + + for ( ; script < script_limit; script++ ) + { + if ( script->langsys ) + { + OTL_LangSys* langsys = script->langsys; + OTL_LangSys* langsys_limit = langsys + script->num_langsys; + + + for ( ; langsys < langsys_limit; langsys++ ) + { + FREE( langsys->feature_indices ); + langsys->num_feature_indices = 0; + } + FREE( script->langsys ); + } + script->langsys_default = NULL; + script->num_langsys = 0; + } + FREE( list->scripts ); + } + list->num_scripts = 0; + } + } + + + static + TT_Error Load_OTL_LangSys_List( OTL_Script* script, + FT_Stream stream, + TT_ULong default_offset ) + { + FT_System system = stream->system; + TT_Error error; + + TT_UShort n, count; + OTL_LangSys* langsys; + + + /* read the langsys tags and offsets */ + { + count = script->num_langsys; + langsys = script->langsys; + + if ( ACCESS_Frame( 6L * count ) ) + goto Exit; + + for ( n = 0; n < count; n++, langsys++ ) + { + TT_ULong offset; + + + langsys->lang_tag = GET_ULong(); + offset = GET_UShort(); + + if ( langsys->lang_offset == default_offset ) + script->langsys_default = langsys; + + langsys->lang_offset = offset + script->script_offset; + } + + FORGET_Frame(); + } + + /* now read each langsys record */ + { + count = script->num_langsys; + langsys = script->langsys; + + for ( n = 0; n < count; n++, langsys++ ) + { + TT_UShort num_feature_indices, i; + + + if ( FILE_Seek( langsys->lang_offset ) || + ACCESS_Frame( 8L ) ) + goto Exit; + + langsys->lookup_order = GET_ULong(); + langsys->req_feature_index = GET_UShort(); + langsys->num_feature_indices = GET_UShort(); + + FORGET_Frame(); + + num_feature_indices = langsys->num_feature_indices; + + if ( ALLOC_ARRAY ( langsys->feature_indices, + num_feature_indices, TT_UShort ) || + ACCESS_Frame( num_feature_indices * 2L ) ) + goto Exit; + + for ( i = 0; i < num_feature_indices; i++ ) + langsys->feature_indices[i] = GET_UShort(); + + FORGET_Frame(); + } + } + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* OTL_Load_Script_List */ + /* */ + /* */ + /* Loads an OpenType Script List from a font resource. */ + /* */ + /* */ + /* list :: The target script list. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_FUNC + TT_Error OTL_Load_Script_List( OTL_Script_List* list, + FT_Stream stream ) + { + FT_System system = stream->system; + TT_Error error; + + TT_ULong start_pos; + TT_UShort num_scripts; + OTL_Script* scripts; + + + start_pos = FILE_Pos(); + + if ( READ_UShort( list->num_scripts ) ) + goto Exit; + + num_scripts = list->num_scripts; + + /* Allocate the scripts table, read their tags and offsets */ + { + TT_UShort n; + + + if ( ALLOC_ARRAY( list->scripts, num_scripts, OTL_Script ) || + ACCESS_Frame( num_scripts * 6L ) ) + goto Exit; + + scripts = list->scripts; + + for ( n = 0; n < num_scripts; n++ ) + { + scripts[n].script_tag = GET_ULong(); + scripts[n].script_offset = GET_UShort() + start_pos; + } + + FORGET_Frame(); + } + + /* now read each script in the table */ + { + TT_UShort n; + OTL_Script* script = scripts; + + + for ( n = num_scripts; n > 0; n--, script++ ) + { + TT_ULong default_langsys_offset; + + + if ( FILE_Seek ( script->script_offset ) || + READ_ULong ( default_langsys_offset ) || + READ_UShort( script->num_langsys ) || + ALLOC_ARRAY( script->langsys, + script->num_langsys, OTL_LangSys ) ) + goto Exit; + + /* read the corresponding langsys list */ + error = Load_OTL_LangSys_List( + script, + stream, + default_langsys_offset + script->script_offset ); + if ( error ) + goto Exit; + } + } + + Exit: + if ( error ) + OTL_Free_Script_List( list, system ); + + return error; + } + + + /********************************* + * Feature List related functions + *********************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* OTL_Free_Features_List */ + /* */ + /* */ + /* Releases a given OpenType Features list. */ + /* */ + /* */ + /* list :: The target feature list. */ + /* system :: The current system object. */ + /* */ + LOCAL_FUNC + void OTL_Free_Features_List( OTL_Feature_List* list, + FT_System system ) + { + if ( list ) + { + if ( list->features ) + { + OTL_Feature* feature = list->features; + OTL_Feature* feature_limit = feature + list->num_features; + + + for ( ; feature < feature_limit; feature++ ) + { + FREE( feature->lookups ); + feature->num_lookups = 0; + } + + FREE( list->features ); + } + list->num_features = 0; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* OTL_Load_Feature_List */ + /* */ + /* */ + /* Loads an OpenType Feature List from a font resource. */ + /* */ + /* */ + /* list :: The target feature list. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_FUNC + TT_Error OTL_Load_Feature_List( OTL_Feature_List* list, + FT_Stream stream ) + { + FT_System system = stream->system; + TT_Error error; + TT_ULong start_pos; + TT_UShort num_features, n; + + + start_pos = FILE_Pos(); + + if ( READ_UShort( num_features ) ) + goto Exit; + + /* allocate the features array and read their tag and offset */ + { + OTL_Feature* feature; + OTL_Feature* feature_limit; + + + if ( ALLOC_ARRAY ( list->features, num_features, OTL_Feature ) || + ACCESS_Frame( num_features * 6L ) ) + goto Exit; + + list->num_features = num_features; + feature = list->features; + feature_limit = feature + num_features; + + for ( ; feature < feature_limit; feature++ ) + { + feature->feature_tag = GET_ULong(); + feature->feature_offset = GET_UShort() + start_pos; + } + + FORGET_Frame(); + } + + /* now read each feature */ + { + OTL_Feature* feature; + OTL_Feature* feature_limit; + + + feature = list->features; + feature_limit = feature + num_features; + + for ( ; feature < feature_limit; feature++ ) + { + TT_UShort num_lookups; + TT_UShort* lookup; + TT_UShort* lookup_limit; + + + if ( FILE_Seek ( feature->feature_offset ) || + READ_ULong ( feature->feature_params ) || + READ_UShort ( num_lookups ) || + ALLOC_ARRAY ( feature->lookups, + num_lookups, TT_UShort ) || + ACCESS_Frame( num_lookups * 2L ) ) + goto Exit; + + feature->num_lookups = num_lookups; + lookup = feature->lookups; + lookup_limit = lookup + num_lookups; + + for ( ; lookup < lookup_limit; lookup++ ) + lookup[0] = GET_UShort(); + + FORGET_Frame(); + } + } + + Exit: + if ( error ) + OTL_Free_Feature_List( list, system ); + + return error; + } + + + /******************************** + * Lookup List related functions + ********************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* OTL_Iterate_Lookup_List */ + /* */ + /* */ + /* Scans an OpenType Lookup List. This can be used to load the */ + /* Lookup sub-tables in a GSUB or GPOS loader. */ + /* */ + /* */ + /* list :: The source list. */ + /* iterator :: The iterator -- a function which is called on each */ + /* element of the list. */ + /* closure :: User-specified data which is passed to each iterator */ + /* with the lookup element pointer. */ + /* */ + /* */ + /* If one iterator call returns a non-zero `result', the list parsing */ + /* is aborted and the value is returned to the caller. Otherwise, */ + /* the function returns 0 when the list has been parsed completely. */ + /* */ + LOCAL_FUNC + TT_Error OTL_Iterate_Lookup_List( OTL_Lookup_List* list, + OTL_Lookup_Iterator iterator, + void* closure ) + { + int result = 0; + + + if ( list->lookups ) + { + OTL_Lookup* lookup = list->lookups; + OTL_Lookup* limit = lookup + list->num_lookups; + + + for ( ; lookup < limit; lookup++ ) + { + result = iterator( lookup, closure ); + if ( result ) + break; + } + } + + return 0; + } + + + /*************************************************************************/ + /* */ + /* */ + /* OTL_Free_Lookup_List */ + /* */ + /* */ + /* Releases a given OpenType Lookup list. Uses a destructor called */ + /* to destroy the Lookup sub-tables. */ + /* */ + /* */ + /* list :: The target lookup list. */ + /* system :: The current system object. */ + /* destructor :: A destructor function called on each lookup element. */ + /* Can be used to destroy sub-tables. Ignored if NULL. */ + /* */ + LOCAL_FUNC + void OTL_Free_Lookup_List( OTL_Lookup_List* list, + FT_System system, + OTL_Lookup_Destructor destroy ) + { + if ( list ) + { + if ( list->lookups ) + { + OTL_Lookup* lookup = list->lookups; + OTL_Lookup* limit = lookup + list->num_lookups; + + + for ( ; lookup < limit; lookup++ ) + { + if ( destroy ) + destroy( lookup, system ); + + FREE( lookup->subtable_offsets ); + lookup->num_subtables = 0; + } + + FREE( list->lookups ); + } + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* OTL_Load_Lookup_List */ + /* */ + /* */ + /* Loads an OpenType Lookup List from a font resource. */ + /* */ + /* */ + /* list :: The target lookup list. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + /* */ + /* This function does NOT load the lookup sub-tables. Instead, it */ + /* stores the file offsets of the particular table in each lookup */ + /* element. It is up to the caller to load these sub-tables. This */ + /* can be done more easily with OTL_Iterate_Lookup_List(). */ + /* */ + LOCAL_FUNC + TT_Error OTL_Load_Lookup_List( OTL_Lookup_List* list, + FT_Stream stream ) + { + FT_System system = stream->system; + TT_Error error; + + TT_UShort num_lookups; + TT_ULong start_pos; + + + start_pos = GET_ULong(); + + if ( READ_UShort( num_lookups ) ) + goto Exit; + + /* allocate the lookups array and read their tags and offset */ + { + TT_UShort n; + + + if ( ALLOC_ARRAY ( list->lookups, num_lookups, OTL_Lookup ) || + ACCESS_Frame( num_lookups * 2L ) ) + goto Exit; + + list->num_lookups = num_lookups; + for ( n = 0; n < num_lookups; n++ ) + list->lookups[n].lookup_offset = start_pos + GET_UShort(); + + FORGET_Frame(); + } + + /* now read each lookup table */ + /* NOTE that we don't load the sub-tables here, but simply */ + /* store their file offsets in the `subtable_offsets' array */ + { + OTL_Lookup* lookup = list->lookups; + OTL_Lookup* lookup_limit = lookup + num_lookups; + + + for ( ; lookup < lookup_limit; lookup++ ) + { + TT_UShort n, num_subtables; + TT_ULong* offsets; + + + if ( FILE_Seek ( lookup->lookup_offset ) || + ACCESS_Frame( 6L ) ) + goto Exit; + + lookup->lookup_type = GET_UShort(); + lookup->lookup_flag = GET_UShort(); + lookup->num_subtables = GET_UShort(); + + num_subtables = lookup->num_subtables; + + FORGET_Frame(); + + if ( ALLOC_ARRAY ( lookup->subtable_offsets, + num_subtables, TT_ULong ) || + ACCESS_Frame( num_subtables * 2L ) ) + goto Exit; + + offsets = lookup->subtable_offsets; + for ( n = 0; n < num_subtables; n++ ) + offsets[n] = lookup->lookup_offset + GET_UShort(); + + FORGET_Frame(); + } + } + + Exit: + if ( error ) + OTL_Free_Lookup_List( list, system, 0 ); + + return error; + } + + + /* generic sub-table freeing and loading */ + + static + void Free_SubTable( OTL_SubTable* subtable, + FT_System system ) + { + if ( subtable ) + { + switch ( subtable->format ) + { + case 1: + { + OTL_SubTable1* st = &subtable->set.format1; + + + FREE( st->indices ); + st->num_indices = 0; + FREE( st ); + } + break; + + case 2: + { + OTL_SubTable2* st = &subtable->set.format2; + + + FREE( st->ranges ); + st->num_ranges = 0; + FREE( st ); + } + break; + + default: + break; + } + + FREE( subtable ); + } + } + + + static + TT_Error Load_SubTable( OTL_SubTable* subtable, + FT_Stream stream ) + { + FT_System system = stream->system; + TT_Error error; + + + if ( READ_UShort( subtable->format ) ) + goto Exit; + + switch ( subtable->format ) + { + case 1: + { + OTL_SubTable1* st = &subtable->set.format1; + TT_UShort num_indices, n; + + + if ( READ_UShort ( num_indices ) || + ALLOC_ARRAY ( st->indices, num_indices, TT_UShort ) || + ACCESS_Frame( num_indices * 2L ) ) + goto Exit; + + st->num_indices = num_indices; + for ( n = 0; n < num_indices; n++ ) + st->indices[n] = GET_UShort(); + + FORGET_Frame(); + } + + case 2: + { + OTL_SubTable2* st = &subtable->set.format2; + TT_UShort num_ranges, n; + OTL_SubTable2_Rec* range; + + + if ( READ_UShort( num_ranges ) || + ALLOC_ARRAY( st->ranges, num_ranges, OTL_SubTable2_Rec ) || + ACCESS_Frame( num_ranges * 6L ) ) + goto Exit; + + st->num_ranges = num_ranges; + range = st->ranges; + for ( ; num_ranges > 0; num_ranges--, range++ ) + { + range->start = GET_UShort(); + range->end = GET_UShort(); + range->data = GET_UShort(); + } + + FORGET_Frame(); + } + break; + + default: + error = TT_Err_Invalid_File_Format; + } + + Exit: + if ( error ) + Free_SubTable( subtable, system ); + + return error; + } + + + /***************************** + * Coverage related functions + *****************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* OTL_Free_Coverage */ + /* */ + /* */ + /* Releases a given OpenType Coverage table. */ + /* */ + /* */ + /* coverage :: The target coverage. */ + /* system :: The current system object. */ + /* */ + LOCAL_FUNC + void OTL_Free_Coverage( OTL_Coverage* coverage, + FT_System system ) + { + Free_SubTable( (OTL_SubTable*)coverage, system ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* OTL_Load_Coverage */ + /* */ + /* */ + /* Loads an OpenType Coverage table from a font resource. */ + /* */ + /* */ + /* coverage :: The target coverage. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_FUNC + TT_Error OTL_Load_Coverage( OTL_Coverage* coverage, + FT_Stream stream ) + { + return Load_SubTable( (OTL_SubTable*)coverage, stream ); + } + + + /************************************* + * Class Definition related functions + *************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* OTL_Free_Class_Def */ + /* */ + /* */ + /* Releases a given OpenType Class Definition table. */ + /* */ + /* */ + /* class_def :: The target class definition. */ + /* system :: The current system object. */ + /* */ + LOCAL_FUNC + void OTL_Free_Class_Def( OTL_Class_Def* class_def, + FT_System system ) + { + Free_SubTable( (OTL_SubTable*)class_def, system ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* OTL_Load_Class_Def */ + /* */ + /* */ + /* Loads an OpenType Class Definition table from a resource. */ + /* */ + /* */ + /* class_def :: The target class definition. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_FUNC + TT_Error OTL_Load_Class_Def( OTL_Class_Def* class_def, + FT_Stream stream ) + { + return OTL_Load_SubTable( (OTL_SubTable*)class_def, stream ); + } + + + /************************************* + * Device related functions + *************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* OTL_Free_Device */ + /* */ + /* */ + /* Releases a given OpenType Layout Device table. */ + /* */ + /* */ + /* device :: The target device table. */ + /* system :: The current system object. */ + /* */ + LOCAL_FUNC + void OTL_Free_Device( OTL_Device* device, + FT_System system ) + { + if ( device ) + { + FREE( device->delta_values ); + FREE( device ); + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* OTL_Load_Device */ + /* */ + /* */ + /* Loads an OpenType Device table from a font resource. */ + /* */ + /* */ + /* device :: The target device table. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_FUNC + TT_Error OTL_Load_Device( OTL_Device* device, + FT_Stream stream ) + { + FT_System system = stream->system; + TT_Error error; + TT_UShort* deltas; + TT_UShort num_deltas, num_values; + + + if ( ACCESS_Frame( 6L ) ) + goto Exit; + + device->start_size = GET_UShort(); + device->end_size = GET_UShort(); + device->delta_format = GET_UShort(); + + FORGET_Frame(); + + num_deltas = device->end_size - device->start_size + 1; + + switch ( device->delta_format ) + { + case 1: + num_values = ( num_deltas + 7 ) >> 3; + break; + + case 2: + num_values = ( num_deltas + 3 ) >> 2; + break; + + case 3: + num_values = ( num_deltas + 1 ) >> 1; + break; + + default: + error = TT_Err_Invalid_File_Format; + goto Exit; + } + + if ( ALLOC_ARRAY( deltas, num_values, TT_UShort ) ) + goto Exit; + + if ( !ACCESS_Frame( num_values * 2L ) ) + { + TT_UShort n; + + + for ( n = 0; n < num_values; n++ ) + deltas[n] = GET_UShort(); + + FORGET_Frame(); + + device->delta_values = deltas; + } + else + FREE( deltas ); + + Exit: + return error; + } + + +/* END */ diff --git a/src/shared/otlayout/otload.h b/src/shared/otlayout/otload.h new file mode 100644 index 000000000..477bba344 --- /dev/null +++ b/src/shared/otlayout/otload.h @@ -0,0 +1,297 @@ +/***************************************************************************/ +/* */ +/* otload.h */ +/* */ +/* OpenType layout loader functions (specification). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 OTLOAD_H +#define OTLOAD_H + +#include +#include + + + /*************************************************************************/ + /* */ + /* */ + /* OTL_Load_Script_List */ + /* */ + /* */ + /* Loads an OpenType Script List from a font resource. */ + /* */ + /* */ + /* list :: The target script list. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_DEF + TT_Error OTL_Load_Script_List( OTL_Script_List* list, + FT_Stream stream ); + + + /*************************************************************************/ + /* */ + /* */ + /* OTL_Load_Feature_List */ + /* */ + /* */ + /* Loads an OpenType Feature List from a font resource. */ + /* */ + /* */ + /* list :: The target feature list. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_DEF + TT_Error OTL_Load_Feature_List( OTL_Feature_List* list, + FT_Stream stream ); + + + /*************************************************************************/ + /* */ + /* */ + /* OTL_Load_Lookup_List */ + /* */ + /* */ + /* Loads an OpenType Lookup List from a font resource. */ + /* */ + /* */ + /* list :: The target lookup list. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + /* */ + /* This function does NOT load the lookup sub-tables. Instead, it */ + /* stores the file offsets of the particular table in each lookup */ + /* element. It is up to the caller to load these sub-tables. This */ + /* can be done more easily with OTL_Iterate_Lookup_List(). */ + /* */ + LOCAL_DEF + TT_Error OTL_Load_Lookup_List( OTL_Lookup_List* list, + FT_Stream stream ); + + + typedef int OTL_Lookup_Iterator( OTL_Lookup* lookup, + void* closure ); + + + typedef void OTL_Lookup_Destructor( OTL_Lookup* lookup, + FT_System system ); + + + /*************************************************************************/ + /* */ + /* */ + /* OTL_Iterate_Lookup_List */ + /* */ + /* */ + /* Scans an OpenType Lookup List. This can be used to load the */ + /* Lookup sub-tables in a GSUB or GPOS loader. */ + /* */ + /* */ + /* list :: The source list. */ + /* iterator :: The iterator -- a function which is called on each */ + /* element of the list. */ + /* closure :: User-specified data which is passed to each iterator */ + /* with the lookup element pointer. */ + /* */ + /* */ + /* If one iterator call returns a non-zero `result', the list parsing */ + /* is aborted and the value is returned to the caller. Otherwise, */ + /* the function returns 0 when the list has been parsed completely. */ + /* */ + LOCAL_DEF + TT_Error OTL_Iterate_Lookup_List( OTL_Lookup_List* list, + OTL_Lookup_Iterator iterator, + void* closure ); + + + /*************************************************************************/ + /* */ + /* */ + /* OTL_Load_Coverage */ + /* */ + /* */ + /* Loads an OpenType Coverage table from a font resource. */ + /* */ + /* */ + /* coverage :: The target coverage. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_FUNC + TT_Error OTL_Load_Coverage( OTL_Coverage* coverage, + FT_Stream stream ); + + + /*************************************************************************/ + /* */ + /* */ + /* OTL_Load_Class_Def */ + /* */ + /* */ + /* Loads an OpenType Class Definition table from a resource. */ + /* */ + /* */ + /* class_def :: The target class definition. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_DEF + TT_Error OTL_Load_Class_Def( OTL_Class_Def* class_def, + FT_Stream stream ); + + + /*************************************************************************/ + /* */ + /* */ + /* OTL_Load_Device */ + /* */ + /* */ + /* Loads an OpenType Device table from a font resource. */ + /* */ + /* */ + /* device :: The target device table. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_DEF + TT_Error OTL_Load_Device( OTL_Device* device, + FT_Stream stream ); + + + /*************************************************************************/ + /* */ + /* */ + /* OTL_Free_Script_List */ + /* */ + /* */ + /* Releases a given OpenType Script list. */ + /* */ + /* */ + /* list :: The target script list. */ + /* system :: The current system object. */ + /* */ + LOCAL_DEF + void OTL_Free_Script_List( OTL_Script_List* list, + FT_System system ); + + + /*************************************************************************/ + /* */ + /* */ + /* OTL_Free_Features_List */ + /* */ + /* */ + /* Releases a given OpenType Features list. */ + /* */ + /* */ + /* list :: The target feature list. */ + /* system :: The current system object. */ + /* */ + LOCAL_DEF + void OTL_Free_Features_List( OTL_Feature_List* list, + FT_System system ); + + + + /*************************************************************************/ + /* */ + /* */ + /* OTL_Free_Lookup_List */ + /* */ + /* */ + /* Releases a given OpenType Lookup list. Uses a destructor called */ + /* to destroy the Lookup sub-tables. */ + /* */ + /* */ + /* list :: The target lookup list. */ + /* system :: The current system object. */ + /* destructor :: A destructor function called on each lookup element. */ + /* Can be used to destroy sub-tables. Ignored if NULL. */ + /* */ + LOCAL_DEF + void OTL_Free_Lookup_List( OTL_Lookup_List* list, + FT_System system, + OTL_Lookup_Destructor destroy ); + + + /*************************************************************************/ + /* */ + /* */ + /* OTL_Free_Coverage */ + /* */ + /* */ + /* Releases a given OpenType Coverage table. */ + /* */ + /* */ + /* coverage :: The target coverage. */ + /* system :: The current system object. */ + /* */ + LOCAL_DEF + void OTL_Free_Coverage( OTL_Coverage* coverage, + FT_System system ); + + + /*************************************************************************/ + /* */ + /* */ + /* OTL_Free_Class_Def */ + /* */ + /* */ + /* Releases a given OpenType Class Definition table. */ + /* */ + /* */ + /* class_def :: The target class definition. */ + /* system :: The current system object. */ + /* */ + LOCAL_DEF + void OTL_Free_Class_Def( OTL_Class_Def* class_def, + FT_System system ); + + + /*************************************************************************/ + /* */ + /* */ + /* OTL_Free_Device */ + /* */ + /* */ + /* Releases a given OpenType Layout Device table. */ + /* */ + /* */ + /* device :: The target device table. */ + /* system :: The current system object. */ + /* */ + LOCAL_DEF + void OTL_Free_Device( OTL_Device* device, + FT_System system ); + + +#endif /* OTLOAD_H */ + + +/* END */ diff --git a/src/shared/readme.txt b/src/shared/readme.txt new file mode 100644 index 000000000..b48163a30 --- /dev/null +++ b/src/shared/readme.txt @@ -0,0 +1,6 @@ +WARNING: + +The files in these subdirectories are shared by several font drivers. + +All C source files are included by at least one of the drivers, and +thus should _never_ be compiled directly. diff --git a/src/shared/rules.mk b/src/shared/rules.mk new file mode 100644 index 000000000..e83466b3a --- /dev/null +++ b/src/shared/rules.mk @@ -0,0 +1,95 @@ +#**************************************************************************** +#* * +#* shared files Makefile * +#* * +#* Copyright 1996-1999 by * +#* David Turner, Robert Wilhelm, and Werner Lemberg. * +#* * +#* This file is part of the FreeType project, and may only be used * +#* modified and distributed under the terms of the FreeType project * +#* license, LICENSE.TXT. By continuing to use, modify, or distribute * +#* this file you indicate that you have read the license and * +#* understand and accept it fully. * +#* * +#**************************************************************************** + + +#**************************************************************************** +#* * +#* IMPORTANT NOTE: This Makefile is intended for GNU Make! * +#* If you provide Makefiles for other make utilities, * +#* please place them in `freetype/lib/arch/'. * +#* * +#* * +#* This file is to be included by the FreeType Makefile.lib, located in * +#* the `freetype/lib' directory. Here is the list of the variables that * +#* must be defined to use it: * +#* * +#* * +#* BASE_DIR: The location of the base layer's directory. This is * +#* usually `freetype/lib/base'. * +#* * +#* ARCH_DIR: The location of the architecture-dependent directory. * +#* This is usually `freetype/lib/arch/'. * +#* * +#* DRIVERS_DIR: The location of the font driver sub-dirs, usually * +#* `freetype/lib/drivers'. * +#* * +#* OBJ_DIR: The location where the compiled object(s) file will be * +#* placed. * +#* * +#* BASE_H: A list of pathnames to the base layer's header files on * +#* which the driver depends. * +#* * +#* FT_CFLAGS: A set of flags used for compilation of object files. * +#* This contains at least the include paths of the arch * +#* and base directories + optimization + warnings + ANSI * +#* compliance. * +#* * +#* FT_IFLAG: The flag used to specify an include path on the * +#* compiler command line. For example, with GCC, this is * +#* `-I', while some other compilers use `/i=' or `-J', * +#* etc. * +#* * +#* FT_OBJ: The suffix of an object file for the platform; can be * +#* `o', `obj', `coff', `tco', etc. depending on the * +#* platform. * +#* * +#* * +#* It also updates the following variables defined and used in the main * +#* Makefile: * +#* * +#* DRV_OBJ_S: The list of driver object files in * +#* single-object mode. * +#* * +#* DRV_OBJ_M: The list of driver object files in * +#* multiple-objects mode. * +#* * +#* FTINIT_DRIVER_PATHS: The list of include paths used to compile the * +#* `ftinit' component which registers all font * +#* drivers in the FT_Init_FreeType() function. * +#* * +#* FTINIT_DRIVER_H: The list of header dependencies used to * +#* compile the `ftinit' component. * +#* * +#* FTINIT_DRIVER_MACROS: The list of macros to be defined when * +#* compiling the `ftinit' component. * +#* * +#* `Single-object compilation' means that each font driver is compiled * +#* into a single object file. This is useful to get rid of all * +#* driver-specific entries. * +#* * +#**************************************************************************** + +ifndef SHARED_RULES +SHARED_RULES := 1 + +SHARED := $(SRC_)shared +SHARED_ := $(SHARED)$(SEP) + +SHARED_H := $(wildcard $(SHARED_)*.h) +SHARED_SRC := $(wildcard $(SHARED_)*.c) + +endif + +# END diff --git a/src/shared/sfnt.h b/src/shared/sfnt.h new file mode 100644 index 000000000..5549479f1 --- /dev/null +++ b/src/shared/sfnt.h @@ -0,0 +1,347 @@ +/***************************************************************************/ +/* */ +/* sfnt.h */ +/* */ +/* High-level `sfnt' driver interface (specification). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Directory_Func */ + /* */ + /* */ + /* Loads the table directory into a face object. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: The input stream. */ + /* faceIndex :: The index of the TrueType font, if we're opening a */ + /* collection. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + /* */ + /* The stream cursor must be at the font file's origin */ + /* */ + typedef + TT_Error (*TT_Load_Directory_Func)( TT_Face face, + FT_Stream stream, + TT_Long faceIndex ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Any_Func */ + /* */ + /* */ + /* Loads any font table into client memory. Used by the */ + /* TT_Get_Font_Data() API function. */ + /* */ + /* */ + /* 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 + TT_Error (*TT_Load_Any_Func)( TT_Face face, + TT_ULong tag, + TT_Long offset, + void* buffer, + TT_Long* 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. */ + /* */ + /* */ + /* TrueType 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 + TT_Error (*TT_Load_SBit_Image_Func)( TT_Face face, + TT_Int x_ppem, + TT_Int y_ppem, + TT_UInt glyph_index, + 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! */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + typedef + TT_Error (*TT_Get_PS_Name_Func)( TT_Face face, + TT_UInt index, + TT_String** PSname ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Metrics */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + typedef + TT_Error (*TT_Load_Metrics_Func)( TT_Face face, + FT_Stream stream, + TT_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. */ + /* */ + /* */ + /* 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 + TT_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. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + typedef + TT_Error (*TT_CharMap_Free_Func)( TT_Face face, + TT_CMapTable* cmap ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Table */ + /* */ + /* */ + /* Loads a given TrueType table. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + /* */ + /* The function will use `face->goto_table' to seek the stream to */ + /* the start of the table */ + /* */ + typedef + TT_Error (*TT_Load_Table_Func)( TT_Face face, + FT_Stream stream ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Table */ + /* */ + /* */ + /* Loads a given TrueType table. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + /* */ + /* The function will use `face->goto_table' to seek the stream to */ + /* the start of the table */ + /* */ + 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. */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + typedef struct SFNT_Interface_ + { + TT_Goto_Table_Func goto_table; + + TT_Load_Any_Func load_any; + TT_Load_Directory_Func load_directory; + + 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; + + + /* 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/src/shared/sfnt/rules.mk b/src/shared/sfnt/rules.mk new file mode 100644 index 000000000..e8ab1f72c --- /dev/null +++ b/src/shared/sfnt/rules.mk @@ -0,0 +1,58 @@ +#**************************************************************************** +#* * +#* SFNT/TrueType Makefile * +#* * +#* Copyright 1996-1999 by * +#* David Turner, Robert Wilhelm, and Werner Lemberg. * +#* * +#* This file is part of the FreeType project, and may only be used * +#* modified and distributed under the terms of the FreeType project * +#* license, LICENSE.TXT. By continuing to use, modify, or distribute * +#* this file you indicate that you have read the license and * +#* understand and accept it fully. * +#* * +#**************************************************************************** + + +#**************************************************************************** +#* * +#* IMPORTANT NOTE: This Makefile is intended for GNU Make! * +#* If you provide Makefiles for other make utilities, * +#* please place them in `freetype/lib/arch/'. * +#* * +#* * +#* This file is to be included by the Makefiles of each driver that uses * +#* the shared source code in `freetype2/lib/drivers/sfnt'. This code * +#* contains type definitions as well as interface which are common to all * +#* `sfnt' font formats (i.e., TrueType, OpenType-TTF, and OpenType-CFF). * +#* * +#* * +#* The purpose of this Makefile is to define two make variables that are * +#* used directly by the parent Makefile. * +#* * +#**************************************************************************** + + +# SFNT_DIR is the directory to the `sfnt' sources +# +SFNT_DIR := $(SRC)$(SEP)shared$(SEP)sfnt +SFNT_DIR_ := $(SFNT_DIR)$(SEP) + + +# SFNT_H is the list of all header files on which the client drivers depend +# +SFNT_H := $(SFNT_DIR_)tttypes.h \ + $(SFNT_DIR_)ttload.h \ + $(SFNT_DIR_)ttsbit.h \ + $(SFNT_DIR_)ttpost.h \ + $(SFNT_DIR_)sfnt.h + +# SFNT_SRC is the list of all shared source files that are included by any +# client driver +# +SFNT_SRC := $(SFNT_DIR_)ttload.c \ + $(SFNT_DIR_)ttsbit.c \ + $(SFNT_DIR_)ttpost.c + + +# END diff --git a/src/shared/sfnt/sfnt.h b/src/shared/sfnt/sfnt.h new file mode 100644 index 000000000..f1bc9c586 --- /dev/null +++ b/src/shared/sfnt/sfnt.h @@ -0,0 +1,50 @@ +/***************************************************************************/ +/* */ +/* sfnt.h */ +/* */ +/* Defines the function interface used to access SFNT files, i.e., */ +/* TrueType, OpenType-TT, and OpenType-T2 files (specification only). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 + + + typedef TT_Long (*SFNT_LookUp_Table)( TT_Face face, + TT_ULong tag ); + + + typedef TT_Error (*SFNT_Load_Table)( TT_Face face, + TT_ULong tag, + TT_Long offset, + void* buffer, + TT_Long* length ); + + typedef TT_Error (*SFNT_Get_PS_Name)( TT_Face face, + TT_UShort index, + TT_String* *ps_name ); + + typedef struct SFNT_Interface_ + { + SFNT_LookUp_Table lookup_table; + SFNT_Load_Table load_table; + + } SFNT_Interface; + + +#endif /* SFNT_H */ + + +/* END */ diff --git a/src/shared/sfnt/ttload.c b/src/shared/sfnt/ttload.c new file mode 100644 index 000000000..e18b52b99 --- /dev/null +++ b/src/shared/sfnt/ttload.c @@ -0,0 +1,1488 @@ +/***************************************************************************/ +/* */ +/* ttload.c */ +/* */ +/* TrueType tables loader (body). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/* */ +/* WARNING: This file should not be compiled directly; it is meant to be */ +/* included in the source of several font drivers (i.e., the TTF */ +/* and OTF drivers). */ +/* */ +/***************************************************************************/ + + +#include + +#include +#include +#include + + +/* required by the tracing mode */ +#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. */ + /* */ + /* */ + /* Index of table if found, -1 otherwise. */ + /* */ + EXPORT_FUNC + FT_Long TT_LookUp_Table( TT_Face face, + TT_ULong tag ) + { + TT_Long i, found; + + + FT_TRACE4(( "TT_LookUp_Table( %08lx, %c%c%c%c )\n", + (TT_Long)face, + (TT_Char)(tag >> 24), + (TT_Char)(tag >> 16), + (TT_Char)(tag >> 8), + (TT_Char)(tag) )); + + found = -1; + for ( i = 0; i < face->num_tables; i++ ) + if ( face->dir_tables[i].Tag == tag ) + { + found = i; + break; + } + + if ( found == -1 ) + { + FT_TRACE4(( " Could not find table!\n" )); + } + + return found; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Collection */ + /* */ + /* */ + /* Loads the TTC table directory into face table. */ + /* */ + /* */ + /* face :: A face object handle. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + static + TT_Error TT_Load_Collection( TT_Face face, + FT_Stream stream ) + { + TT_Long n; + TT_Error error; + FT_Memory memory = stream->memory; + + + FT_TRACE3(( "TT_Load_Collection( %08lx )\n", (TT_Long)face )); + + if ( FILE_Seek ( 0L ) || + ACCESS_Frame( 12L ) ) + goto Exit; + + face->ttc_header.Tag = GET_Tag4(); + face->ttc_header.version = GET_Long(); + face->ttc_header.DirCount = GET_Long(); /* see comment in tttypes.h */ + + FORGET_Frame(); + + if ( face->ttc_header.Tag != TTAG_ttcf ) + { + face->ttc_header.Tag = 0; + face->ttc_header.version = 0; + face->ttc_header.DirCount = 0; + + face->ttc_header.TableDirectory = NULL; + + FT_TRACE3(( "skipped.\n" )); + + error = TT_Err_File_Is_Not_Collection; + goto Exit; + } + + if ( ALLOC_ARRAY( face->ttc_header.TableDirectory, + face->ttc_header.DirCount, + TT_ULong ) || + ACCESS_Frame( face->ttc_header.DirCount * 4L ) ) + goto Exit; + + for ( n = 0; n < face->ttc_header.DirCount; n++ ) + face->ttc_header.TableDirectory[n] = GET_ULong(); + + FORGET_Frame(); + + FT_TRACE3(( "collections directory loaded.\n" )); + + 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. */ + /* faceIndex :: The index of the TrueType font, if we're opening a */ + /* collection. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_FUNC + TT_Error TT_Load_Directory( TT_Face face, + FT_Stream stream, + TT_Long faceIndex ) + { + TT_Error error; + FT_Memory memory = stream->memory; + + TT_UShort n, limit; + TT_TableDir tableDir; + + TT_TableDirEntry* entry; + + + FT_TRACE2(( "TT_Load_Directory( %08lx, %ld )\n", + (TT_Long)face, faceIndex )); + + error = TT_Load_Collection( face, stream ); + if ( error ) + { + /* if this is a `traditional' error, exit now */ + if ( error != TT_Err_File_Is_Not_Collection ) + goto Exit; + + /* the file isn't a collection, exit if we're asking */ + /* for a collected font */ + + /* Note that we don't exit during font format checking (i.e., */ + /* faceIndex is -1) */ + if ( faceIndex > 0 ) + goto Exit; + + /* Now skip to the beginning of the file */ + if ( FILE_Seek( 0 ) ) + goto Exit; + } + else + { + /* The file is a collection. Check the font index */ + if ( faceIndex >= face->ttc_header.DirCount ) + { + error = TT_Err_Bad_Argument; + goto Exit; + } + + /* if we're checking the font format, exit immediately */ + if ( faceIndex < 0 ) + goto Exit; + + /* select a TrueType font in the ttc file */ + if ( FILE_Seek( face->ttc_header.TableDirectory[faceIndex] ) ) + goto Exit; + } + + if ( ACCESS_Frame( 12L ) ) + goto Exit; + + tableDir.version = GET_Long(); + tableDir.numTables = GET_UShort(); + + tableDir.searchRange = GET_UShort(); + tableDir.entrySelector = GET_UShort(); + tableDir.rangeShift = GET_UShort(); + + FORGET_Frame(); + + FT_TRACE2(( "-- Tables count : %12u\n", tableDir.numTables )); + FT_TRACE2(( "-- Format version : %08lx\n", tableDir.version )); + + /* Check that we have a `sfnt' format there */ + /* We must also be able to accept Mac/GX fonts, as well as OT ones */ + + if ( tableDir.version != 0x00010000 && + tableDir.version != TTAG_true && + tableDir.version != TTAG_OTTO ) + { + FT_TRACE2(( "[not a valid TTF or OTF font]" )); + error = TT_Err_Invalid_File_Format; + goto Exit; + } + + /* if we're performing a font format check, exit immediately */ + /* with success */ + if ( faceIndex < 0 ) + goto Exit; + + face->num_tables = tableDir.numTables; + + if ( ALLOC_ARRAY( face->dir_tables, + face->num_tables, + TT_TableDirEntry ) ) + goto Exit; + + if ( ACCESS_Frame( face->num_tables * 16L ) ) + goto Exit; + + limit = face->num_tables; + entry = face->dir_tables; + + for ( n = 0; n < limit; n++ ) + { /* 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", + (TT_Char)(entry->Tag >> 24), + (TT_Char)(entry->Tag >> 16), + (TT_Char)(entry->Tag >> 8 ), + (TT_Char)(entry->Tag), + entry->Offset, + entry->Length )); + entry++; + } + + FORGET_Frame(); + + FT_TRACE2(( "Directory loaded\n\n" )); + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Any */ + /* */ + /* */ + /* Loads any font table into client memory. Used by the */ + /* TT_Get_Font_Data() API function. */ + /* */ + /* */ + /* 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. */ + /* */ + LOCAL_FUNC + TT_Error TT_Load_Any( TT_Face face, + TT_ULong tag, + TT_Long offset, + void* buffer, + TT_Long* length ) + { + TT_Error error; + FT_Stream stream; + TT_Long table; + TT_ULong size; + + + if ( tag != 0 ) + { + /* look for tag in font directory */ + table = TT_LookUp_Table( face, tag ); + if ( table < 0 ) + { + error = TT_Err_Table_Missing; + goto Exit; + } + + offset += face->dir_tables[table].Offset; + size = face->dir_tables[table].Length; + } + else + /* tag = 0 -- the use want 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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_FUNC + TT_Error TT_Load_Header( TT_Face face, + FT_Stream stream ) + { + TT_Error error; + + TT_Long table; + TT_Header* header; + + + FT_TRACE2(( "Load_TT_Header( %08lx )\n", (TT_Long)face )); + + if ( ( table = TT_LookUp_Table( face, TTAG_head ) ) < 0 ) + { + FT_TRACE0(( "Font Header is missing!\n" )); + error = TT_Err_Header_Table_Missing; + + goto Exit; + } + + if ( FILE_Seek( face->dir_tables[table].Offset ) || + ACCESS_Frame( 54L ) ) + goto Exit; + + header = &face->header; + + header->Table_Version = GET_ULong(); + header->Font_Revision = GET_ULong(); + + header->CheckSum_Adjust = GET_Long(); + header->Magic_Number = GET_Long(); + + header->Flags = GET_UShort(); + header->Units_Per_EM = GET_UShort(); + + header->Created [0] = GET_Long(); + header->Created [1] = GET_Long(); + header->Modified[0] = GET_Long(); + header->Modified[1] = GET_Long(); + + header->xMin = GET_Short(); + header->yMin = GET_Short(); + header->xMax = GET_Short(); + header->yMax = GET_Short(); + + header->Mac_Style = GET_UShort(); + header->Lowest_Rec_PPEM = GET_UShort(); + + header->Font_Direction = GET_Short(); + header->Index_To_Loc_Format = GET_Short(); + header->Glyph_Data_Format = GET_Short(); + + FORGET_Frame(); + + 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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_FUNC + TT_Error TT_Load_MaxProfile( TT_Face face, + FT_Stream stream ) + { + TT_Error error; + + TT_Long i; + TT_MaxProfile* maxProfile = &face->max_profile; + + + FT_TRACE2(( "Load_TT_MaxProfile( %08lx )\n", (TT_Long)face )); + + if ( ( i = TT_LookUp_Table( face, TTAG_maxp ) ) < 0 ) + { + error = TT_Err_Max_Profile_Missing; + + goto Exit; + } + + if ( FILE_Seek( face->dir_tables[i].Offset ) || + ACCESS_Frame( 32L ) ) + goto Exit; + + /* read frame data into face table */ + maxProfile->version = GET_ULong(); + maxProfile->numGlyphs = GET_UShort(); + + maxProfile->maxPoints = GET_UShort(); + maxProfile->maxContours = GET_UShort(); + maxProfile->maxCompositePoints = GET_UShort(); + maxProfile->maxCompositeContours = GET_UShort(); + + maxProfile->maxZones = GET_UShort(); + maxProfile->maxTwilightPoints = GET_UShort(); + + maxProfile->maxStorage = GET_UShort(); + maxProfile->maxFunctionDefs = GET_UShort(); + maxProfile->maxInstructionDefs = GET_UShort(); + maxProfile->maxStackElements = GET_UShort(); + maxProfile->maxSizeOfInstructions = GET_UShort(); + maxProfile->maxComponentElements = GET_UShort(); + maxProfile->maxComponentDepth = GET_UShort(); + + FORGET_Frame(); + + /* 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 = (TT_ULong)maxProfile->maxComponentElements + + maxProfile->maxComponentDepth; + + FT_TRACE2(( "GASP 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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + static + TT_Error TT_Load_Metrics( TT_Face face, + FT_Stream stream, + TT_Bool vertical ) + { + TT_Error error; + FT_Memory memory = stream->memory; + + TT_UShort n, num_shorts, num_longs; + TT_Long table; + + TT_LongMetrics** longs; + TT_ShortMetrics** shorts; + + TT_LongMetrics* long_metric; + + FT_TRACE2(( "TT_Load_%s_Metrics( %08lx )\n", + vertical ? "Vertical" : "Horizontal", (TT_Long)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! */ + /* */ + table = TT_LookUp_Table( face, TTAG_vmtx ); + if ( table < 0 ) + { + /* Set the 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 + { + if ( ( table = TT_LookUp_Table( face, TTAG_hmtx ) ) < 0 ) + { + 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; + } + + num_shorts = face->max_profile.numGlyphs - num_longs; + + if ( num_longs > face->max_profile.numGlyphs ) /* sanity check */ + { + FT_ERROR(( " more metrics than glyphs!\n" )); + error = 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 ( FILE_Seek( face->dir_tables[table].Offset ) || + ACCESS_Frame( face->dir_tables[table].Length ) ) + goto Exit; + + long_metric = *longs; + for ( n = 0; n < num_longs; n++ ) + { + long_metric->advance = GET_UShort(); + long_metric->bearing = GET_Short(); + long_metric++; + } + + for ( n = 0; n < num_shorts; n++ ) + (*shorts)[n] = GET_Short(); + + 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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_FUNC + TT_Error TT_Load_Metrics_Header( TT_Face face, + FT_Stream stream, + TT_Bool vertical ) + { + TT_Error error; + + TT_Long table; + TT_HoriHeader* header; + + + 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. */ + if ( ( table = TT_LookUp_Table( face, TTAG_vhea ) ) < 0 ) + { + 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. */ + if ( ( table = TT_LookUp_Table( face, TTAG_hhea ) ) < 0 ) + { + error = TT_Err_Horiz_Header_Missing; + + goto Exit; + } + + header = &face->horizontal; + } + + if ( FILE_Seek( face->dir_tables[table].Offset ) || + ACCESS_Frame( 36L ) ) + goto Exit; + + header->Version = GET_ULong(); + header->Ascender = GET_Short(); + header->Descender = GET_Short(); + header->Line_Gap = GET_Short(); + + header->advance_Width_Max = GET_UShort(); + + header->min_Left_Side_Bearing = GET_Short(); + header->min_Right_Side_Bearing = GET_Short(); + header->xMax_Extent = GET_Short(); + header->caret_Slope_Rise = GET_Short(); + header->caret_Slope_Run = GET_Short(); + + header->Reserved[0] = GET_Short(); + header->Reserved[1] = GET_Short(); + header->Reserved[2] = GET_Short(); + header->Reserved[3] = GET_Short(); + header->Reserved[4] = GET_Short(); + + header->metric_Data_Format = GET_Short(); + header->number_Of_HMetrics = GET_UShort(); + + FORGET_Frame(); + + 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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_FUNC + TT_Error TT_Load_Names( TT_Face face, FT_Stream stream ) + { + TT_Error error; + FT_Memory memory = stream->memory; + + TT_UShort i; + TT_Long table; + TT_Long storageSize; + + TT_NameTable* names; + TT_NameRec* namerec; + + + FT_TRACE2(( "Names " )); + + if ( ( table = TT_LookUp_Table( face, TTAG_name ) ) < 0 ) + { + /* The name table is required so indicate failure. */ + FT_TRACE2(( "is missing!\n" )); + error = TT_Err_Name_Table_Missing; + + goto Exit; + } + + /* Seek to the beginning of the table and check the frame access. */ + /* The names table has a 6 byte header. */ + if ( FILE_Seek( face->dir_tables[table].Offset ) || + ACCESS_Frame( 6L ) ) + goto Exit; + + names = &face->name_table; + + /* Load the initial names data. */ + names->format = GET_UShort(); + names->numNameRecords = GET_UShort(); + names->storageOffset = GET_UShort(); + + FORGET_Frame(); + + /* 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. */ + namerec = names->names; + storageSize = 0; + + for ( i = 0; i < names->numNameRecords; i++, namerec++ ) + { + TT_Long upper; + + + namerec->platformID = GET_UShort(); + namerec->encodingID = GET_UShort(); + namerec->languageID = GET_UShort(); + namerec->nameID = GET_UShort(); + namerec->stringLength = GET_UShort(); + namerec->stringOffset = GET_UShort(); + + upper = namerec->stringOffset + namerec->stringLength; + if ( upper > storageSize ) storageSize = upper; + } + + FORGET_Frame(); + + if ( ALLOC( names->storage, storageSize ) || + FILE_Read_At( face->dir_tables[table].Offset + names->storageOffset, + (void*)names->storage, storageSize ) ) + goto Exit; + + /* Go through and assign the string pointers to the name records. */ + namerec = names->names; + for ( i = 0; i < names->numNameRecords; i++, namerec++ ) + namerec->string = names->storage + namerec->stringOffset; + + /* Print Name Record Table in case of debugging */ +#if 0 + namerec = names->names; + for ( i = 0; i < names->numNameRecords; i++, namerec++ ) + { + TT_UShort j; + + + FT_TRACE2(( "%d %d %x %d ", + namerec->platformID, + namerec->encodingID, + namerec->languageID, + namerec->nameID )); + + /* I know that M$ encoded strings are Unicode, */ + /* but this works reasonable well for debugging purposes. */ + if ( namerec->string ) + for ( j = 0; j < namerec->stringLength; j++ ) + { + TT_Char c = *(namerec->string + j); + + if ( (TT_Byte)c < 128 ) + FT_TRACE2(( "%c", c )); + } + } + FT_TRACE2(( "\n" )); +#endif + + FT_TRACE2(( "loaded\n" )); + + Exit: + return error; + + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Free_Names */ + /* */ + /* */ + /* Frees the name records. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_FUNC + TT_Error TT_Free_Names( TT_Face face ) + { + FT_Memory memory = face->root.driver->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; + + return TT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_FUNC + TT_Error TT_Load_CMap( TT_Face face, + FT_Stream stream ) + { + TT_Error error; + FT_Memory memory = stream->memory; + + TT_Long i, off, cur_off, table_start; + TT_UShort n, limit; + + TT_CMapDir cmap_dir; + TT_CharMap charmap; + TT_CMapTable* cmap; + + + FT_TRACE2(( "CMaps " )); + + if ( ( i = TT_LookUp_Table( face, TTAG_cmap ) ) < 0 ) + { + error = TT_Err_CMap_Table_Missing; + + goto Exit; + } + + table_start = face->dir_tables[i].Offset; + + if ( ( FILE_Seek( table_start ) ) || + ( ACCESS_Frame( 4L ) ) ) /* 4 bytes cmap header */ + goto Exit; + + cmap_dir.tableVersionNumber = GET_UShort(); + cmap_dir.numCMaps = GET_UShort(); + + FORGET_Frame(); + + off = FILE_Pos(); /* save offset to cmapdir[] which follows */ + + /* save 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; + + limit = face->num_charmaps; + charmap = face->charmaps; + + for ( n = 0; n < limit; n++ ) + { + charmap->root.face = (FT_Face)face; + cmap = &charmap->cmap; + + if ( FILE_Seek( off ) || + ACCESS_Frame( 8L ) ) + goto Exit; + + cmap->loaded = FALSE; + cmap->platformID = GET_UShort(); + cmap->platformEncodingID = GET_UShort(); + + cur_off = GET_Long(); + + FORGET_Frame(); + + off = FILE_Pos(); + + if ( FILE_Seek( table_start + cur_off ) || + ACCESS_Frame( 6L ) ) + goto Exit; + + cmap->format = GET_UShort(); + cmap->length = GET_UShort(); + cmap->version = GET_UShort(); + + FORGET_Frame(); + + cmap->offset = FILE_Pos(); + + charmap++; + } + + 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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_FUNC + TT_Error TT_Load_OS2( TT_Face face, + FT_Stream stream ) + { + TT_Error error; + + TT_Long i; + TT_Int j; + TT_OS2* os2; + + + 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. */ + if ( ( i = TT_LookUp_Table( face, TTAG_OS2 ) ) < 0 ) + { + FT_TRACE2(( "is missing\n!" )); + face->os2.version = 0xFFFF; + error = TT_Err_Ok; + + goto Exit; + } + + if ( FILE_Seek( face->dir_tables[i].Offset ) || + ACCESS_Frame( 78L ) ) + goto Exit; + + os2 = &face->os2; + + os2->version = GET_UShort(); + os2->xAvgCharWidth = GET_Short(); + os2->usWeightClass = GET_UShort(); + os2->usWidthClass = GET_UShort(); + os2->fsType = GET_Short(); + os2->ySubscriptXSize = GET_Short(); + os2->ySubscriptYSize = GET_Short(); + os2->ySubscriptXOffset = GET_Short(); + os2->ySubscriptYOffset = GET_Short(); + os2->ySuperscriptXSize = GET_Short(); + os2->ySuperscriptYSize = GET_Short(); + os2->ySuperscriptXOffset = GET_Short(); + os2->ySuperscriptYOffset = GET_Short(); + os2->yStrikeoutSize = GET_Short(); + os2->yStrikeoutPosition = GET_Short(); + os2->sFamilyClass = GET_Short(); + + for ( j = 0; j < 10; j++ ) + os2->panose[j] = GET_Byte(); + + os2->ulUnicodeRange1 = GET_ULong(); + os2->ulUnicodeRange2 = GET_ULong(); + os2->ulUnicodeRange3 = GET_ULong(); + os2->ulUnicodeRange4 = GET_ULong(); + + for ( j = 0; j < 4; j++ ) + os2->achVendID[j] = GET_Byte(); + + os2->fsSelection = GET_UShort(); + os2->usFirstCharIndex = GET_UShort(); + os2->usLastCharIndex = GET_UShort(); + os2->sTypoAscender = GET_Short(); + os2->sTypoDescender = GET_Short(); + os2->sTypoLineGap = GET_Short(); + os2->usWinAscent = GET_UShort(); + os2->usWinDescent = GET_UShort(); + + FORGET_Frame(); + + if ( os2->version >= 0x0001 ) + { + /* only version 1 tables */ + + if ( ACCESS_Frame( 8L ) ) /* read into frame */ + goto Exit; + + os2->ulCodePageRange1 = GET_ULong(); + os2->ulCodePageRange2 = GET_ULong(); + + FORGET_Frame(); + } + else + { + os2->ulCodePageRange1 = 0; + os2->ulCodePageRange2 = 0; + } + + 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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_FUNC + TT_Error TT_Load_PostScript( TT_Face face, + FT_Stream stream ) + { + TT_Error error; + TT_Long i; + TT_Postscript* post = &face->postscript; + + + FT_TRACE2(( "PostScript " )); + + if ( ( i = TT_LookUp_Table( face, TTAG_post ) ) < 0 ) + return TT_Err_Post_Table_Missing; + + if ( FILE_Seek( face->dir_tables[i].Offset ) || + ACCESS_Frame( 32L ) ) + return error; + + /* read frame data into face table */ + + post->FormatType = GET_ULong(); + post->italicAngle = GET_ULong(); + post->underlinePosition = GET_Short(); + post->underlineThickness = GET_Short(); + post->isFixedPitch = GET_ULong(); + post->minMemType42 = GET_ULong(); + post->maxMemType42 = GET_ULong(); + post->minMemType1 = GET_ULong(); + post->maxMemType1 = GET_ULong(); + + FORGET_Frame(); + + /* we don't load the glyph names, we do that in another */ + /* module (ttpost). */ + + FT_TRACE2(( "loaded\n" )); + + return TT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Gasp */ + /* */ + /* */ + /* Loads the `GASP' table into a face object. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_FUNC + TT_Error TT_Load_Gasp( TT_Face face, + FT_Stream stream ) + { + TT_Error error; + FT_Memory memory = stream->memory; + + TT_Long table; + TT_UShort num_ranges; + TT_UShort j; + TT_GaspRange* gaspranges; + + + FT_TRACE2(( "TT_Load_Gasp( %08lx )\n", (TT_Long)face )); + + error = TT_Err_Ok; + + /* the gasp table is optional */ + if ( ( table = TT_LookUp_Table( face, TTAG_gasp ) ) < 0 ) + goto Exit; + + if ( FILE_Seek( face->dir_tables[table].Offset ) || + 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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_FUNC + TT_Error TT_Load_Kern( TT_Face face, + FT_Stream stream ) + { + TT_Error error; + FT_Memory memory = stream->memory; + + TT_Long table; + TT_UShort n, num_tables, version; + + + error = TT_Err_Ok; + table = TT_LookUp_Table( face, TTAG_kern ); + if ( table < 0 ) + goto Exit; + + if ( FILE_Seek( face->dir_tables[table].Offset ) || + READ_UShort( version ) || + READ_UShort( num_tables ) ) + goto Exit; + + for ( n = 0; n < num_tables; n++ ) + { + TT_UShort coverage; + + + if ( FILE_Skip( 4L ) || + READ_UShort( coverage ) ) + goto Exit; + + if ( coverage == 0x0001 ) + { + TT_UShort num_pairs, m; + TT_Kern_0_Pair* pair; + + + /* found a horizontal format 0 kerning table ! */ + if ( READ_UShort( num_pairs ) || + FILE_Skip( 6 ) ) + goto Exit; + + /* allocate array of kerning pairs */ + if ( ALLOC_ARRAY( face->kern_pairs, num_pairs, TT_Kern_0_Pair ) ) + goto Exit; + + /* read the kerning pairs */ + if ( ACCESS_Frame( 6L * num_pairs ) ) + goto Exit; + + pair = face->kern_pairs; + for ( m = 0; m < num_pairs; m++ ) + { + pair->left = GET_UShort(); + pair->right = GET_UShort(); + pair->value = GET_UShort(); + pair++; + } + + FORGET_Frame(); + + face->num_kern_pairs = num_pairs; + face->kern_table_index = n; + 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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_FUNC + TT_Error TT_Load_Hdmx( TT_Face face, + FT_Stream stream ) + { + TT_Error error; + FT_Memory memory = stream->memory; + + TT_HdmxRec* rec; + TT_Hdmx hdmx; + TT_Long table; + TT_UShort n; + TT_Long num_glyphs; + TT_Long record_size; + + hdmx.version = 0; + hdmx.num_records = 0; + hdmx.records = 0; + + face->hdmx = hdmx; + + error = TT_Err_Ok; + + /* ths table is optional */ + if ( ( table = TT_LookUp_Table( face, TTAG_hdmx ) ) < 0 ) + return error; + + if ( FILE_Seek( face->dir_tables[table].Offset ) || + 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( hdmx.records, sizeof ( TT_HdmxRec ) * hdmx.num_records ) ) + goto Exit; + + num_glyphs = face->root.num_glyphs; + record_size -= num_glyphs + 2; + rec = hdmx.records; + + for ( n = 0; n < hdmx.num_records; n++ ) + { + /* read record */ + if ( READ_Byte( rec->ppem ) || + READ_Byte( rec->max_width ) ) + goto Exit; + + if ( ALLOC( rec->widths, num_glyphs ) || + FILE_Read( rec->widths, num_glyphs ) ) + goto Exit; + + /* skip padding bytes */ + if ( record_size > 0 ) + if ( FILE_Skip( record_size ) ) + goto Exit; + + rec++; + } + + face->hdmx = hdmx; + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Free_Hdmx */ + /* */ + /* */ + /* Frees the horizontal device metrics table. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_FUNC + TT_Error TT_Free_Hdmx( TT_Face face ) + { + if ( face ) + { + TT_UShort n; + FT_Memory memory = face->root.driver->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; + } + + return TT_Err_Ok; + } + + +/* END */ diff --git a/src/shared/sfnt/ttload.h b/src/shared/sfnt/ttload.h new file mode 100644 index 000000000..889c9e02f --- /dev/null +++ b/src/shared/sfnt/ttload.h @@ -0,0 +1,353 @@ +/***************************************************************************/ +/* */ +/* ttload.h */ +/* */ +/* Load the basic TrueType tables, i.e., tables that can be either in */ +/* TTF or OTF font (specification). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 + + + /*************************************************************************/ + /* */ + /* */ + /* TT_LookUp_Table */ + /* */ + /* */ + /* Looks for a TrueType table by name. */ + /* */ + /* */ + /* face :: A face object handle. */ + /* tag :: The searched tag. */ + /* */ + /* */ + /* Index of table if found, -1 otherwise. */ + /* */ + EXPORT_DEF + TT_Long TT_LookUp_Table( TT_Face face, + TT_ULong tag ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Directory */ + /* */ + /* */ + /* Loads the table directory into a face object. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: The input stream. */ + /* faceIndex :: The index of the TrueType font, if we're opening a */ + /* collection. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_DEF + TT_Error TT_Load_Directory( TT_Face face, + FT_Stream stream, + TT_Long faceIndex ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Any */ + /* */ + /* */ + /* Loads any font table into client memory. Used by the */ + /* TT_Get_Font_Data() API function. */ + /* */ + /* */ + /* 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. */ + /* */ + LOCAL_DEF + TT_Error TT_Load_Any( TT_Face face, + TT_ULong tag, + TT_Long offset, + void* buffer, + TT_Long* length ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Header */ + /* */ + /* */ + /* Loads the TrueType font header. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_DEF + TT_Error TT_Load_Header( TT_Face face, + FT_Stream stream ); + + + /*************************************************************************/ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_DEF + TT_Error TT_Load_Metrics_Header( TT_Face face, + FT_Stream stream, + TT_Bool vertical ); + + + LOCAL_DEF + TT_Error TT_Load_CMap( TT_Face face, + FT_Stream stream ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_MaxProfile */ + /* */ + /* */ + /* Loads the maximum profile into a face object. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_DEF + TT_Error TT_Load_MaxProfile( TT_Face face, + FT_Stream stream ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Names */ + /* */ + /* */ + /* Loads the name records. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_DEF + TT_Error TT_Load_Names( TT_Face face, + FT_Stream stream ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_OS2 */ + /* */ + /* */ + /* Loads the OS2 table. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: A handle to the input stream. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_DEF + TT_Error TT_Load_OS2( TT_Face face, + FT_Stream stream ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Postscript */ + /* */ + /* */ + /* Loads the Postscript table. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: A handle to the input stream. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_DEF + TT_Error TT_Load_PostScript( TT_Face face, + FT_Stream stream ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Hdmx */ + /* */ + /* */ + /* Loads the horizontal device metrics table. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: A handle to the input stream. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_DEF + TT_Error TT_Load_Hdmx( TT_Face face, + FT_Stream stream ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Free_Names */ + /* */ + /* */ + /* Frees the name records. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_DEF + TT_Error TT_Free_Names( TT_Face face ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Free_Hdmx */ + /* */ + /* */ + /* Frees the horizontal device metrics table. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_DEF + TT_Error TT_Free_Hdmx ( TT_Face face ); + + + /*************************************************************************/ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_DEF + TT_Error TT_Load_Kern( TT_Face face, + FT_Stream stream ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Gasp */ + /* */ + /* */ + /* Loads the `GASP' table into a face object. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_DEF + TT_Error TT_Load_Gasp( TT_Face face, + FT_Stream stream ); + + +#endif /* TTLOAD_H */ + + +/* END */ diff --git a/src/shared/sfnt/ttpost.c b/src/shared/sfnt/ttpost.c new file mode 100644 index 000000000..30aa19fdd --- /dev/null +++ b/src/shared/sfnt/ttpost.c @@ -0,0 +1,713 @@ +/***************************************************************************/ +/* */ +/* ttpost.c */ +/* */ +/* Postscript names table processing (body). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 +#include +#include + + /* the 258 default Mac PS glyph names */ + + const TT_String* TT_Mac_Postscript_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", + }; + + + static + TT_Error Load_Format_20( TT_Face face, + FT_Stream stream ) + { + FT_Memory memory = stream->memory; + TT_Error error; + + TT_UShort num_glyphs; + TT_UShort num_names; + + TT_UShort* glyph_indices = 0; + TT_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 */ + { + TT_UShort n; + + + if ( ALLOC_ARRAY ( glyph_indices, num_glyphs, TT_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 */ + { + TT_UShort n; + + + num_names = 0; + + for ( n = 0; n < num_glyphs; n++ ) + { + TT_UShort index; + + + index = glyph_indices[n]; + if ( index >= 258 ) + { + index -= 257; + if ( index > num_names ) + num_names = index; + } + } + } + + /* now load the name strings */ + { + TT_UShort n; + + + if ( ALLOC_ARRAY( name_strings, num_names, TT_Char* ) ) + goto Fail; + + for ( n = 0; n < num_names; n++ ) + { + TT_Byte len; + + + if ( READ_Byte ( len ) || + ALLOC_ARRAY( name_strings[n], len+1, TT_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: + { + TT_UShort n; + + + for ( n = 0; n < num_names; n++ ) + FREE( name_strings[n] ); + } + + Fail: + FREE( name_strings ); + FREE( glyph_indices ); + + Exit: + return error; + } + + + static + TT_Error Load_Format_25( TT_Face face, + FT_Stream stream ) + { + FT_Memory memory = stream->memory; + TT_Error error; + + TT_UShort num_glyphs; + TT_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 */ + { + TT_UShort n; + + + for ( n = 0; n < num_glyphs; n++ ) + { + TT_Long index = (TT_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 + TT_Error Load_Post_Names( TT_Face face ) + { + FT_Stream stream; + TT_Error error; + + /* get a stream for the face's resource */ + stream = face->root.stream; + + /* seek to the beginning of the PS names table */ + { + TT_Long table; + + + table = TT_LookUp_Table( face, TTAG_post ); + if ( FILE_Seek( face->dir_tables[table].Offset + 32L ) ) + goto Exit; + } + + /* now read postscript table */ + switch ( face->postscript.FormatType ) + { + case 0x00020000: + error = Load_Format_20( face, stream ); + break; + + case 0x00028000: + 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 0x00020000: + { + TT_Post_20* table = &names->names.format_20; + TT_UShort n; + + + FREE( table->glyph_indices ); + table->num_glyphs = 0; + + for ( n = 0; n < table->num_names; n++ ) + FREE( table->glyph_names[n] ); + + FREE( table->glyph_names ); + table->num_names = 0; + } + break; + + case 0x00028000: + { + 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. */ + /* */ + /* */ + /* 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! */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + EXPORT_FUNC + TT_Error TT_Get_PS_Name( TT_Face face, + TT_UInt index, + TT_String** PSname ) + { + TT_Error error; + TT_Post_Names* names; + + if ( !face ) + return TT_Err_Invalid_Face_Handle; + + if ( index >= face->root.num_glyphs ) + return TT_Err_Invalid_Glyph_Index; + + names = &face->postscript_names; + + /* `.notdef' by default */ + *PSname = (TT_String*)TT_Mac_Postscript_Names[0]; + + switch ( face->postscript.FormatType ) + { + case 0x00010000: + if ( index < 258 ) /* paranoid checking */ + *PSname = (TT_String*)TT_Mac_Postscript_Names[index]; + break; + + case 0x00020000: + { + TT_Post_20* table = &names->names.format_20; + + + if ( !names->loaded ) + { + error = Load_Post_Names( face ); + if ( error ) + break; + } + + if ( index < table->num_glyphs ) + { + TT_UShort name_index = table->glyph_indices[index]; + + + if ( name_index < 258 ) + *PSname = (TT_String*)TT_Mac_Postscript_Names[name_index]; + else + *PSname = (TT_String*)table->glyph_names[name_index - 258]; + } + } + break; + + case 0x00028000: + { + 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 = (TT_String*)TT_Mac_Postscript_Names[index]; + } + } + break; + + case 0x00030000: + break; /* nothing to do */ + } + + return TT_Err_Ok; + } + + +/* END */ diff --git a/src/shared/sfnt/ttpost.h b/src/shared/sfnt/ttpost.h new file mode 100644 index 000000000..1ff813e43 --- /dev/null +++ b/src/shared/sfnt/ttpost.h @@ -0,0 +1,95 @@ +/***************************************************************************/ +/* */ +/* ttpost.h */ +/* */ +/* Postcript name table processing for TrueType and OpenType fonts */ +/* (specification). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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. */ + /* */ + /*************************************************************************/ + + +#ifndef TTPOST_H +#define TTPOST_H + +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +#define TT_Err_Invalid_Post_Table_Format 0x0B00 +#define TT_Err_Invalid_Post_Table 0x0B01 + + +#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES + +#if 0 + /* the 258 standard Mac glyph names, used for format 1.0 and 2.5 */ + LOCAL_DEF + const TT_String* TT_Mac_Postscript_Names[]; +#endif + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Get_PS_Name */ + /* */ + /* */ + /* 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! */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + EXPORT_DEF + TT_Error TT_Get_PS_Name( TT_Face face, + TT_UInt index, + TT_String** PSname ); + + + LOCAL_DEF + void TT_Free_Post_Names( TT_Face face ); + + +#endif /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */ + + +#ifdef __cplusplus +} +#endif + + +#endif /* TTPOST_H */ + + +/* END */ diff --git a/src/shared/sfnt/ttsbit.c b/src/shared/sfnt/ttsbit.c new file mode 100644 index 000000000..fd3fc2d15 --- /dev/null +++ b/src/shared/sfnt/ttsbit.c @@ -0,0 +1,1443 @@ +/***************************************************************************/ +/* */ +/* ttsbit.c */ +/* */ +/* TrueType and OpenType embedded bitmap support (body). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/* */ +/* WARNING: This file should not be compiled directly, it is meant to be */ +/* included in the source of several font drivers (i.e., the TTF */ +/* and OTF drivers). */ +/* */ +/***************************************************************************/ + + +#include + +#include +#include + + + /*************************************************************************/ + /* */ + /* */ + /* 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; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Small_SBit_Metrics */ + /* */ + /* */ + /* Loads a small bitmap metrics record. */ + /* */ + /* */ + /* stream :: The input stream. */ + /* */ + /* */ + /* metrics :: A small metrics structure. */ + /* */ + static + void TT_Load_Small_SBit_Metrics( TT_SBit_Small_Metrics* metrics, + FT_Stream stream ) + { + metrics->height = GET_Byte(); + metrics->width = GET_Byte(); + metrics->bearingX = GET_Char(); + metrics->bearingY = GET_Char(); + metrics->advance = GET_Byte(); + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_SBit_Metrics */ + /* */ + /* */ + /* Loads a bitmap metrics record. */ + /* */ + /* */ + /* stream :: The input stream. */ + /* */ + /* */ + /* metrics :: A metrics structure. */ + /* */ + static + void TT_Load_SBit_Metrics( TT_SBit_Metrics* metrics, + FT_Stream stream ) + { + metrics->height = GET_Byte(); + metrics->width = GET_Byte(); + + metrics->horiBearingX = GET_Char(); + metrics->horiBearingY = GET_Char(); + metrics->horiAdvance = GET_Byte(); + + metrics->vertBearingX = GET_Char(); + metrics->vertBearingY = GET_Char(); + metrics->vertAdvance = GET_Byte(); + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_SBit_Line_Metrics */ + /* */ + /* */ + /* Loads a bitmap line metrics record. */ + /* */ + /* */ + /* stream :: The input stream. */ + /* */ + /* */ + /* metrics :: A line metrics structure. */ + /* */ + static + void TT_Load_SBit_Line_Metrics( TT_SBit_Line_Metrics* metrics, + FT_Stream stream ) + { + metrics->ascender = GET_Char(); + metrics->descender = GET_Char(); + metrics->max_width = GET_Byte(); + + metrics->caret_slope_numerator = GET_Char(); + metrics->caret_slope_denominator = GET_Char(); + metrics->caret_offset = GET_Char(); + + metrics->min_origin_SB = GET_Char(); + metrics->min_advance_SB = GET_Char(); + metrics->max_before_BL = GET_Char(); + metrics->min_after_BL = GET_Char(); + metrics->pads[0] = GET_Char(); + metrics->pads[1] = GET_Char(); + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_SBit_Const_Metrics */ + /* */ + /* */ + /* Loads the metrics for `EBLC' index tables format 2 and 5. */ + /* */ + /* */ + /* range :: The target range. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + static + TT_Error Load_SBit_Const_Metrics( TT_SBit_Range* range, + FT_Stream stream ) + { + TT_Error error; + + if ( !ACCESS_Frame( 12L ) ) + { + range->image_size = GET_ULong(); + TT_Load_SBit_Metrics( &range->metrics, stream ); + + FORGET_Frame(); + } + + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + static + TT_Error Load_SBit_Range_Codes( TT_SBit_Range* range, + FT_Stream stream, + TT_Bool load_offsets ) + { + TT_Error error; + TT_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, TT_ULong ) ) + goto Exit; + + size = count * 4L; + } + else + size = count * 2L; + + /* Allocate glyph codes table and access frame */ + if ( ALLOC_ARRAY ( range->glyph_codes, count, TT_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] = (TT_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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + static + TT_Error Load_SBit_Range( TT_SBit_Range* range, + FT_Stream stream ) + { + TT_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 */ + { + TT_ULong num_glyphs, n; + TT_Int size_elem; + TT_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, TT_ULong ) || + + ACCESS_Frame( num_glyphs * size_elem ) ) + goto Exit; + + for ( n = 0; n < num_glyphs; n++ ) + range->glyph_offsets[n] = (TT_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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_FUNC + TT_Error TT_Load_SBit_Strikes( TT_Face face, + FT_Stream stream ) + { + TT_Error error = 0; + FT_Memory memory = stream->memory; + TT_Fixed version; + TT_ULong num_strikes; + TT_ULong table_base; + TT_Long table; + + + /* this table is optional */ + if ( ( table = TT_LookUp_Table( face, TTAG_EBLC ) ) < 0 ) + goto Exit; + + table_base = face->dir_tables[table].Offset; + if ( FILE_Seek( table_base ) || + ACCESS_Frame( 8L ) ) + goto Exit; + + version = GET_Long(); + num_strikes = GET_ULong(); + + FORGET_Frame(); + + /* check version number and strike count */ + if ( version != 0x00020000 || + num_strikes >= 0x10000 ) + { + 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; + TT_ULong count = num_strikes; + + if ( ACCESS_Frame( 48L * num_strikes ) ) + goto Exit; + + while ( count > 0 ) + { + TT_ULong indexTablesSize; + + + strike->ranges_offset = GET_ULong(); + indexTablesSize = GET_ULong(); /* don't save */ + + strike->num_ranges = GET_ULong(); + strike->color_ref = GET_ULong(); + + TT_Load_SBit_Line_Metrics( &strike->hori, stream ); + TT_Load_SBit_Line_Metrics( &strike->vert, stream ); + + strike->start_glyph = GET_UShort(); + strike->end_glyph = GET_UShort(); + strike->x_ppem = GET_Byte(); + strike->y_ppem = GET_Byte(); + strike->bit_depth = GET_Byte(); + strike->flags = GET_Char(); + + count--; + strike++; + } + + FORGET_Frame(); + } + + /* allocate the index ranges for each strike table */ + { + TT_SBit_Strike* strike = face->sbit_strikes; + TT_ULong count = num_strikes; + + + while ( count > 0 ) + { + TT_SBit_Range* range; + TT_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. */ + /* */ + /* */ + /* TrueType error code. 0 means the glyph index was found. */ + /* */ + static + TT_Error Find_SBit_Range( TT_UShort glyph_index, + TT_SBit_Strike* strike, + TT_SBit_Range** arange, + TT_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 ) + { + TT_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: + { + TT_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; + break; + } + } + } + + /* fall-through */ + default: + goto Fail; + } + + /* 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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. Returns */ + /* TT_Err_Invalid_Argument if no sbit exist for the requested glyph. */ + /* */ + static + TT_Error Find_SBit_Image( TT_Face face, + TT_UShort glyph_index, + TT_Int x_ppem, + TT_Int y_ppem, + + TT_SBit_Range** arange, + TT_SBit_Strike** astrike, + TT_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 ) + { + TT_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. */ + /* */ + /* */ + /* TrueType 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 + TT_Error Load_SBit_Metrics( FT_Stream stream, + TT_SBit_Range* range, + TT_SBit_Metrics* metrics ) + { + TT_Error error = TT_Err_Ok; + + + switch ( range->index_format ) + { + case 1: /* variable metrics */ + case 3: + case 4: + { + switch ( range->image_format ) + { + case 1: /* small metrics */ + case 2: + case 8: + { + TT_SBit_Small_Metrics smetrics; + + + /* read small metrics */ + if ( ACCESS_Frame( 5L ) ) + goto Exit; + TT_Load_Small_SBit_Metrics( &smetrics, stream ); + FORGET_Frame(); + + /* 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; + + default: /* big metrics */ + if ( ACCESS_Frame( 8L ) ) + goto Exit; + TT_Load_SBit_Metrics( metrics, stream ); + FORGET_Frame(); + } + } + break; + + default: /* constant metrics */ + *metrics = range->metrics; + } + + 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. */ + /* */ + /* --------- */ + /* | | ----- */ + /* | *** | |***| */ + /* | * | | * | */ + /* | * | ------> | * | */ + /* | * | | * | */ + /* | * | | * | */ + /* | *** | |***| */ + /* --------- ----- */ + /* */ + /***********************************************************************/ + + TT_Int rows, count; + TT_Long line_len; + TT_Byte* line; + + + /***********************************************************************/ + /* */ + /* first of all, checks the top-most lines of the bitmap, and removes */ + /* them if they're empty. */ + /* */ + { + line = (TT_Byte*)map->buffer; + rows = map->rows; + line_len = map->pitch; + + + for ( count = 0; count < rows; count++ ) + { + TT_Byte* cur = line; + TT_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 = (TT_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 = (TT_Byte*)map->buffer + (rows - 1) * line_len; + + for ( count = 0; count < rows; count++ ) + { + TT_Byte* cur = line; + TT_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 + { + TT_Byte* limit; + + + line = (TT_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 = (TT_Byte*)map->buffer; + limit = line + rows * line_len; + + for ( ; line < limit; line += line_len ) + { + TT_Int n, width = map->width; + TT_Byte old; + TT_Byte* cur = line; + + + old = cur[0] << 1; + for ( n = 8; n < width; n += 8 ) + { + TT_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 + { + TT_Int right = map->width-1; + TT_Byte* limit; + TT_Byte mask; + + + line = (TT_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 + TT_Error Load_SBit_Single( FT_Bitmap* map, + TT_Int x_offset, + TT_Int y_offset, + TT_Int pix_bits, + TT_UShort image_format, + TT_SBit_Metrics* metrics, + FT_Stream stream ) + { + TT_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; + } + + { + TT_Int glyph_width = metrics->width; + TT_Int glyph_height = metrics->height; + TT_Int glyph_size; + TT_Int line_bits = pix_bits * glyph_width; + TT_Bool pad_bytes = 0; + + + /* compute size of glyph image */ + switch ( image_format ) + { + case 1: /* byte-padded formats */ + case 6: + { + TT_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, stream->cursor, line_bits, pad_bytes, + x_offset * pix_bits, y_offset ); + + FORGET_Frame(); + } + + Exit: + return error; + } + + + static + TT_Error Load_SBit_Image( TT_SBit_Strike* strike, + TT_SBit_Range* range, + TT_ULong ebdt_pos, + TT_ULong glyph_offset, + FT_Bitmap* map, + TT_Int x_offset, + TT_Int y_offset, + FT_Stream stream, + TT_SBit_Metrics* metrics ) + { + FT_Memory memory = stream->memory; + TT_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 ) + { + TT_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 */ + case 9: + break; + + default: /* invalid image format */ + return TT_Err_Invalid_File_Format; + } + + /* All right, we're in a compound format. First of all, read */ + /* the array of elements */ + { + TT_SBit_Component* components; + TT_SBit_Component* comp; + TT_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; + TT_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. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* */ + /* map :: The target pixmap. */ + /* metrics :: A big sbit metrics structure for the glyph image. */ + /* */ + /* */ + /* TrueType 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 + TT_Error TT_Load_SBit_Image( TT_Face face, + TT_Int x_ppem, + TT_Int y_ppem, + TT_UInt glyph_index, + FT_Stream stream, + FT_Bitmap* map, + TT_SBit_Metrics* metrics ) + { + TT_Error error; + FT_Memory memory = stream->memory; + TT_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 */ + { + TT_Long table = TT_LookUp_Table( face, TTAG_EBDT ); + + + if ( table < 0 ) + { + error = TT_Err_Invalid_File_Format; + goto Exit; + } + + ebdt_pos = face->dir_tables[table].Offset; + } + + /* clear the bitmap & load the 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; + + /* 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; + + metrics->vertBearingX = -metrics->width / 2; + metrics->vertBearingY = advance / 10; + metrics->vertAdvance = advance * 12 / 10; + } + + /* Crop the bitmap now */ + Crop_Bitmap( map, metrics ); + + Exit: + return error; + } + + +/* END */ diff --git a/src/shared/sfnt/ttsbit.h b/src/shared/sfnt/ttsbit.h new file mode 100644 index 000000000..414ceaed7 --- /dev/null +++ b/src/shared/sfnt/ttsbit.h @@ -0,0 +1,104 @@ +/***************************************************************************/ +/* */ +/* ttsbit.h */ +/* */ +/* TrueType and OpenType embedded bitmap support (specification). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef TTSBIT_H +#define TTSBIT_H + +#include + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_SBit_Strikes */ + /* */ + /* */ + /* Loads the table of embedded bitmap sizes for this face. */ + /* */ + /* */ + /* face :: The target face object. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_DEF + TT_Error TT_Load_SBit_Strikes( TT_Face face, + FT_Stream stream ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Free_SBit_Strikes */ + /* */ + /* */ + /* Releases the embedded bitmap tables. */ + /* */ + /* */ + /* face :: The target face object. */ + /* */ + LOCAL_DEF + void TT_Free_SBit_Strikes( TT_Face face ); + + + /*************************************************************************/ + /* */ + /* */ + /* 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. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* */ + /* map :: The target pixmap. */ + /* metrics :: A big sbit metrics structure for the glyph image. */ + /* */ + /* */ + /* TrueType 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_DEF + TT_Error TT_Load_SBit_Image( TT_Face face, + TT_Int x_ppem, + TT_Int y_ppem, + TT_UInt glyph_index, + FT_Stream stream, + FT_Bitmap* map, + TT_SBit_Metrics* metrics ); + + +#endif /* TTSBIT_H */ + + +/* END */ diff --git a/src/shared/sfnt/tttypes.h b/src/shared/sfnt/tttypes.h new file mode 100644 index 000000000..33b24534a --- /dev/null +++ b/src/shared/sfnt/tttypes.h @@ -0,0 +1,1848 @@ +/***************************************************************************/ +/* */ +/* tttypes.h */ +/* */ +/* Basic SFNT/TrueType type definitions and interface (specification */ +/* only). */ +/* */ +/* This code is shared by all TrueType and OpenType drivers. */ +/* */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 + + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*** ***/ + /*** ***/ + /*** DEFINITIONS OF BASIC DATA TYPES ***/ + /*** ***/ + /*** ***/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* The REDEFINE() macro is used to convert a FreeType generic type into */ + /* a TrueType-specific one. It simply replaces the `FT_' prefix by */ + /* `TT_' in order to define compatible types like TT_Long, TT_Error, */ + /* TT_Outline, etc. */ + /* */ +#undef REDEFINE +#define REDEFINE( type ) typedef FT_##type TT_##type + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Bool */ + /* */ + /* */ + /* A typedef of unsigned char, used for simple booleans. */ + /* */ + REDEFINE( Bool ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_FWord */ + /* */ + /* */ + /* A signed 16-bit integer used to store a distance in original font */ + /* units. */ + /* */ + REDEFINE( FWord ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_UFWord */ + /* */ + /* */ + /* An unsigned 16-bit integer used to store a distance in original */ + /* font units. */ + /* */ + REDEFINE( UFWord ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Char */ + /* */ + /* */ + /* A simple typedef for the _signed_ char type. */ + /* */ + REDEFINE( Char ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Byte */ + /* */ + /* */ + /* A simple typedef for the _unsigned_ char type. */ + /* */ + REDEFINE( Byte ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_String */ + /* */ + /* */ + /* A simple typedef for the char type, usually used for strings. */ + /* */ + REDEFINE( String ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Short */ + /* */ + /* */ + /* A typedef for signed short. */ + /* */ + REDEFINE( Short ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_UShort */ + /* */ + /* */ + /* A typedef for unsigned short. */ + /* */ + REDEFINE( UShort ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Int */ + /* */ + /* */ + /* A typedef for the int type. */ + /* */ + REDEFINE( Int ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_UInt */ + /* */ + /* */ + /* A typedef for the unsigned int type. */ + /* */ + REDEFINE( UInt ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Long */ + /* */ + /* */ + /* A typedef for signed long. */ + /* */ + REDEFINE( Long ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_ULong */ + /* */ + /* */ + /* A typedef for unsigned long. */ + /* */ + REDEFINE( ULong ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_F2Dot14 */ + /* */ + /* */ + /* A signed 2.14 fixed float type used for unit vectors. */ + /* */ + REDEFINE( F2Dot14 ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_F26Dot6 */ + /* */ + /* */ + /* A signed 26.6 fixed float type used for vectorial pixel */ + /* coordinates. */ + /* */ + REDEFINE( F26Dot6 ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Fixed */ + /* */ + /* */ + /* This type is used to store 16.16 fixed float values, like scales */ + /* or matrix coefficients. */ + /* */ + REDEFINE( Fixed ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_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. */ + /* */ + REDEFINE( Pos ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Vector */ + /* */ + /* */ + /* A simple structure used to store a 2d vector; coordinates are of */ + /* the TT_Pos type. */ + /* */ + /* */ + /* x :: The horizontal coordinate. */ + /* y :: The vertical coordinate. */ + /* */ + REDEFINE( Vector ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_UnitVector */ + /* */ + /* */ + /* A simple structure used to store a 2d vector unit vector. Uses */ + /* TT_F2Dot14 types. */ + /* */ + /* */ + /* x :: Horizontal coordinate. */ + /* y :: Vertical coordinate. */ + /* */ + REDEFINE( UnitVector ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_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. */ + /* */ + REDEFINE( Matrix ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_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). */ + /* */ + REDEFINE( BBox ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Error */ + /* */ + /* */ + /* The TrueType error code type. A value of 0 is always interpreted */ + /* as a successful operation. */ + /* */ + REDEFINE( Error ); + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*** ***/ + /*** ***/ + /*** 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_ + { + TT_ULong Tag; + TT_Fixed version; + TT_Long DirCount; + TT_ULong* TableDirectory; + + } TTC_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_ + { + TT_Fixed version; /* should be 0x10000 */ + TT_UShort numTables; /* number of tables */ + + TT_UShort searchRange; /* These parameters are only used */ + TT_UShort entrySelector; /* for a dichotomy search in the */ + TT_UShort rangeShift; /* directory. We ignore them. */ + + } TT_TableDir; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_TableDirEntry */ + /* */ + /* */ + /* 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_TableDirEntry_ + { + TT_ULong Tag; /* table type */ + TT_ULong CheckSum; /* table checksum */ + TT_ULong Offset; /* table file offset */ + TT_ULong Length; /* table length */ + + } TT_TableDirEntry; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Header */ + /* */ + /* */ + /* A structure used to model a TrueType font header table. All */ + /* fields follow the TrueType specification. */ + /* */ + typedef struct TT_Header_ + { + TT_Fixed Table_Version; + TT_Fixed Font_Revision; + + TT_Long CheckSum_Adjust; + TT_Long Magic_Number; + + TT_UShort Flags; + TT_UShort Units_Per_EM; + + TT_Long Created [2]; + TT_Long Modified[2]; + + TT_FWord xMin; + TT_FWord yMin; + TT_FWord xMax; + TT_FWord yMax; + + TT_UShort Mac_Style; + TT_UShort Lowest_Rec_PPEM; + + TT_Short Font_Direction; + TT_Short Index_To_Loc_Format; + TT_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_ + { + TT_Fixed Version; + TT_FWord Ascender; + TT_FWord Descender; + TT_FWord Line_Gap; + + TT_UFWord advance_Width_Max; /* advance width maximum */ + + TT_FWord min_Left_Side_Bearing; /* minimum left-sb */ + TT_FWord min_Right_Side_Bearing; /* minimum right-sb */ + TT_FWord xMax_Extent; /* xmax extents */ + TT_FWord caret_Slope_Rise; + TT_FWord caret_Slope_Run; + TT_FWord caret_Offset; + + TT_Short Reserved[4]; + + TT_Short metric_Data_Format; + TT_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_ + { + TT_Fixed Version; + TT_FWord Ascender; + TT_FWord Descender; + TT_FWord Line_Gap; + + TT_UFWord advance_Height_Max; /* advance height maximum */ + + TT_FWord min_Top_Side_Bearing; /* minimum left-sb or top-sb */ + TT_FWord min_Bottom_Side_Bearing; /* minimum right-sb or bottom-sb */ + TT_FWord yMax_Extent; /* xmax or ymax extents */ + TT_FWord caret_Slope_Rise; + TT_FWord caret_Slope_Run; + TT_FWord caret_Offset; + + TT_Short Reserved[4]; + + TT_Short metric_Data_Format; + TT_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_ + { + TT_UShort version; /* 0x0001 - more or 0xFFFF */ + TT_FWord xAvgCharWidth; + TT_UShort usWeightClass; + TT_UShort usWidthClass; + TT_Short fsType; + TT_FWord ySubscriptXSize; + TT_FWord ySubscriptYSize; + TT_FWord ySubscriptXOffset; + TT_FWord ySubscriptYOffset; + TT_FWord ySuperscriptXSize; + TT_FWord ySuperscriptYSize; + TT_FWord ySuperscriptXOffset; + TT_FWord ySuperscriptYOffset; + TT_FWord yStrikeoutSize; + TT_FWord yStrikeoutPosition; + TT_Short sFamilyClass; + + TT_Byte panose[10]; + + TT_ULong ulUnicodeRange1; /* Bits 0-31 */ + TT_ULong ulUnicodeRange2; /* Bits 32-63 */ + TT_ULong ulUnicodeRange3; /* Bits 64-95 */ + TT_ULong ulUnicodeRange4; /* Bits 96-127 */ + + TT_Char achVendID[4]; + + TT_UShort fsSelection; + TT_UShort usFirstCharIndex; + TT_UShort usLastCharIndex; + TT_Short sTypoAscender; + TT_Short sTypoDescender; + TT_Short sTypoLineGap; + TT_UShort usWinAscent; + TT_UShort usWinDescent; + + /* only version 1 tables: */ + + TT_ULong ulCodePageRange1; /* Bits 0-31 */ + TT_ULong ulCodePageRange2; /* Bits 32-63 */ + + } 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_ + { + TT_Fixed FormatType; + TT_Fixed italicAngle; + TT_FWord underlinePosition; + TT_FWord underlineThickness; + TT_ULong isFixedPitch; + TT_ULong minMemType42; + TT_ULong maxMemType42; + TT_ULong minMemType1; + TT_ULong maxMemType1; + + /* Glyph names follow in the file, but we don't */ + /* load them by default. See the ttpost.c file. */ + + } TT_Postscript; + + + /*************************************************************************/ + /* */ + /* */ + /* 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_ + { + TT_UShort tableVersionNumber; + TT_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_ + { + TT_UShort platformID; + TT_UShort platformEncodingID; + TT_Long offset; + + } TT_CMapDirEntry; + + + /*************************************************************************/ + /* */ + /* */ + /* 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_ + { + TT_Fixed version; + TT_UShort numGlyphs; + TT_UShort maxPoints; + TT_UShort maxContours; + TT_UShort maxCompositePoints; + TT_UShort maxCompositeContours; + TT_UShort maxZones; + TT_UShort maxTwilightPoints; + TT_UShort maxStorage; + TT_UShort maxFunctionDefs; + TT_UShort maxInstructionDefs; + TT_UShort maxStackElements; + TT_UShort maxSizeOfInstructions; + TT_UShort maxComponentElements; + TT_UShort maxComponentDepth; + + } TT_MaxProfile; + + + /*************************************************************************/ + /* */ + /* */ + /* 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_ + { + TT_UShort advance; + TT_Short bearing; + + } TT_LongMetrics; + + + /*************************************************************************/ + /* */ + /* TT_ShortMetrics */ + /* */ + /* */ + /* A simple type to model the short metrics of the `hmtx' and `vmtx' */ + /* tables. */ + /* */ + typedef TT_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_ + { + TT_UShort platformID; + TT_UShort encodingID; + TT_UShort languageID; + TT_UShort nameID; + TT_UShort stringLength; + TT_UShort stringOffset; + + /* this last field is not defined in the spec */ + /* but used by the FreeType engine */ + + TT_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_ + { + TT_UShort format; + TT_UShort numNameRecords; + TT_UShort storageOffset; + TT_NameRec* names; + TT_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_ + { + TT_UShort maxPPEM; + TT_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_ + { + TT_UShort version; + TT_UShort numRanges; + TT_GaspRange* gaspRanges; + + } TT_Gasp; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_HdmxRec */ + /* */ + /* */ + /* A small structure used to model the pre-computed widths of a given */ + /* size. They're 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_ + { + TT_Byte ppem; + TT_Byte max_width; + TT_Byte* widths; + + } TT_HdmxRec; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_HdmxRec */ + /* */ + /* */ + /* 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_ + { + TT_UShort version; + TT_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_ + { + TT_UShort left; /* index of left glyph in pair */ + TT_UShort right; /* index of right glyph in pair */ + TT_FWord value; /* kerning value */ + + } TT_Kern_0_Pair; + + + /*************************************************************************/ + /* */ + /* */ + /* 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_ + { + TT_Byte height; + TT_Byte width; + + TT_Char horiBearingX; + TT_Char horiBearingY; + TT_Byte horiAdvance; + + TT_Char vertBearingX; + TT_Char vertBearingY; + TT_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_ + { + TT_Byte height; + TT_Byte width; + + TT_Char bearingX; + TT_Char bearingY; + TT_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 */ + /* */ + typedef struct TT_SBit_Line_Metrics_ + { + TT_Char ascender; + TT_Char descender; + TT_Byte max_width; + TT_Char caret_slope_numerator; + TT_Char caret_slope_denominator; + TT_Char caret_offset; + TT_Char min_origin_SB; + TT_Char min_advance_SB; + TT_Char max_before_BL; + TT_Char min_after_BL; + TT_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 + { + TT_UShort first_glyph; + TT_UShort last_glyph; + + TT_UShort index_format; + TT_UShort image_format; + TT_ULong image_offset; + + TT_ULong image_size; + TT_SBit_Metrics metrics; + TT_ULong num_glyphs; + + TT_ULong* glyph_offsets; + TT_UShort* glyph_codes; + + TT_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_ + { + TT_Int num_ranges; + TT_SBit_Range* sbit_ranges; + TT_ULong ranges_offset; + + TT_ULong color_ref; + + TT_SBit_Line_Metrics hori; + TT_SBit_Line_Metrics vert; + + TT_UShort start_glyph; + TT_UShort end_glyph; + + TT_Byte x_ppem; + TT_Byte y_ppem; + + TT_Byte bit_depth; + TT_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_ + { + TT_UShort glyph_code; + + TT_Char x_offset; + TT_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; + + TT_Byte x_ppem; + TT_Byte y_ppem; + + TT_Byte x_ppem_substitute; + TT_Byte y_ppem_substitute; + + } TT_SBit_Scale; + + + /*************************************************************************/ + /* */ + /* */ + /* 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_ + { + TT_UShort num_glyphs; + TT_UShort num_names; + TT_UShort* glyph_indices; + TT_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_ + { + TT_UShort num_glyphs; + TT_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_ + { + TT_Bool loaded; + + union + { + TT_Post_20 format_20; + TT_Post_25 format_25; + + } names; + + } TT_Post_Names; + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*** ***/ + /*** ***/ + /*** 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 */ + /* `drivers/truetype/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; + + + /*************************************************************************/ + /* */ + /* 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. */ + /* */ + /* ttcHeader :: The TrueType collection header, used when the */ + /* file is a `ttc' rather than a `ttf'. For */ + /* ordinary font files, the field */ + /* `ttcHeader.DirCount' is set to 0. */ + /* */ + /* 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. */ + /* */ + /* 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. */ + /* */ + /* 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 :: 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. */ + /* */ + /* kern_pairs :: Array of kerning pairs, if any. Ignored for */ + /* Type 2 fonts. */ + /* */ + typedef struct TT_FaceRec_ + { + FT_FaceRec root; + + TTC_Header ttc_header; + + TT_UShort num_tables; + TT_TableDirEntry* dir_tables; + + TT_Header header; /* TrueType header table */ + TT_HoriHeader horizontal; /* TrueType horizontal header */ + + TT_MaxProfile max_profile; + TT_ULong max_components; + + TT_Bool vertical_info; + TT_VertHeader vertical; /* TT Vertical header, if present */ + + TT_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 */ + + TT_Int num_charmaps; + void* charmaps; /* array of TT_CharMapRec */ + + /***********************************************************************/ + /* */ + /* Optional TrueType/OpenType tables */ + /* */ + /***********************************************************************/ + + /* horizontal device metrics */ + TT_Hdmx hdmx; + + /* grid-fitting and scaling table */ + TT_Gasp gasp; /* the `gasp' table */ + + /* embedded bitmaps support */ + TT_Int num_sbit_strikes; + TT_SBit_Strike* sbit_strikes; + + TT_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 */ + TT_UShort num_locations; + TT_Long* glyph_locations; + + /* the font program, if any */ + TT_ULong font_program_size; + TT_Byte* font_program; + + /* the cvt program, if any */ + TT_ULong cvt_program_size; + TT_Byte* cvt_program; + + /* the original, unscaled, control value table */ + TT_ULong cvt_size; + TT_Short* cvt; + + /* the format 0 kerning table, if any */ + TT_Int num_kern_pairs; + TT_Int kern_table_index; + TT_Kern_0_Pair* kern_pairs; + + } TT_FaceRec; + + +#ifdef __cplusplus + } +#endif + + +#endif /* TTTYPES_H */ + + +/* END */ diff --git a/src/shared/t1types.h b/src/shared/t1types.h new file mode 100644 index 000000000..853b743c5 --- /dev/null +++ b/src/shared/t1types.h @@ -0,0 +1,485 @@ +/******************************************************************* + * + * t1types.h 1.0 + * + * Basic Type1/Type2 type definitions and interface. + * + * This code is shared by the Type1 and Type2 drivers + * + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.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 + + +#ifdef __cplusplus + extern "C" { +#endif + + + +/*************************************************************************/ +/*************************************************************************/ +/*************************************************************************/ +/*** ***/ +/*** ***/ +/*** DEFINITIONS OF BASIC DATA TYPES ***/ +/*** ***/ +/*** ***/ +/*************************************************************************/ +/*************************************************************************/ +/*************************************************************************/ + + +/* The REDEFINE macro is used to convert a FreeType generic type into */ +/* a TrueType-specific one. It simply replaces the "FT_" prefix by "T1_" */ +/* in order to define compatible T1_Long, T1_Error, T1_Outline, etc.. */ +/* */ +#undef REDEFINE +#define REDEFINE( type ) typedef FT_##type T1_##type + + + /* T1_Bool */ + /* */ + /* */ + /* A simple typedef of unsigned char, used for simple booleans. */ + /* */ + REDEFINE( Bool ); + + + /* T1_FWord */ + /* */ + /* */ + /* a signed 16-bit integer used to store a distance in original */ + /* font units. */ + /* */ + REDEFINE( FWord ); + + + /* T1_UFWord */ + /* */ + /* */ + /* an unsigned 16-bit integer used to store a distance in original */ + /* font units. */ + /* */ + REDEFINE( UFWord ); + + + /* T1_Char */ + /* */ + /* */ + /* a simple typedef for the _signed_ char type. */ + /* */ + REDEFINE( Char ); + + + /* T1_Byte */ + /* */ + /* */ + /* a simple typedef for the _unsigned_ char type. */ + /* */ + REDEFINE( Byte ); + + + /* T1_String */ + /* */ + /* */ + /* a simple typedef for the char type, used for strings usually. */ + /* */ + REDEFINE( String ); + + + /* T1_Short */ + /* */ + /* */ + /* a typedef for signed short */ + /* */ + REDEFINE( Short ); + + + /* T1_UShort */ + /* */ + /* */ + /* a typedef for unsigned short */ + /* */ + REDEFINE( UShort ); + + + /* FT_Int */ + /* */ + /* */ + /* a typedef for the int type */ + /* */ + REDEFINE( Int ); + + + /* FT_UInt */ + /* */ + /* */ + /* a typedef for the unsigned int type */ + /* */ + REDEFINE( UInt ); + + + /* T1_Long */ + /* */ + /* */ + /* a typedef for signed long */ + /* */ + REDEFINE( Long ); + + + /* T1_ULong */ + /* */ + /* */ + /* a typedef for unsigned long */ + /* */ + REDEFINE( ULong ); + + + /* T1_F2Dot14 */ + /* */ + /* */ + /* a signed 2.14 fixed float used for unit vectors */ + /* */ + REDEFINE( F2Dot14 ); + + + /* T1_F26Dot6 */ + /* */ + /* */ + /* a signed 26.6 fixed float used for vectorial pixel coordinates */ + /* */ + REDEFINE( F26Dot6 ); + + + /* T1_Fixed */ + /* */ + /* */ + /* This type is used to store 16.16 fixed float values, like */ + /* scales or matrix coefficients.. */ + /* */ + REDEFINE( Fixed ); + + + /* T1_Pos */ + /* */ + /* */ + /* The type T1_Pos is a 32-bits 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.. */ + /* */ + REDEFINE( Pos ); + + + /* T1_Vector */ + /* */ + /* */ + /* A simple structure used to store a 2d vector, coordinates */ + /* are of the T1_Pos type. */ + /* */ + /* */ + /* x :: horizontal coordinate */ + /* y :: vertical coordinate */ + /* */ + REDEFINE( Vector ); + + /* T1_UnitVector */ + /* */ + /* */ + /* A simple structure used to store a 2d vector unit vector. */ + /* uses T1_F2Dot14 types. */ + /* */ + /* */ + /* x :: horizontal coordinate */ + /* y :: vertical coordinate */ + /* */ + REDEFINE( UnitVector ); + + + /* T1_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 */ + /* */ + REDEFINE( Matrix ); + + + /* T1_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) */ + /* */ + REDEFINE( BBox ); + + + /* T1_Error */ + /* */ + /* */ + /* The FreeType error code type. A value of 0 is always */ + /* interpreted as a succesful operation. */ + /* */ + REDEFINE( Error ); + + + +/*************************************************************************/ +/*************************************************************************/ +/*************************************************************************/ +/*** ***/ +/*** ***/ +/*** REQUIRED TYPE1/TYPE2 TABLES DEFINITIONS ***/ +/*** ***/ +/*** ***/ +/*************************************************************************/ +/*************************************************************************/ +/*************************************************************************/ + + /***********************************************************************/ + /* */ + /* T1_FontInfo */ + /* */ + /* */ + /* The FontInfo dictionary structure. */ + /* */ + /* */ + /* version :: */ + /* notice :: */ + /* full_name :: */ + /* family_name :: */ + /* weight :: */ + /* italic_angle :: */ + /* is_fixed_pitch :: */ + /* underline_position :: */ + /* underline_thickness :: */ + /* */ + typedef struct T1_FontInfo_ + { + T1_String* version; + T1_String* notice; + T1_String* full_name; + T1_String* family_name; + T1_String* weight; + T1_Long italic_angle; + T1_Bool is_fixed_pitch; + T1_Short underline_position; + T1_UShort underline_thickness; + + } T1_FontInfo; + + + /***********************************************************************/ + /* */ + /* T1_Private */ + /* */ + /* */ + /* The Private dictionary structure. */ + /* */ + /* */ + /* unique_id :: the font's unique id */ + /* lenIV :: length of decrypt padding */ + /* */ + /* num_blues :: number of blue values */ + /* num_other_blues :: number of other blue values */ + /* num_family_blues :: number of family blue values */ + /* num_family_other_blues :: number of family other blue values */ + /* */ + /* blue_values :: array of blue values */ + /* other_blues :: array of other blue values */ + /* family_blues :: array of family blue values */ + /* family_other_blues :: array of family other blue values */ + /* */ + /* blue_scale :: */ + /* blue_shift :: */ + /* blue_scale :: */ + /* */ + /* standard_width :: */ + /* standard_height :: */ + /* */ + /* num_snap_widths :: */ + /* num_snap_heights :: */ + /* force_bold :: */ + /* round_stem_up :: */ + /* */ + /* stem_snap_widths :: */ + /* stem_snap_heights :: */ + /* */ + /* language_group :: */ + /* password :: */ + /* */ + /* min_feature :: */ + /* */ + /* */ + typedef struct T1_Private_ + { + T1_Int unique_id; + T1_Int lenIV; + + T1_Byte num_blues; + T1_Byte num_other_blues; + T1_Byte num_family_blues; + T1_Byte num_family_other_blues; + + T1_Short blue_values[14]; + T1_Short other_blues[10]; + + T1_Short family_blues [14]; + T1_Short family_other_blues[10]; + + T1_Fixed blue_scale; + T1_Int blue_shift; + T1_Int blue_fuzz; + + T1_UShort standard_width; + T1_UShort standard_height; + + T1_Byte num_snap_widths; + T1_Byte num_snap_heights; + T1_Bool force_bold; + T1_Bool round_stem_up; + + T1_Short stem_snap_widths [13]; /* reserve one place for the std */ + T1_Short stem_snap_heights[13]; /* reserve one place for the std */ + + T1_Long language_group; + T1_Long password; + + T1_Short min_feature[2]; + + } T1_Private; + + + + /***********************************************************************/ + /* */ + /* T1_Private */ + /* */ + /* */ + /* The Private dictionary structure. */ + /* */ + /* */ + /* num_chars :: number of char codes in encoding. Usually 256 */ + /* code_first :: lower char code in encoding */ + /* code_last :: higher char code in encoding */ + /* */ + /* char_code :: array of character codes */ + /* char_index :: array of correpsonding glyph indices */ + /* char_name :: array of correpsonding glyph names */ + /* */ + typedef struct T1_Encoding_ + { + T1_Int num_chars; + T1_Int code_first; + T1_Int code_last; + + T1_Short* char_index; + T1_String** char_name; + + } T1_Encoding; + + + +/*************************************************************************/ +/*************************************************************************/ +/*************************************************************************/ +/*** ***/ +/*** ***/ +/*** 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 "drivers/truetype/ttobjs.h" ***/ +/*** ***/ +/*** ***/ +/*************************************************************************/ +/*************************************************************************/ +/*************************************************************************/ + + + typedef struct T1_FaceRec_* T1_Face; + + + /***************************************************/ + /* */ + /* T1_Face : */ + /* */ + /* Type1 face record.. */ + /* */ + + typedef struct T1_FaceRec_ + { + FT_FaceRec root; + + T1_FontInfo font_info; + FT_String* font_name; + + T1_Encoding encoding; + + T1_Byte* subrs_block; + T1_Byte* charstrings_block; + + T1_Int num_subrs; + T1_Byte** subrs; + T1_Int* subrs_len; + + T1_Int num_glyphs; + T1_String** glyph_names; /* array of glyph names */ + T1_Byte** charstrings; /* array of glyph charstrings */ + T1_Int* charstrings_len; + + T1_Byte paint_type; + T1_Byte font_type; + T1_Matrix font_matrix; + T1_BBox font_bbox; + T1_Long unique_id; + T1_Long font_id; + + T1_Int stroke_width; + T1_Private private_dict; + + } T1_FaceRec; + + +#endif /* T1TYPES_H */ diff --git a/src/shared/tterrors.h b/src/shared/tterrors.h new file mode 100644 index 000000000..a8c6b5f93 --- /dev/null +++ b/src/shared/tterrors.h @@ -0,0 +1,126 @@ +/***************************************************************************/ +/* */ +/* tterrors.h */ +/* */ +/* TrueType error ID definitions (specification only). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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_Unavailable_Outline FT_Err_Unavailable_Outline +#define TT_Err_Unavailable_Bitmap FT_Err_Unavailable_Bitmap +#define TT_Err_Unavailable_Pixmap FT_Err_Unavailable_Pixmap +#define TT_Err_File_Is_Not_Collection FT_Err_File_Is_Not_Collection + +#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_Points FT_Err_Too_Many_Points +#define TT_Err_Too_Many_Contours FT_Err_Too_Many_Contours +#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 /* FTERRID_H */ + + +/* END */ diff --git a/src/shared/ttnameid.h b/src/shared/ttnameid.h new file mode 100644 index 000000000..98b19abc9 --- /dev/null +++ b/src/shared/ttnameid.h @@ -0,0 +1,603 @@ +/***************************************************************************/ +/* */ +/* ttnameid.h */ +/* */ +/* TrueType name ID definitions (specification only). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 +#error "Don't include this file! Use freetype.h instead." +#endif + + +#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 +#define TT_PLATFORM_MICROSOFT 3 + + + /*************************************************************************/ + /* */ + /* Possible values of the platform specific encoding identifier field in */ + /* the name records of the TTF `name' table when the `Platform' */ + /* identifier code is TT_PLATFORM_APPLE_UNICODE. */ + /* */ +#define TT_APPLE_ID_DEFAULT 0 +#define TT_APPLE_ID_UNICODE_1_1 1 +#define TT_APPLE_ID_ISO_10646 2 +#define TT_APPLE_ID_UNICODE_2_0 3 + + + /*************************************************************************/ + /* */ + /* Possible values of the platform specific encoding identifier field in */ + /* the name records of the TTF `name' table when 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 when the `Platform' */ + /* identifier code is TT_PLATFORM_ISO. */ + /* */ +#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 when 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 when 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_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_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 +#define TT_MAC_LANGID_SCOTTISH_GAELIC 140 +#define TT_MAC_LANGID_IRISH_GAELIC 141 +#define TT_MAC_LANGID_BRETON 142 +#define TT_MAC_LANGID_INUKTITUT 143 + + + /*************************************************************************/ + /* */ + /* Possible values of the language identifier field in the name records */ + /* of the TTF `name' table when 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 + + + /*************************************************************************/ + /* */ + /* Bit mask values for the Unicode ranges from the TTF `OS2 ' table. */ + /* */ + /*************************************************************************/ + + +/* General Scripts Area */ + +/* Bit 0 C0 Controls and Basic Latin */ +#define TT_UCR_BASIC_LATIN (1 << 0) /* U+0000-U+007F */ +/* Bit 1 C1 Controls and Latin-1 Supplement */ +#define TT_UCR_LATIN1_SUPPLEMENT (1 << 1) /* U+0080-U+00FF */ +/* Bit 2 Latin Extended-A */ +#define TT_UCR_LATIN_EXTENDED_A (1 << 2) /* U+0100-U+017F */ +/* Bit 3 Latin Extended-B */ +#define TT_UCR_LATIN_EXTENDED_B (1 << 3) /* U+0180-U+024F */ +/* Bit 4 IPA Extensions */ +#define TT_UCR_IPA_EXTENSIONS (1 << 4) /* U+0250-U+02AF */ +/* Bit 5 Spacing Modifier Letters */ +#define TT_UCR_SPACING_MODIFIER (1 << 5) /* U+02B0-U+02FF */ +/* Bit 6 Combining Diacritical Marks */ +#define TT_UCR_COMBINING_DIACRITICAL_MARKS (1 << 6) /* U+0300-U+036F */ +/* Bit 7 Greek */ +#define TT_UCR_GREEK (1 << 7) /* U+0370-U+03FF */ +/* Bit 8 is reserved (was: Greek Symbols and Coptic) */ +/* Bit 9 Cyrillic */ +#define TT_UCR_CYRILLIC (1 << 9) /* U+0400-U+04FF */ +/* Bit 10 Armenian */ +#define TT_UCR_ARMENIAN (1 << 10) /* U+0530-U+058F */ +/* Bit 11 Hebrew */ +#define TT_UCR_HEBREW (1 << 11) /* U+0590-U+05FF */ +/* Bit 12 is reserved (was: Hebrew Extended) */ +/* Bit 13 Arabic */ +#define TT_UCR_ARABIC (1 << 13) /* U+0600-U+06FF */ +/* Bit 14 is reserved (was: Arabic Extended) */ +/* Bit 15 Devanagari */ +#define TT_UCR_DEVANAGARI (1 << 15) /* U+0900-U+097F */ +/* Bit 16 Bengali */ +#define TT_UCR_BENGALI (1 << 16) /* U+0980-U+09FF */ +/* Bit 17 Gurmukhi */ +#define TT_UCR_GURMUKHI (1 << 17) /* U+0A00-U+0A7F */ +/* Bit 18 Gujarati */ +#define TT_UCR_GUJARATI (1 << 18) /* U+0A80-U+0AFF */ +/* Bit 19 Oriya */ +#define TT_UCR_ORIYA (1 << 19) /* U+0B00-U+0B7F */ +/* Bit 20 Tamil */ +#define TT_UCR_TAMIL (1 << 20) /* U+0B80-U+0BFF */ +/* Bit 21 Telugu */ +#define TT_UCR_TELUGU (1 << 21) /* U+0C00-U+0C7F */ +/* Bit 22 Kannada */ +#define TT_UCR_KANNADA (1 << 22) /* U+0C80-U+0CFF */ +/* Bit 23 Malayalam */ +#define TT_UCR_MALAYALAM (1 << 23) /* U+0D00-U+0D7F */ +/* Bit 24 Thai */ +#define TT_UCR_THAI (1 << 24) /* U+0E00-U+0E7F */ +/* Bit 25 Lao */ +#define TT_UCR_LAO (1 << 25) /* U+0E80-U+0EFF */ +/* Bit 26 Georgian */ +#define TT_UCR_GEORGIAN (1 << 26) /* U+10A0-U+10FF */ +/* Bit 27 is reserved (was Georgian Extended) */ +/* Bit 28 Hangul Jamo */ +#define TT_UCR_HANGUL_JAMO (1 << 28) /* U+1100-U+11FF */ +/* Bit 29 Latin Extended Additional */ +#define TT_UCR_LATIN_EXTENDED_ADDITIONAL (1 << 29) /* U+1E00-U+1EFF */ +/* Bit 30 Greek Extended */ +#define TT_UCR_GREEK_EXTENDED (1 << 30) /* U+1F00-U+1FFF */ + +/* Symbols Area */ + +/* Bit 31 General Punctuation */ +#define TT_UCR_GENERAL_PUNCTUATION (1 << 31) /* U+2000-U+206F */ +/* Bit 32 Superscripts And Subscripts */ +#define TT_UCR_SUPERSCRIPTS_SUBSCRIPTS (1 << 0) /* U+2070-U+209F */ +/* Bit 33 Currency Symbols */ +#define TT_UCR_CURRENCY_SYMBOLS (1 << 1) /* U+20A0-U+20CF */ +/* Bit 34 Combining Diacritical Marks For Symbols */ +#define TT_UCR_COMBINING_DIACRITICAL_MARKS_SYMB (1 << 2) /* U+20D0-U+20FF */ +/* Bit 35 Letterlike Symbols */ +#define TT_UCR_LETTERLIKE_SYMBOLS (1 << 3) /* U+2100-U+214F */ +/* Bit 36 Number Forms */ +#define TT_UCR_NUMBER_FORMS (1 << 4) /* U+2150-U+218F */ +/* Bit 37 Arrows */ +#define TT_UCR_ARROWS (1 << 5) /* U+2190-U+21FF */ +/* Bit 38 Mathematical Operators */ +#define TT_UCR_MATHEMATICAL_OPERATORS (1 << 6) /* U+2200-U+22FF */ +/* Bit 39 Miscellaneous Technical */ +#define TT_UCR_MISCELLANEOUS_TECHNICAL (1 << 7) /* U+2300-U+23FF */ +/* Bit 40 Control Pictures */ +#define TT_UCR_CONTROL_PICTURES (1 << 8) /* U+2400-U+243F */ +/* Bit 41 Optical Character Recognition */ +#define TT_UCR_OCR (1 << 9) /* U+2440-U+245F */ +/* Bit 42 Enclosed Alphanumerics */ +#define TT_UCR_ENCLOSED_ALPHANUMERICS (1 << 10) /* U+2460-U+24FF */ +/* Bit 43 Box Drawing */ +#define TT_UCR_BOX_DRAWING (1 << 11) /* U+2500-U+257F */ +/* Bit 44 Block Elements */ +#define TT_UCR_BLOCK_ELEMENTS (1 << 12) /* U+2580-U+259F */ +/* Bit 45 Geometric Shapes */ +#define TT_UCR_GEOMETRIC_SHAPES (1 << 13) /* U+25A0-U+25FF */ +/* Bit 46 Miscellaneous Symbols */ +#define TT_UCR_MISCELLANEOUS_SYMBOLS (1 << 14) /* U+2600-U+26FF */ +/* Bit 47 Dingbats */ +#define TT_UCR_DINGBATS (1 << 15) /* U+2700-U+27BF */ + +/* CJK Phonetics and Symbols Area */ + +/* Bit 48 CJK Symbols And Punctuation */ +#define TT_UCR_CJK_SYMBOLS (1 << 16) /* U+3000-U+303F */ +/* Bit 49 Hiragana */ +#define TT_UCR_HIRAGANA (1 << 17) /* U+3040-U+309F */ +/* Bit 50 Katakana */ +#define TT_UCR_KATAKANA (1 << 18) /* U+30A0-U+30FF */ +/* Bit 51 Bopomofo */ +#define TT_UCR_BOPOMOFO (1 << 19) /* U+3100-U+312F */ +/* Bit 52 Hangul Compatibility Jamo */ +#define TT_UCR_HANGUL_COMPATIBILITY_JAMO (1 << 20) /* U+3130-U+318F */ +/* Bit 53 CJK Miscellaneous */ +#define TT_UCR_CJK_MISC (1 << 21) /* U+3190-U+319F */ +/* Bit 54 Enclosed CJK Letters And Months */ +#define TT_UCR_ENCLOSED_CJK_LETTERS_MONTHS (1 << 22) /* U+3200-U+32FF */ +/* Bit 55 CJK Compatibility */ +#define TT_UCR_CJK_COMPATIBILITY (1 << 23) /* U+3300-U+33FF */ + +/* Hangul Syllables Area */ + +/* Bit 56 Hangul */ +#define TT_UCR_HANGUL (1 << 24) /* U+AC00-U+D7A3 */ + +/* Surrogates Area */ + +/* Bit 57 Surrogates */ +#define TT_UCR_SURROGATES (1 << 25) /* U+D800-U+DFFF */ +/* Bit 58 is reserved for Unicode SubRanges */ + +/* CJK Ideographs Area */ + +/* Bit 59 CJK Unified Ideographs */ +#define TT_UCR_CJK_UNIFIED_IDEOGRAPHS (1 << 27) /* U+4E00-U+9FFF */ + +/* Private Use Area */ + +/* Bit 60 Private Use */ +#define TT_UCR_PRIVATE_USE (1 << 28) /* U+E000-U+F8FF */ + +/* Compatibility Area and Specials */ + +/* Bit 61 CJK Compatibility Ideographs */ +#define TT_UCR_CJK_COMPATIBILITY_IDEOGRAPHS (1 << 29) /* U+F900-U+FAFF */ +/* Bit 62 Alphabetic Presentation Forms */ +#define TT_UCR_ALPHABETIC_PRESENTATION_FORMS (1 << 30) /* U+FB00-U+FB4F */ +/* Bit 63 Arabic Presentation Forms-A */ +#define TT_UCR_ARABIC_PRESENTATION_FORMS_A (1 << 31) /* U+FB50-U+FSFF */ +/* Bit 64 Combining Half Marks */ +#define TT_UCR_COMBINING_HALF_MARKS (1 << 0) /* U+FE20-U+FE2F */ +/* Bit 65 CJK Compatibility Forms */ +#define TT_UCR_CJK_COMPATIBILITY_FORMS (1 << 1) /* U+FE30-U+FE4F */ +/* Bit 66 Small Form Variants */ +#define TT_UCR_SMALL_FORM_VARIANTS (1 << 2) /* U+FE50-U+FE6F */ +/* Bit 67 Arabic Presentation Forms-B */ +#define TT_UCR_ARABIC_PRESENTATION_FORMS_B (1 << 3) /* U+FE70-U+FEFF */ +/* Bit 68 Halfwidth And Fullwidth Forms */ +#define TT_UCR_HALFWIDTH_FULLWIDTH_FORMS (1 << 4) /* U+FF00-U+FFEF */ +/* Bit 69 Specials */ +#define TT_UCR_SPECIALS (1 << 5) /* U+FEFF, + U+FFF0-U+FFFF */ +/* Bit 70 Tibetan */ +#define TT_UCR_TIBETAN (1 << 6) /* U+0F00-U+0FBF */ + + +#endif /* TTNAMEID_H */ + + +/* END */ diff --git a/src/shared/tttags.h b/src/shared/tttags.h new file mode 100644 index 000000000..73bbfc0ef --- /dev/null +++ b/src/shared/tttags.h @@ -0,0 +1,60 @@ +/***************************************************************************/ +/* */ +/* tttags.h */ +/* */ +/* Tags for TrueType tables (specification only). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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_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_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_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/src/shared/tttypes.h b/src/shared/tttypes.h new file mode 100644 index 000000000..a5140e9be --- /dev/null +++ b/src/shared/tttypes.h @@ -0,0 +1,2066 @@ +/***************************************************************************/ +/* */ +/* tttypes.h */ +/* */ +/* Basic SFNT/TrueType type definitions and interface (specification */ +/* only). */ +/* */ +/* This code is shared by all TrueType and OpenType drivers. */ +/* */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 + + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*** ***/ + /*** ***/ + /*** DEFINITIONS OF BASIC DATA TYPES ***/ + /*** ***/ + /*** ***/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* The REDEFINE() macro is used to convert a FreeType generic type into */ + /* a TrueType-specific one. It simply replaces the `FT_' prefix by */ + /* `TT_' in order to define compatible types like TT_Long, TT_Error, */ + /* TT_Outline, etc. */ + /* */ +#undef REDEFINE +#define REDEFINE( type ) typedef FT_##type TT_##type + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Bool */ + /* */ + /* */ + /* A typedef of unsigned char, used for simple booleans. */ + /* */ + REDEFINE( Bool ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_FWord */ + /* */ + /* */ + /* A signed 16-bit integer used to store a distance in original font */ + /* units. */ + /* */ + REDEFINE( FWord ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_UFWord */ + /* */ + /* */ + /* An unsigned 16-bit integer used to store a distance in original */ + /* font units. */ + /* */ + REDEFINE( UFWord ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Char */ + /* */ + /* */ + /* A simple typedef for the _signed_ char type. */ + /* */ + REDEFINE( Char ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Byte */ + /* */ + /* */ + /* A simple typedef for the _unsigned_ char type. */ + /* */ + REDEFINE( Byte ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_String */ + /* */ + /* */ + /* A simple typedef for the char type, usually used for strings. */ + /* */ + REDEFINE( String ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Short */ + /* */ + /* */ + /* A typedef for signed short. */ + /* */ + REDEFINE( Short ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_UShort */ + /* */ + /* */ + /* A typedef for unsigned short. */ + /* */ + REDEFINE( UShort ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Int */ + /* */ + /* */ + /* A typedef for the int type. */ + /* */ + REDEFINE( Int ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_UInt */ + /* */ + /* */ + /* A typedef for the unsigned int type. */ + /* */ + REDEFINE( UInt ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Long */ + /* */ + /* */ + /* A typedef for signed long. */ + /* */ + REDEFINE( Long ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_ULong */ + /* */ + /* */ + /* A typedef for unsigned long. */ + /* */ + REDEFINE( ULong ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_F2Dot14 */ + /* */ + /* */ + /* A signed 2.14 fixed float type used for unit vectors. */ + /* */ + REDEFINE( F2Dot14 ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_F26Dot6 */ + /* */ + /* */ + /* A signed 26.6 fixed float type used for vectorial pixel */ + /* coordinates. */ + /* */ + REDEFINE( F26Dot6 ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Fixed */ + /* */ + /* */ + /* This type is used to store 16.16 fixed float values, like scales */ + /* or matrix coefficients. */ + /* */ + REDEFINE( Fixed ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_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. */ + /* */ + REDEFINE( Pos ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Vector */ + /* */ + /* */ + /* A simple structure used to store a 2d vector; coordinates are of */ + /* the TT_Pos type. */ + /* */ + /* */ + /* x :: The horizontal coordinate. */ + /* y :: The vertical coordinate. */ + /* */ + REDEFINE( Vector ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_UnitVector */ + /* */ + /* */ + /* A simple structure used to store a 2d vector unit vector. Uses */ + /* TT_F2Dot14 types. */ + /* */ + /* */ + /* x :: Horizontal coordinate. */ + /* y :: Vertical coordinate. */ + /* */ + REDEFINE( UnitVector ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_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. */ + /* */ + REDEFINE( Matrix ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_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). */ + /* */ + REDEFINE( BBox ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Error */ + /* */ + /* */ + /* The TrueType error code type. A value of 0 is always interpreted */ + /* as a successful operation. */ + /* */ + REDEFINE( Error ); + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*** ***/ + /*** ***/ + /*** 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_ + { + TT_ULong Tag; + TT_Fixed version; + TT_Long DirCount; + TT_ULong* TableDirectory; + + } TTC_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_ + { + TT_Fixed version; /* should be 0x10000 */ + TT_UShort numTables; /* number of tables */ + + TT_UShort searchRange; /* These parameters are only used */ + TT_UShort entrySelector; /* for a dichotomy search in the */ + TT_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_ + { + TT_ULong Tag; /* table type */ + TT_ULong CheckSum; /* table checksum */ + TT_ULong Offset; /* table file offset */ + TT_ULong Length; /* table length */ + + } TT_Table; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Header */ + /* */ + /* */ + /* A structure used to model a TrueType font header table. All */ + /* fields follow the TrueType specification. */ + /* */ + typedef struct TT_Header_ + { + TT_Fixed Table_Version; + TT_Fixed Font_Revision; + + TT_Long CheckSum_Adjust; + TT_Long Magic_Number; + + TT_UShort Flags; + TT_UShort Units_Per_EM; + + TT_Long Created [2]; + TT_Long Modified[2]; + + TT_FWord xMin; + TT_FWord yMin; + TT_FWord xMax; + TT_FWord yMax; + + TT_UShort Mac_Style; + TT_UShort Lowest_Rec_PPEM; + + TT_Short Font_Direction; + TT_Short Index_To_Loc_Format; + TT_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_ + { + TT_Fixed Version; + TT_FWord Ascender; + TT_FWord Descender; + TT_FWord Line_Gap; + + TT_UFWord advance_Width_Max; /* advance width maximum */ + + TT_FWord min_Left_Side_Bearing; /* minimum left-sb */ + TT_FWord min_Right_Side_Bearing; /* minimum right-sb */ + TT_FWord xMax_Extent; /* xmax extents */ + TT_FWord caret_Slope_Rise; + TT_FWord caret_Slope_Run; + TT_FWord caret_Offset; + + TT_Short Reserved[4]; + + TT_Short metric_Data_Format; + TT_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_ + { + TT_Fixed Version; + TT_FWord Ascender; + TT_FWord Descender; + TT_FWord Line_Gap; + + TT_UFWord advance_Height_Max; /* advance height maximum */ + + TT_FWord min_Top_Side_Bearing; /* minimum left-sb or top-sb */ + TT_FWord min_Bottom_Side_Bearing; /* minimum right-sb or bottom-sb */ + TT_FWord yMax_Extent; /* xmax or ymax extents */ + TT_FWord caret_Slope_Rise; + TT_FWord caret_Slope_Run; + TT_FWord caret_Offset; + + TT_Short Reserved[4]; + + TT_Short metric_Data_Format; + TT_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_ + { + TT_UShort version; /* 0x0001 - more or 0xFFFF */ + TT_FWord xAvgCharWidth; + TT_UShort usWeightClass; + TT_UShort usWidthClass; + TT_Short fsType; + TT_FWord ySubscriptXSize; + TT_FWord ySubscriptYSize; + TT_FWord ySubscriptXOffset; + TT_FWord ySubscriptYOffset; + TT_FWord ySuperscriptXSize; + TT_FWord ySuperscriptYSize; + TT_FWord ySuperscriptXOffset; + TT_FWord ySuperscriptYOffset; + TT_FWord yStrikeoutSize; + TT_FWord yStrikeoutPosition; + TT_Short sFamilyClass; + + TT_Byte panose[10]; + + TT_ULong ulUnicodeRange1; /* Bits 0-31 */ + TT_ULong ulUnicodeRange2; /* Bits 32-63 */ + TT_ULong ulUnicodeRange3; /* Bits 64-95 */ + TT_ULong ulUnicodeRange4; /* Bits 96-127 */ + + TT_Char achVendID[4]; + + TT_UShort fsSelection; + TT_UShort usFirstCharIndex; + TT_UShort usLastCharIndex; + TT_Short sTypoAscender; + TT_Short sTypoDescender; + TT_Short sTypoLineGap; + TT_UShort usWinAscent; + TT_UShort usWinDescent; + + /* only version 1 tables: */ + + TT_ULong ulCodePageRange1; /* Bits 0-31 */ + TT_ULong ulCodePageRange2; /* Bits 32-63 */ + + } 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_ + { + TT_Fixed FormatType; + TT_Fixed italicAngle; + TT_FWord underlinePosition; + TT_FWord underlineThickness; + TT_ULong isFixedPitch; + TT_ULong minMemType42; + TT_ULong maxMemType42; + TT_ULong minMemType1; + TT_ULong maxMemType1; + + /* Glyph names follow in the file, but we don't */ + /* load them by default. See the ttpost.c file. */ + + } TT_Postscript; + + + /*************************************************************************/ + /* */ + /* */ + /* 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_ + { + TT_UShort tableVersionNumber; + TT_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_ + { + TT_UShort platformID; + TT_UShort platformEncodingID; + TT_Long offset; + + } TT_CMapDirEntry; + + + /*************************************************************************/ + /* */ + /* */ + /* 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_ + { + TT_Fixed version; + TT_UShort numGlyphs; + TT_UShort maxPoints; + TT_UShort maxContours; + TT_UShort maxCompositePoints; + TT_UShort maxCompositeContours; + TT_UShort maxZones; + TT_UShort maxTwilightPoints; + TT_UShort maxStorage; + TT_UShort maxFunctionDefs; + TT_UShort maxInstructionDefs; + TT_UShort maxStackElements; + TT_UShort maxSizeOfInstructions; + TT_UShort maxComponentElements; + TT_UShort maxComponentDepth; + + } TT_MaxProfile; + + + /*************************************************************************/ + /* */ + /* */ + /* 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_ + { + TT_UShort advance; + TT_Short bearing; + + } TT_LongMetrics; + + + /*************************************************************************/ + /* */ + /* TT_ShortMetrics */ + /* */ + /* */ + /* A simple type to model the short metrics of the `hmtx' and `vmtx' */ + /* tables. */ + /* */ + typedef TT_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_ + { + TT_UShort platformID; + TT_UShort encodingID; + TT_UShort languageID; + TT_UShort nameID; + TT_UShort stringLength; + TT_UShort stringOffset; + + /* this last field is not defined in the spec */ + /* but used by the FreeType engine */ + + TT_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_ + { + TT_UShort format; + TT_UShort numNameRecords; + TT_UShort storageOffset; + TT_NameRec* names; + TT_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_ + { + TT_UShort maxPPEM; + TT_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_ + { + TT_UShort version; + TT_UShort numRanges; + TT_GaspRange* gaspRanges; + + } TT_Gasp; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_HdmxRec */ + /* */ + /* */ + /* A small structure used to model the pre-computed widths of a given */ + /* size. They're 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_ + { + TT_Byte ppem; + TT_Byte max_width; + TT_Byte* widths; + + } TT_HdmxRec; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_HdmxRec */ + /* */ + /* */ + /* 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_ + { + TT_UShort version; + TT_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_ + { + TT_UShort left; /* index of left glyph in pair */ + TT_UShort right; /* index of right glyph in pair */ + TT_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_ + { + TT_Byte height; + TT_Byte width; + + TT_Char horiBearingX; + TT_Char horiBearingY; + TT_Byte horiAdvance; + + TT_Char vertBearingX; + TT_Char vertBearingY; + TT_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_ + { + TT_Byte height; + TT_Byte width; + + TT_Char bearingX; + TT_Char bearingY; + TT_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 */ + /* */ + typedef struct TT_SBit_Line_Metrics_ + { + TT_Char ascender; + TT_Char descender; + TT_Byte max_width; + TT_Char caret_slope_numerator; + TT_Char caret_slope_denominator; + TT_Char caret_offset; + TT_Char min_origin_SB; + TT_Char min_advance_SB; + TT_Char max_before_BL; + TT_Char min_after_BL; + TT_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 + { + TT_UShort first_glyph; + TT_UShort last_glyph; + + TT_UShort index_format; + TT_UShort image_format; + TT_ULong image_offset; + + TT_ULong image_size; + TT_SBit_Metrics metrics; + TT_ULong num_glyphs; + + TT_ULong* glyph_offsets; + TT_UShort* glyph_codes; + + TT_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_ + { + TT_Int num_ranges; + TT_SBit_Range* sbit_ranges; + TT_ULong ranges_offset; + + TT_ULong color_ref; + + TT_SBit_Line_Metrics hori; + TT_SBit_Line_Metrics vert; + + TT_UShort start_glyph; + TT_UShort end_glyph; + + TT_Byte x_ppem; + TT_Byte y_ppem; + + TT_Byte bit_depth; + TT_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_ + { + TT_UShort glyph_code; + + TT_Char x_offset; + TT_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; + + TT_Byte x_ppem; + TT_Byte y_ppem; + + TT_Byte x_ppem_substitute; + TT_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_ + { + TT_UShort num_glyphs; + TT_UShort num_names; + TT_UShort* glyph_indices; + TT_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_ + { + TT_UShort num_glyphs; + TT_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_ + { + TT_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_ + { + TT_Byte* glyphIdArray; + + } TT_CMap0; + + + /* format 2 */ + typedef struct TT_CMap2SubHeader_ + { + TT_UShort firstCode; /* first valid low byte */ + TT_UShort entryCount; /* number of valid low bytes */ + TT_Short idDelta; /* delta value to glyphIndex */ + TT_UShort idRangeOffset; /* offset from here to 1st code */ + + } TT_CMap2SubHeader; + + + typedef struct TT_CMap2_ + { + TT_UShort* subHeaderKeys; + /* high byte mapping table */ + /* value = subHeader index * 8 */ + + TT_CMap2SubHeader* subHeaders; + TT_UShort* glyphIdArray; + TT_UShort numGlyphId; /* control value */ + + } TT_CMap2; + + + /* format 4 */ + typedef struct TT_CMap4Segment_ + { + TT_UShort endCount; + TT_UShort startCount; + TT_Short idDelta; + TT_UShort idRangeOffset; + + } TT_CMap4Segment; + + + typedef struct TT_CMap4_ + { + TT_UShort segCountX2; /* number of segments * 2 */ + TT_UShort searchRange; /* these parameters can be used */ + TT_UShort entrySelector; /* for a binary search */ + TT_UShort rangeShift; + + TT_CMap4Segment* segments; + TT_UShort* glyphIdArray; + TT_UShort numGlyphId; /* control value */ + + } TT_CMap4; + + + /* format 6 */ + typedef struct TT_CMap6_ + { + TT_UShort firstCode; /* first character code of subrange */ + TT_UShort entryCount; /* number of character codes in subrange */ + + TT_UShort* glyphIdArray; + + } TT_CMap6; + + typedef struct TT_CMapTable_ TT_CMapTable; + + typedef + TT_UInt (*TT_CharMap_Func)( TT_CMapTable* charmap, + TT_ULong char_code ); + + /* charmap table */ + struct TT_CMapTable_ + { + TT_UShort platformID; + TT_UShort platformEncodingID; + TT_UShort format; + TT_UShort length; + TT_UShort version; + + TT_Bool loaded; + TT_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 */ + /* `drivers/truetype/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 TT_Error (*TT_Interpreter)( void* exec_context ); + + + /*************************************************************************/ + /* */ + /* */ + /* 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 :: length of table in bytes. Set to 0 when not needed */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + /* */ + /* The stream cursor must be at the font file's origin */ + /* */ + typedef + TT_Error (*TT_Goto_Table_Func)( TT_Face face, + TT_ULong tag, + FT_Stream stream, + TT_ULong *length ); + + /*************************************************************************/ + /* */ + /* 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. */ + /* */ + /* ttcHeader :: The TrueType collection header, used when the */ + /* file is a `ttc' rather than a `ttf'. For */ + /* ordinary font files, the field */ + /* `ttcHeader.DirCount' is set to 0. */ + /* */ + /* 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_face :: 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) */ + /* */ + /* sfnt :: a pointer to the SFNT `driver' 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. */ + /* */ + /* 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 :: 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. */ + /* */ + /* kern_pairs :: Array of kerning pairs, if any. Ignored for */ + /* Type 2 fonts. */ + /* */ + /* interpreter :: Pointer to the TrueType bytecode interpreter */ + /* this field is also used to hook the debugger */ + /* in `ttdebug' */ + /* */ + typedef struct TT_FaceRec_ + { + FT_FaceRec root; + + TTC_Header ttc_header; + + TT_UShort num_tables; + TT_Table* dir_tables; + + TT_Header header; /* TrueType header table */ + TT_HoriHeader horizontal; /* TrueType horizontal header */ + + TT_MaxProfile max_profile; + TT_ULong max_components; + + TT_Bool vertical_info; + TT_VertHeader vertical; /* TT Vertical header, if present */ + + TT_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 */ + + TT_Int num_charmaps; + TT_CharMap charmaps; /* array of TT_CharMapRec */ + + /* a pointer to the function used to seek a stream to the start of */ + /* a given TrueType table. This should default to the function */ + /* TT_Goto_Table defined in `ttload.h', but some font drivers */ + /* might need something different, e.g. Type 42 fonts */ + TT_Goto_Table_Func goto_table; + + /* a typeless pointer to the SFNT_Interface table used to load */ + /* the basic TrueType tables in the face object */ + void* sfnt; + + /***********************************************************************/ + /* */ + /* Optional TrueType/OpenType tables */ + /* */ + /***********************************************************************/ + + /* horizontal device metrics */ + TT_Hdmx hdmx; + + /* grid-fitting and scaling table */ + TT_Gasp gasp; /* the `gasp' table */ + + /* embedded bitmaps support */ + TT_Int num_sbit_strikes; + TT_SBit_Strike* sbit_strikes; + + TT_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 */ + TT_UShort num_locations; + TT_Long* glyph_locations; + + /* the font program, if any */ + TT_ULong font_program_size; + TT_Byte* font_program; + + /* the cvt program, if any */ + TT_ULong cvt_program_size; + TT_Byte* cvt_program; + + /* the original, unscaled, control value table */ + TT_ULong cvt_size; + TT_Short* cvt; + + /* the format 0 kerning table, if any */ + TT_Int num_kern_pairs; + TT_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; + + } TT_FaceRec; + + +#ifdef __cplusplus + } +#endif + + +#endif /* TTTYPES_H */ + + +/* END */ diff --git a/src/shared/type1/rules.mk b/src/shared/type1/rules.mk new file mode 100644 index 000000000..d9c950efd --- /dev/null +++ b/src/shared/type1/rules.mk @@ -0,0 +1,54 @@ +#**************************************************************************** +#* * +#* Shared/Type1 Makefile * +#* * +#* Copyright 1996-1999 by * +#* David Turner, Robert Wilhelm, and Werner Lemberg. * +#* * +#* This file is part of the FreeType project, and may only be used * +#* modified and distributed under the terms of the FreeType project * +#* license, LICENSE.TXT. By continuing to use, modify, or distribute * +#* this file you indicate that you have read the license and * +#* understand and accept it fully. * +#* * +#**************************************************************************** + + +#**************************************************************************** +#* * +#* IMPORTANT NOTE: This Makefile is intended for GNU Make! * +#* If you provide Makefiles for other make utilities, * +#* please place them in `freetype/lib/arch/'. * +#* * +#* * +#* This file is to be included by the Makefiles of each driver that uses * +#* the shared source code in `freetype2/lib/drivers/type1'. This code * +#* contains type definitions as well as interface which are common to all * +#* supported Postscript font formats (i.e. Type1 and Type2). * +#* * +#* * +#* The purpose of this Makefile is to define make variables that are used * +#* directly by the parent Makefile. * +#* * +#**************************************************************************** + + +# T1SHARED_DIR is the directory to the `shared/type1' sources +# +T1SHARED_DIR := $(SRC)/shared/type1 +T1SHARED_DIR_ := $(T1SHARED_DIR)$(SEP) + + +# T1SHARED_H is the list of all header files on which the client drivers +# depend +# +T1SHARED_H := $(T1SHARED_DIR_)t1types.h \ + $(T1SHARED_DIR_)t1encode.h + +# T1SHARED_SRC is the list of all shared source files that are included +# by any client driver +# +T1SHARED_SRC := $(T1SHARED_DIR_)t1encode.c + + +# END diff --git a/src/shared/type1/t1encode.c b/src/shared/type1/t1encode.c new file mode 100644 index 000000000..a1bf73d72 --- /dev/null +++ b/src/shared/type1/t1encode.c @@ -0,0 +1,330 @@ +/***************************************************************************/ +/* */ +/* t1encode.c */ +/* */ +/* Type 1 standard encoding tables definitions (body). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 included by both the Type1 and Type2 driver. */ +/* It should never be compiled directly. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* t1_standard_strings: */ + /* */ + /* This array contains the Adobe Standard Glyph Names ordered by */ + /* SID. It was taken from the CFF specification. */ + /* */ + LOCAL_FUNC + const T1_String* 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", + "height", "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", "quillemotleft", "guilsinglleft", "guilsinglright", "fi", + /* 110 */ + "fl", "endash", "dagger", "daggerdbl", "periodcenter", + "paragraph", "bullet", "quotesinglbase", "quotedblbase", "quotedblright", + /* 120 */ + "quillemotright", "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", + "regitered", "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: */ + /* */ + /* A simple table used to encode the Adobe StandardEncoding. The */ + /* table values are the SID of the standard glyphs; the table index */ + /* is the character code for the encoding. */ + /* */ + /* Example: */ + /* */ + /* t1_standard_encoding[33] == 2 */ + /* */ + /* which means that the glyph name for character code 32 is */ + /* */ + /* t1_standard_strings[2] == "exclam" */ + /* */ + /* (this correspond to the exclamation mark `!'). */ + /* */ + LOCAL_FUNC + T1_Short t1_standard_encoding[256] = + { + /* 0 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, + /* 50 */ + 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, + /* 100 */ + 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, + /* 150 */ + 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, + /* 200 */ + 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, + /* 250 */ + 148, 149, 0, 0, 0, 0 + }; + + + /*************************************************************************/ + /* */ + /* t1_expert_encoding: */ + /* */ + /* A simple table used to encode the Adobe ExpertEncoding. The */ + /* table values are the SID of the standard glyphs; the table index */ + /* is the character code for the encoding. */ + /* */ + /* Example: */ + /* */ + /* t1_expert_encoding[33] == 229 */ + /* */ + /* which means that the glyph name for character code 32 is */ + /* */ + /* t1_standard_strings[229] == "exclamsmall" */ + /* */ + LOCAL_FUNC + T1_Short t1_expert_encoding[256] = + { + /* 0 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 229, 230, 0, 231, 232, 233, 234, + 235, 236, 237, 238, 13, 14, 15, 99, 239, 240, + /* 50 */ + 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, + /* 100 */ + 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, + /* 150 */ + 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, + /* 200 */ + 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, + /* 250 */ + 373, 374, 375, 376, 377, 378 + }; + + + /*************************************************************************/ + /* */ + /* t1_expert_subset_encoding: */ + /* */ + /* A simple table used to encode the Adobe ExpertEncoding subset */ + /* defined in the CFF specification. It will probably evolve into */ + /* another form sooner or later, as we deal with charsets */ + /* differently than with encodings. */ + /* */ + LOCAL_FUNC + FT_Short t1_expert_subset_encoding[256] = + { + /* 0 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 231, 232, 0, 0, + 235, 236, 237, 238, 13, 14, 15, 99, 239, 240, + /* 50 */ + 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, 0, 272, 0, 0, 0, 0, + /* 100 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 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, + /* 150 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 304, 305, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 314, 315, + 0, 0, 0, 0, 0, 0, 0, 0, 158, 155, + 163, 0, 320, 321, 322, 323, 324, 325, 0, 0, + /* 200 */ + 326, 150, 164, 169, 327, 328, 329, 330, 331, 332, + 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, + 343, 344, 345, 346, 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, + /* 250 */ + 0, 0, 0, 0, 0, 0 + }; + + +/* END */ diff --git a/src/shared/type1/t1encode.h b/src/shared/type1/t1encode.h new file mode 100644 index 000000000..4a55acd89 --- /dev/null +++ b/src/shared/type1/t1encode.h @@ -0,0 +1,98 @@ +/***************************************************************************/ +/* */ +/* t1encode.h */ +/* */ +/* Type 1 standard encoding tables definitions (specification). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 included by both the Type1 and Type2 driver. */ +/* It should never be compiled directly. */ +/* */ +/***************************************************************************/ + + +#ifndef T1ENCODE_H +#define T1ENCODE_H + +#include + + + /*************************************************************************/ + /* */ + /* t1_standard_strings: */ + /* */ + /* This array contains the Adobe Standard Glyph Names ordered by */ + /* SID. It was taken from the CFF specification. */ + /* */ + LOCAL_DEF + const T1_String* t1_standard_strings[]; + + + /*************************************************************************/ + /* */ + /* t1_standard_encoding: */ + /* */ + /* A simple table used to encode the Adobe StandardEncoding. The */ + /* table values are the SID of the standard glyphs; the table index */ + /* is the character code for the encoding. */ + /* */ + /* Example: */ + /* */ + /* t1_standard_encoding[33] == 2 */ + /* */ + /* which means that the glyph name for character code 32 is */ + /* */ + /* t1_standard_strings[2] == "exclam" */ + /* */ + /* (this correspond to the exclamation mark `!'). */ + /* */ + LOCAL_DEF + T1_Short t1_standard_encoding[256]; + + + /*************************************************************************/ + /* */ + /* t1_expert_encoding: */ + /* */ + /* A simple table used to encode the Adobe ExpertEncoding. The */ + /* table values are the SID of the standard glyphs; the table index */ + /* is the character code for the encoding. */ + /* */ + /* Example: */ + /* */ + /* t1_expert_encoding[33] == 229 */ + /* */ + /* which means that the glyph name for character code 32 is */ + /* */ + /* t1_standard_strings[229] == "exclamsmall" */ + /* */ + LOCAL_DEF + T1_Short t1_expert_encoding[256]; + + + /*************************************************************************/ + /* */ + /* t1_expert_subset_encoding: */ + /* */ + /* A simple table used to encode the Adobe ExpertEncoding subset */ + /* defined in the CFF specification. It will probably evolve into */ + /* another form sooner or later, as we deal with charsets */ + /* differently than with encodings. */ + /* */ + LOCAL_DEF + T1_Short t1_expert_subset_encoding[256]; + + +#endif /* T1ENCODE_H */ + + +/* END */ diff --git a/src/shared/type1/t1types.h b/src/shared/type1/t1types.h new file mode 100644 index 000000000..853b743c5 --- /dev/null +++ b/src/shared/type1/t1types.h @@ -0,0 +1,485 @@ +/******************************************************************* + * + * t1types.h 1.0 + * + * Basic Type1/Type2 type definitions and interface. + * + * This code is shared by the Type1 and Type2 drivers + * + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.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 + + +#ifdef __cplusplus + extern "C" { +#endif + + + +/*************************************************************************/ +/*************************************************************************/ +/*************************************************************************/ +/*** ***/ +/*** ***/ +/*** DEFINITIONS OF BASIC DATA TYPES ***/ +/*** ***/ +/*** ***/ +/*************************************************************************/ +/*************************************************************************/ +/*************************************************************************/ + + +/* The REDEFINE macro is used to convert a FreeType generic type into */ +/* a TrueType-specific one. It simply replaces the "FT_" prefix by "T1_" */ +/* in order to define compatible T1_Long, T1_Error, T1_Outline, etc.. */ +/* */ +#undef REDEFINE +#define REDEFINE( type ) typedef FT_##type T1_##type + + + /* T1_Bool */ + /* */ + /* */ + /* A simple typedef of unsigned char, used for simple booleans. */ + /* */ + REDEFINE( Bool ); + + + /* T1_FWord */ + /* */ + /* */ + /* a signed 16-bit integer used to store a distance in original */ + /* font units. */ + /* */ + REDEFINE( FWord ); + + + /* T1_UFWord */ + /* */ + /* */ + /* an unsigned 16-bit integer used to store a distance in original */ + /* font units. */ + /* */ + REDEFINE( UFWord ); + + + /* T1_Char */ + /* */ + /* */ + /* a simple typedef for the _signed_ char type. */ + /* */ + REDEFINE( Char ); + + + /* T1_Byte */ + /* */ + /* */ + /* a simple typedef for the _unsigned_ char type. */ + /* */ + REDEFINE( Byte ); + + + /* T1_String */ + /* */ + /* */ + /* a simple typedef for the char type, used for strings usually. */ + /* */ + REDEFINE( String ); + + + /* T1_Short */ + /* */ + /* */ + /* a typedef for signed short */ + /* */ + REDEFINE( Short ); + + + /* T1_UShort */ + /* */ + /* */ + /* a typedef for unsigned short */ + /* */ + REDEFINE( UShort ); + + + /* FT_Int */ + /* */ + /* */ + /* a typedef for the int type */ + /* */ + REDEFINE( Int ); + + + /* FT_UInt */ + /* */ + /* */ + /* a typedef for the unsigned int type */ + /* */ + REDEFINE( UInt ); + + + /* T1_Long */ + /* */ + /* */ + /* a typedef for signed long */ + /* */ + REDEFINE( Long ); + + + /* T1_ULong */ + /* */ + /* */ + /* a typedef for unsigned long */ + /* */ + REDEFINE( ULong ); + + + /* T1_F2Dot14 */ + /* */ + /* */ + /* a signed 2.14 fixed float used for unit vectors */ + /* */ + REDEFINE( F2Dot14 ); + + + /* T1_F26Dot6 */ + /* */ + /* */ + /* a signed 26.6 fixed float used for vectorial pixel coordinates */ + /* */ + REDEFINE( F26Dot6 ); + + + /* T1_Fixed */ + /* */ + /* */ + /* This type is used to store 16.16 fixed float values, like */ + /* scales or matrix coefficients.. */ + /* */ + REDEFINE( Fixed ); + + + /* T1_Pos */ + /* */ + /* */ + /* The type T1_Pos is a 32-bits 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.. */ + /* */ + REDEFINE( Pos ); + + + /* T1_Vector */ + /* */ + /* */ + /* A simple structure used to store a 2d vector, coordinates */ + /* are of the T1_Pos type. */ + /* */ + /* */ + /* x :: horizontal coordinate */ + /* y :: vertical coordinate */ + /* */ + REDEFINE( Vector ); + + /* T1_UnitVector */ + /* */ + /* */ + /* A simple structure used to store a 2d vector unit vector. */ + /* uses T1_F2Dot14 types. */ + /* */ + /* */ + /* x :: horizontal coordinate */ + /* y :: vertical coordinate */ + /* */ + REDEFINE( UnitVector ); + + + /* T1_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 */ + /* */ + REDEFINE( Matrix ); + + + /* T1_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) */ + /* */ + REDEFINE( BBox ); + + + /* T1_Error */ + /* */ + /* */ + /* The FreeType error code type. A value of 0 is always */ + /* interpreted as a succesful operation. */ + /* */ + REDEFINE( Error ); + + + +/*************************************************************************/ +/*************************************************************************/ +/*************************************************************************/ +/*** ***/ +/*** ***/ +/*** REQUIRED TYPE1/TYPE2 TABLES DEFINITIONS ***/ +/*** ***/ +/*** ***/ +/*************************************************************************/ +/*************************************************************************/ +/*************************************************************************/ + + /***********************************************************************/ + /* */ + /* T1_FontInfo */ + /* */ + /* */ + /* The FontInfo dictionary structure. */ + /* */ + /* */ + /* version :: */ + /* notice :: */ + /* full_name :: */ + /* family_name :: */ + /* weight :: */ + /* italic_angle :: */ + /* is_fixed_pitch :: */ + /* underline_position :: */ + /* underline_thickness :: */ + /* */ + typedef struct T1_FontInfo_ + { + T1_String* version; + T1_String* notice; + T1_String* full_name; + T1_String* family_name; + T1_String* weight; + T1_Long italic_angle; + T1_Bool is_fixed_pitch; + T1_Short underline_position; + T1_UShort underline_thickness; + + } T1_FontInfo; + + + /***********************************************************************/ + /* */ + /* T1_Private */ + /* */ + /* */ + /* The Private dictionary structure. */ + /* */ + /* */ + /* unique_id :: the font's unique id */ + /* lenIV :: length of decrypt padding */ + /* */ + /* num_blues :: number of blue values */ + /* num_other_blues :: number of other blue values */ + /* num_family_blues :: number of family blue values */ + /* num_family_other_blues :: number of family other blue values */ + /* */ + /* blue_values :: array of blue values */ + /* other_blues :: array of other blue values */ + /* family_blues :: array of family blue values */ + /* family_other_blues :: array of family other blue values */ + /* */ + /* blue_scale :: */ + /* blue_shift :: */ + /* blue_scale :: */ + /* */ + /* standard_width :: */ + /* standard_height :: */ + /* */ + /* num_snap_widths :: */ + /* num_snap_heights :: */ + /* force_bold :: */ + /* round_stem_up :: */ + /* */ + /* stem_snap_widths :: */ + /* stem_snap_heights :: */ + /* */ + /* language_group :: */ + /* password :: */ + /* */ + /* min_feature :: */ + /* */ + /* */ + typedef struct T1_Private_ + { + T1_Int unique_id; + T1_Int lenIV; + + T1_Byte num_blues; + T1_Byte num_other_blues; + T1_Byte num_family_blues; + T1_Byte num_family_other_blues; + + T1_Short blue_values[14]; + T1_Short other_blues[10]; + + T1_Short family_blues [14]; + T1_Short family_other_blues[10]; + + T1_Fixed blue_scale; + T1_Int blue_shift; + T1_Int blue_fuzz; + + T1_UShort standard_width; + T1_UShort standard_height; + + T1_Byte num_snap_widths; + T1_Byte num_snap_heights; + T1_Bool force_bold; + T1_Bool round_stem_up; + + T1_Short stem_snap_widths [13]; /* reserve one place for the std */ + T1_Short stem_snap_heights[13]; /* reserve one place for the std */ + + T1_Long language_group; + T1_Long password; + + T1_Short min_feature[2]; + + } T1_Private; + + + + /***********************************************************************/ + /* */ + /* T1_Private */ + /* */ + /* */ + /* The Private dictionary structure. */ + /* */ + /* */ + /* num_chars :: number of char codes in encoding. Usually 256 */ + /* code_first :: lower char code in encoding */ + /* code_last :: higher char code in encoding */ + /* */ + /* char_code :: array of character codes */ + /* char_index :: array of correpsonding glyph indices */ + /* char_name :: array of correpsonding glyph names */ + /* */ + typedef struct T1_Encoding_ + { + T1_Int num_chars; + T1_Int code_first; + T1_Int code_last; + + T1_Short* char_index; + T1_String** char_name; + + } T1_Encoding; + + + +/*************************************************************************/ +/*************************************************************************/ +/*************************************************************************/ +/*** ***/ +/*** ***/ +/*** 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 "drivers/truetype/ttobjs.h" ***/ +/*** ***/ +/*** ***/ +/*************************************************************************/ +/*************************************************************************/ +/*************************************************************************/ + + + typedef struct T1_FaceRec_* T1_Face; + + + /***************************************************/ + /* */ + /* T1_Face : */ + /* */ + /* Type1 face record.. */ + /* */ + + typedef struct T1_FaceRec_ + { + FT_FaceRec root; + + T1_FontInfo font_info; + FT_String* font_name; + + T1_Encoding encoding; + + T1_Byte* subrs_block; + T1_Byte* charstrings_block; + + T1_Int num_subrs; + T1_Byte** subrs; + T1_Int* subrs_len; + + T1_Int num_glyphs; + T1_String** glyph_names; /* array of glyph names */ + T1_Byte** charstrings; /* array of glyph charstrings */ + T1_Int* charstrings_len; + + T1_Byte paint_type; + T1_Byte font_type; + T1_Matrix font_matrix; + T1_BBox font_bbox; + T1_Long unique_id; + T1_Long font_id; + + T1_Int stroke_width; + T1_Private private_dict; + + } T1_FaceRec; + + +#endif /* T1TYPES_H */ diff --git a/src/truetype/rules.mk b/src/truetype/rules.mk new file mode 100644 index 000000000..cba7ac126 --- /dev/null +++ b/src/truetype/rules.mk @@ -0,0 +1,205 @@ +#**************************************************************************** +#* * +#* TrueType driver Makefile * +#* * +#* Copyright 1996-1999 by * +#* David Turner, Robert Wilhelm, and Werner Lemberg. * +#* * +#* This file is part of the FreeType project, and may only be used * +#* modified and distributed under the terms of the FreeType project * +#* license, LICENSE.TXT. By continuing to use, modify, or distribute * +#* this file you indicate that you have read the license and * +#* understand and accept it fully. * +#* * +#**************************************************************************** + + +#**************************************************************************** +#* * +#* IMPORTANT NOTE: This Makefile is intended for GNU Make! * +#* If you provide Makefiles for other make utilities, * +#* please place them in `freetype/lib/arch/'. * +#* * +#* * +#* This file is to be included by the FreeType Makefile.lib, located in * +#* the `freetype/lib' directory. Here is the list of the variables that * +#* must be defined to use it: * +#* * +#* * +#* BASE_DIR: The location of the base layer's directory. This is * +#* usually `freetype/lib/base'. * +#* * +#* ARCH_DIR: The location of the architecture-dependent directory. * +#* This is usually `freetype/lib/arch/'. * +#* * +#* DRIVERS_DIR: The location of the font driver sub-dirs, usually * +#* `freetype/lib/drivers'. * +#* * +#* OBJ_DIR: The location where the compiled object(s) file will be * +#* placed. * +#* * +#* BASE_H: A list of pathnames to the base layer's header files on * +#* which the driver depends. * +#* * +#* FT_CFLAGS: A set of flags used for compilation of object files. * +#* This contains at least the include paths of the arch * +#* and base directories + optimization + warnings + ANSI * +#* compliance. * +#* * +#* FT_IFLAG: The flag used to specify an include path on the * +#* compiler command line. For example, with GCC, this is * +#* `-I', while some other compilers use `/i=' or `-J', * +#* etc. * +#* * +#* FT_OBJ: The suffix of an object file for the platform; can be * +#* `o', `obj', `coff', `tco', etc. depending on the * +#* platform. * +#* * +#* * +#* It also updates the following variables defined and used in the main * +#* Makefile: * +#* * +#* DRV_OBJ_S: The list of driver object files in * +#* single-object mode. * +#* * +#* DRV_OBJ_M: The list of driver object files in * +#* multiple-objects mode. * +#* * +#* FTINIT_DRIVER_PATHS: The list of include paths used to compile the * +#* `ftinit' component which registers all font * +#* drivers in the FT_Init_FreeType() function. * +#* * +#* FTINIT_DRIVER_H: The list of header dependencies used to * +#* compile the `ftinit' component. * +#* * +#* FTINIT_DRIVER_MACROS: The list of macros to be defined when * +#* compiling the `ftinit' component. * +#* * +#* `Single-object compilation' means that each font driver is compiled * +#* into a single object file. This is useful to get rid of all * +#* driver-specific entries. * +#* * +#**************************************************************************** + +# include the rules defined for the SFNT driver, which is heavily used +# by the TrueType one.. +# +include $(SRC_)sfnt/rules.mk + + +# TrueType driver directory +# +TT_DIR := $(SRC_)truetype +TT_DIR_ := $(TT_DIR)$(SEP) + + +# location of all extensions to the driver, if any +# +TT_EXT_DIR := $(TT_DIR_)extend +TT_EXT_DIR_ := $(TT_EXT_DIR)$(SEP) + +# additional include flags used when compiling the driver +# +TT_INCLUDE := $(SFNT_INCLUDE) $(TT_DIR) $(TT_EXT_DIR) + + +# compilation flags for the driver +# +TT_CFLAGS := $(TT_INCLUDE:%=$I%) +TT_COMPILE := $(FT_CC) $(TT_CFLAGS) + + +# 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 := $(SFNT_H) \ + $(TT_DIR_)ttconfig.h \ + $(TT_DRV_SRC:%.c=%.h) + + +# default TrueType extensions sources +# +TT_EXT_SRC := $(TT_EXT_DIR_)ttxkern.c \ + $(TT_EXT_DIR_)ttxgasp.c \ + $(TT_EXT_DIR_)ttxpost.c \ + $(TT_EXT_DIR_)ttxcmap.c \ + $(TT_EXT_DIR_)ttxwidth.c + + +# default TrueType extensions headers +# +TT_EXT_H := $(TT_EXT_SRC:.c=.h) + + +# driver object(s) +# +# TT_DRV_OBJ_M is used during `debug' builds +# TT_DRV_OBJ_S is used during `release' builds +# +TT_DRV_OBJ_M := $(TT_DRV_SRC:$(TT_DIR_)%.c=$(OBJ_)%.$O) +TT_DRV_OBJ_S := $(OBJ_)truetype.$O + + +# default extensions objects +# +TT_EXT_OBJ := $(TT_EXT_SRC:$(TT_EXT_DIR_)%.c=$(OBJ_)%.$O) + + + +# driver root source file(s) +# +TT_DRV_SRC_M := $(TT_DRV_SRC) $(SFNT_SRC) +TT_DRV_SRC_S := $(TT_DIR_)truetype.c + + +# driver - single object +# +# the driver is recompiled if any of the header or source files is changed +# as well as any of the shared source files found in `shared/sfnt' +# +$(TT_DRV_OBJ_S): $(BASE_H) $(TT_DRV_H) $(TT_DRV_SRC) $(TT_DRV_SRC_S) + $(TT_COMPILE) $T$@ $(TT_DRV_SRC_S) + + + +# driver - multiple objects +# +# All objects are recompiled if any of the header files is changed +# +$(OBJ_)tt%.$O: $(TT_DIR_)tt%.c $(BASE_H) $(TT_DRV_H) + $(TT_COMPILE) $T$@ $< + +$(OBJ_)ttx%.$O: $(TT_EXT_DIR_)ttx%.c $(BASE_H) $(SFNT_H) $(TT_EXT_H) + $(TT_COMPILE) $T$@ $< + +$(OBJ_)tt%.$O: $(SFNT_DIR_)tt%.c $(BASE_H) $(SFNT_H) + $(TT_COMPILE) $T$@ $< + + +# treat `ttpload' as a special case, as it includes C files +# +$(OBJ_)ttpload.$O: $(TT_DIR_)ttpload.c $(BASE_H) $(SFNT_SRC) $(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) + + +# update `ftinit' variables +# +FTINIT_DRIVER_PATHS += $(SFNT_DIR) $(TT_DIR) $(TT_EXT_DIR) +FTINIT_DRIVER_H += $(SFNT_H) $(TT_DRV_H) +FTINIT_DRIVER_MACROS += FT_SUPPORT_TRUETYPE + +# END diff --git a/src/truetype/truetype.c b/src/truetype/truetype.c new file mode 100644 index 000000000..e5fe88400 --- /dev/null +++ b/src/truetype/truetype.c @@ -0,0 +1,50 @@ +/***************************************************************************/ +/* */ +/* truetype.c */ +/* */ +/* FreeType TrueType driver component (body only). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 compile the FreeType TrueType font driver. It */ + /* relies on all components included in the `base' layer (see the file */ + /* `ftbase.c'). The source code is located in `freetype/ttlib' and */ + /* contains: */ + /* */ + /* - a driver interface */ + /* - an object manager */ + /* - a table loader */ + /* - a glyph loader */ + /* - a glyph hinter/bytecode interpreter */ + /* - a charmap processor */ + /* - an extension manager (only used for some tools) */ + /* */ + /* Note that the engine extensions found in `freetype/ttlib/extend' are */ + /* reserved to specific tools and/or font servers; they're not part of */ + /* the `core' TrueType driver, even though they are separately linkable */ + /* to it. */ + /* */ + /*************************************************************************/ + + +#define FT_MAKE_OPTION_SINGLE_OBJECT + +#include /* driver interface */ +#include /* tables loader */ +#include /* glyph loader */ +#include /* bytecode interpreter */ +#include /* object manager */ + +/* END */ diff --git a/src/truetype/ttconfig.h b/src/truetype/ttconfig.h new file mode 100644 index 000000000..cdb4f6e57 --- /dev/null +++ b/src/truetype/ttconfig.h @@ -0,0 +1,66 @@ +/***************************************************************************/ +/* */ +/* ttconfig.h */ +/* */ +/* TrueType configuration file (specification only). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 configure various aspects of the TrueType */ + /* driver. */ + /* */ + /*************************************************************************/ + + +#ifndef TTCONFIG_H +#define TTCONFIG_H + + + /*************************************************************************/ + /* */ + /* 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 a faster, though larger, code. */ + /* */ +#define TT_CONFIG_OPTION_INTERPRETER_SWITCH + + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_EMBEDDED_BITMAPS if you want to support */ + /* embedded bitmaps in the TrueType/OpenType driver. */ + /* */ +#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. */ + /* */ +#define TT_CONFIG_OPTION_POSTSCRIPT_NAMES + + +#define TT_USE_FIXED + +#endif /* TTCONFIG_H */ + + +/* END */ diff --git a/src/truetype/ttdriver.c b/src/truetype/ttdriver.c new file mode 100644 index 000000000..7dafb88fc --- /dev/null +++ b/src/truetype/ttdriver.c @@ -0,0 +1,783 @@ +/***************************************************************************/ +/* */ +/* ttdriver.c */ +/* */ +/* TrueType font driver implementation (body). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 + + +#undef FT_COMPONENT +#define FT_COMPONENT trace_ttdriver + + + static + TT_Bool string_compare( const TT_String* s1, + const TT_String* s2 ) + { + int tries; + + + for ( tries = 128; tries > 0; tries-- ) + { + if ( !*s1 ) + return !*s2; + + if ( *s1 != *s2 ) + return 0; + + s1++; + s2++; + } + + return 0; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Get_Interface */ + /* */ + /* */ + /* Some drivers can be compiled with extensions, special code used */ + /* only for specific purposes (usually for system-specific uses). */ + /* Each extension is registered through a simple name (e.g. `sfnt', */ + /* `post_names', etc). */ + /* */ + /* This function is used to return an extension's interface (i.e., */ + /* a table of pointers) when it is present in the driver. */ + /* */ + /* If the driver wasn't compiled with the requested extension, it */ + /* should return NULL. */ + /* */ + /* */ + /* driver :: A handle to the driver object. */ + /* */ + /* interface :: The interface's name string. */ + /* */ + /* */ + /* A typeless pointer to the extension's interface (normally a table */ + /* of function pointers). Returns NULL when the requested extension */ + /* isn't available (i.e., wasn't compiled in the driver at build */ + /* time). */ + /* */ + /* */ + /* Note that unlike format-specific methods returned by */ + /* getFormatInterface(), extensions can be format-independent. */ + /* */ + static + void* Get_Interface( TT_Driver driver, + const TT_String* interface ) + { + /* `sfnt' returns a vtable of functions used to access the tables */ + /* of a TrueType or OpenType font resource. */ + if ( string_compare( interface, "sfnt" ) ) + return (void*)NULL; + + /* XXXX : For now, there is no extension support there */ + UNUSED( driver ); + UNUSED( interface ); + + return NULL; + } + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** F A C E S ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /****************************************************************** + * + * + * find_encoding + * + * + * return the FT_Encoding corresponding to a given + * (platform_id,encoding_id) pair, as found in TrueType charmaps + * + * + * platform_id :: + * encoding_id :: + * + * + * the corresponding FT_Encoding tag. ft_encoding_none by default + * + *****************************************************************/ + + 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_BIG_5, ft_encoding_big5 } + }; + + 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; + } + + + + + /*************************************************************************/ + /* */ + /* */ + /* Init_Face */ + /* */ + /* */ + /* A driver method used to initialize a new TrueType face object. */ + /* */ + /* */ + /* resource :: A handle to the source resource. */ + /* */ + /* typeface_index :: An index of the face in the font resource. Used */ + /* to access individual faces in font collections. */ + /* */ + /* */ + /* face :: A handle to the face object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The `typeface_index' parameter field will be set to -1 if the */ + /* engine only wants to test the format of the resource. This means */ + /* that font drivers should simply check the font format, then return */ + /* immediately with an error code of 0 (meaning success). The field */ + /* `num_faces' should be set. */ + /* */ + /* Done_Face() will be called subsequently, whatever the result was. */ + /* */ + static + TT_Error Init_Face( FT_Stream stream, + TT_Long typeface_index, + TT_Face face ) + { + TT_Error error; + + /* initialize the TrueType face object */ + error = TT_Init_Face( stream, typeface_index, face ); + + /* now set up root fields */ + if ( !error && typeface_index >= 0 ) + { + FT_Face root = &face->root; + FT_Int flags; + TT_CharMap charmap; + TT_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 */ + + /* 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; + } + + face->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 ) ) + return error; + + 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; + } + + root->num_fixed_sizes = 0; + root->available_sizes = 0; + + /*****************************************************************/ + /* */ + /* 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 = root->height; + if ( face->vertical_info ) + root->max_advance_height = face->vertical.advance_Height_Max; + + root->underline_position = face->postscript.underlinePosition; + root->underline_thickness = face->postscript.underlineThickness; + + /* root->max_points - already set up */ + /* root->max_contours - already set up */ + + } + return error; + } + + +#undef PAIR_TAG +#define PAIR_TAG( left, right ) ( ((TT_ULong)left << 16) | (TT_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 + TT_Error Get_Kerning( TT_Face face, + TT_UShort left_glyph, + TT_UShort right_glyph, + TT_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! */ + TT_ULong search_tag = PAIR_TAG( left_glyph, right_glyph ); + TT_Long left, right; + + + left = 0; + right = face->num_kern_pairs - 1; + + while ( left + 1 < right ) + { + TT_Int middle = (left + right) >> 1; + TT_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; + else + right = middle; + } + + pair = face->kern_pairs + left; + if ( PAIR_TAG( pair->left, pair->right ) == search_tag ) + goto Found; + + pair = face->kern_pairs + right; + if ( PAIR_TAG( pair->left, pair->right ) == search_tag ) + goto Found; + } + + 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. */ + /* */ + /* */ + /* size :: A handle to the target size object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + TT_Error Set_Char_Sizes( TT_Size size, + TT_F26Dot6 char_width, + TT_F26Dot6 char_height, + TT_UInt horz_resolution, + TT_UInt vert_resolution ) + { + FT_Size_Metrics* metrics = &size->root.metrics; + TT_Face face = (TT_Face)size->root.face; + TT_Long dim_x, dim_y; + + + 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; + dim_y = (char_height * vert_resolution) / 72; + + /* Truncate to integer pixels if required by font - nearly all */ + /* TrueType fonts have this bit set, as hinting can really work */ + /* with integer pixel sizes. */ + if ( face->header.Flags & 8 ) + { + dim_x = (dim_x + 32) & -64; + dim_y = (dim_y + 32) & -64; + } + + metrics->x_scale = FT_MulDiv( dim_x, + 0x10000L, + face->root.units_per_EM ); + + metrics->y_scale = FT_MulDiv( dim_y, + 0x10000L, + face->root.units_per_EM ); + + metrics->x_ppem = (TT_UShort)(dim_x >> 6); + metrics->y_ppem = (TT_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 + TT_Error Set_Pixel_Sizes( TT_Size size, + TT_UInt pixel_width, + TT_UInt pixel_height ) + { + FT_Size_Metrics* metrics = &size->root.metrics; + TT_Face face = (TT_Face)size->root.face; + + + if ( pixel_width < 1 ) pixel_width = 1; + if ( pixel_height < 1 ) pixel_height = 1; + + metrics->x_ppem = pixel_width; + metrics->y_ppem = pixel_height; + + metrics->x_scale = FT_MulDiv( metrics->x_ppem << 6, + 0x10000L, + face->root.units_per_EM ); + + metrics->y_scale = FT_MulDiv( metrics->y_ppem << 6, + 0x10000L, + face->root.units_per_EM ); + + 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). */ + /* */ + /* result :: A set of bit flags indicating the type of data that */ + /* was loaded in the glyph slot (outline, bitmap, */ + /* pixmap, etc). */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + TT_Error Load_Glyph( TT_GlyphSlot slot, + TT_Size size, + TT_UShort glyph_index, + TT_UInt load_flags ) + { + TT_Error error; + + + if ( !slot ) + return TT_Err_Invalid_Glyph_Handle; + + /* check that 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 */ + 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, + TT_Long charcode ) + { + TT_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 error; + + cmap->loaded = TRUE; + } + + if ( cmap->get_index ) + return cmap->get_index( cmap, charcode ); + else + return 0; + } + + + /* The FT_DriverInterface structure is defined in ftdriver.h. */ + + const FT_DriverInterface tt_driver_interface = + { + sizeof ( TT_DriverRec ), + sizeof ( TT_FaceRec ), + sizeof ( TT_SizeRec ), + sizeof ( FT_GlyphSlotRec ), + + "truetype", /* driver name */ + 1, /* driver version */ + 2, /* driver requires FreeType 2 or above */ + + (void*)0, + + (FTDriver_initDriver) TT_Init_Driver, + (FTDriver_doneDriver) TT_Done_Driver, + (FTDriver_getInterface) Get_Interface, + + (FTDriver_initFace) Init_Face, + (FTDriver_doneFace) TT_Done_Face, + (FTDriver_getKerning) Get_Kerning, + + (FTDriver_initSize) TT_Init_Size, + (FTDriver_doneSize) TT_Done_Size, + (FTDriver_setCharSizes) Set_Char_Sizes, + (FTDriver_setPixelSizes) Set_Pixel_Sizes, + + (FTDriver_initGlyphSlot) TT_Init_GlyphSlot, + (FTDriver_doneGlyphSlot) TT_Done_GlyphSlot, + (FTDriver_loadGlyph) Load_Glyph, + + (FTDriver_getCharIndex) Get_Char_Index, + }; + + + + /*************************************************************************/ + /* */ + /* */ + /* 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. */ + /* */ +#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS + + EXPORT_FUNC + FT_DriverInterface* getDriverInterface( void ) + { + return &truetype_driver_interface; + } + +#endif /* CONFIG_OPTION_DYNAMIC_DRIVERS */ + + +/* END */ diff --git a/src/truetype/ttdriver.h b/src/truetype/ttdriver.h new file mode 100644 index 000000000..eba67b612 --- /dev/null +++ b/src/truetype/ttdriver.h @@ -0,0 +1,193 @@ +/***************************************************************************/ +/* */ +/* ttdriver.h */ +/* */ +/* High-level TrueType driver interface (specification). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 +#include +#include +#include +#include + + + /*************************************************************************/ + /* */ + /* */ + /* TTDriver_getFontData */ + /* */ + /* */ + /* Returns either a single font table or the whole font file into */ + /* caller's memory. This function mimics the GetFontData() API */ + /* function found in Windows. */ + /* */ + /* */ + /* face :: A handle to the source TrueType face object. */ + /* */ + /* tag :: A 32-bit integer used to name the table you want to */ + /* read. Use the macro MAKE_TT_TAG (defined in freetype.h) */ + /* to create one. Use the value 0 if you want to access */ + /* the whole file instead. */ + /* */ + /* offset :: The offset from the start of the table or file from */ + /* which you want to read bytes. */ + /* */ + /* buffer :: The address of the target/read buffer where data will be */ + /* copied. */ + /* */ + /* */ + /* length :: The length in bytes of the data to read. If it is set */ + /* to 0 when this function is called, it will return */ + /* immediately, setting the value of `length' to the */ + /* requested table's size (or the whole font file if the */ + /* tag is 0). It is thus possible to allocate and read an */ + /* arbitrary table in two successive calls. */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + typedef TT_Error (*TTDriver_getFontData)( TT_Face face, + TT_ULong tag, + TT_ULong offset, + void* buffer, + TT_Long* length ); + + + /*************************************************************************/ + /* */ + /* */ + /* TTDriver_getFaceWidths */ + /* */ + /* */ + /* Returns the widths and/or heights of a given range of glyph from */ + /* a face. */ + /* */ + /* */ + /* face :: A handle to the source FreeType face object. */ + /* */ + /* first_glyph :: The first glyph in the range. */ + /* */ + /* last_glyph :: The last glyph in the range. */ + /* */ + /* */ + /* widths :: The address of the table receiving the widths */ + /* expressed in font units (UShorts). Set this */ + /* parameter to NULL if you're not interested in these */ + /* values. */ + /* */ + /* heights :: The address of the table receiving the heights */ + /* expressed in font units (UShorts). Set this */ + /* parameter to NULL if you're not interested in these */ + /* values. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + typedef TT_Error (*TTDriver_getFaceWidths)( TT_Face face, + TT_UShort first_glyph, + TT_UShort last_glyph, + TT_UShort* widths, + TT_UShort* heights ); + + + + /*************************************************************************/ + /* */ + /* */ + /* TT_DriverInterface */ + /* */ + /* */ + /* The TrueType-specific interface of this driver. Note that some of */ + /* the methods defined here are optional, as they're only used for */ + /* for specific tasks of the driver. */ + /* */ + /* */ + /* get_font_data :: See the declaration of TTDriver_getFontData(). */ + /* get_face_widths :: See the declaration of */ + /* TTDriver_getFaceWidths(). */ + /* */ + typedef struct TT_DriverInterface_ + { + TTDriver_getFontData get_font_data; + TTDriver_getFaceWidths get_face_widths; + + } TT_DriverInterface; + + + EXPORT_DEF + const FT_DriverInterface tt_driver_interface; + + + EXPORT_DEF + const TT_DriverInterface tt_format_interface; + + + +/************************************************************************* + * + * Here is a template of the code that should appear in each + * font driver's _interface_ file (the one included by "ftinit.c"). + * + * It is used to build, at compile time, a simple linked list of + * the interfaces of the drivers which have been #included in + * "ftinit.c". See the source code of the latter file for details + * + * (Note that this is only required when you want your driver included + * in the set of default drivers loaded by FT_Init_FreeType. Other + * drivers can still be added manually at runtime with FT_Add_Driver. + * + * { + * #ifdef FTINIT_DRIVER_CHAIN + * + * static + * const FT_DriverChain ftinit__driver_chain = + * { + * FT_INIT_LAST_DRIVER_CHAIN, + * &_driver_interface + * }; + * + * #undef FT_INIT_LAST_DRIVER_CHAIN + * #define FT_INIT_LAST_DRIVER_CHAIN &ftinit__driver_chain + * + * #endif + * } + * + * replace with your driver's prefix + * + *************************************************************************/ + + +#ifdef FTINIT_DRIVER_CHAIN + + static + const FT_DriverChain ftinit_tt_driver_chain = + { + FT_INIT_LAST_DRIVER_CHAIN, + &tt_driver_interface + }; + +#undef FT_INIT_LAST_DRIVER_CHAIN +#define FT_INIT_LAST_DRIVER_CHAIN &ftinit_tt_driver_chain + +#endif /* FTINIT_DRIVER_CHAIN */ + + + +#endif /* TTDRIVER_H */ + + +/* END */ diff --git a/src/truetype/tterrors.h b/src/truetype/tterrors.h new file mode 100644 index 000000000..90286e3ed --- /dev/null +++ b/src/truetype/tterrors.h @@ -0,0 +1,124 @@ +/***************************************************************************/ +/* */ +/* tterrors.h */ +/* */ +/* TrueType error ID definitions (specification only). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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_Unavailable_Outline FT_Err_Unavailable_Outline +#define TT_Err_Unavailable_Bitmap FT_Err_Unavailable_Bitmap +#define TT_Err_Unavailable_Pixmap FT_Err_Unavailable_Pixmap +#define TT_Err_File_Is_Not_Collection FT_Err_File_Is_Not_Collection + +#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_Points FT_Err_Too_Many_Points +#define TT_Err_Too_Many_Contours FT_Err_Too_Many_Contours +#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 + + /* 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 /* FTERRID_H */ + + +/* END */ diff --git a/src/truetype/ttgload.c b/src/truetype/ttgload.c new file mode 100644 index 000000000..0a7831525 --- /dev/null +++ b/src/truetype/ttgload.c @@ -0,0 +1,1492 @@ +/***************************************************************************/ +/* */ +/* ttgload.c */ +/* */ +/* TrueType Glyph Loader (body). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 + + + /* required for the tracing mode */ +#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 + + +#undef SCALE_X +#define SCALE_X( distance ) FT_MulFix( distance, exec->metrics.x_scale ) + +#undef SCALE_Y +#define SCALE_Y( distance ) FT_MulFix( distance, exec->metrics.y_scale ) + + + /*************************************************************************/ + /* */ + /* */ + /* 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, + TT_UShort index, + TT_Short* bearing, + TT_UShort* advance ) + { + TT_LongMetrics* longs_m; + TT_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; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* Get_HMetrics */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* face :: A handle to the target source face. */ + /* */ + /* index :: The glyph index. */ + /* */ + /* check :: If set, handle monospaced fonts. */ + /* */ + /* */ + /* lsb :: The left side bearing. */ + /* */ + /* aw :: The advance width. */ + /* */ + static + void Get_HMetrics( TT_Face face, + TT_UShort index, + TT_Bool check, + TT_Short* lsb, + TT_UShort* aw ) + { + TT_Get_Metrics( &face->horizontal, index, lsb, aw ); + + if ( check && face->postscript.isFixedPitch ) + *aw = face->horizontal.advance_Width_Max; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Get_Advance_Widths */ + /* */ + /* */ + /* Returns the advance width table for a given pixel size if it is */ + /* found in the font's `hdmx' table (if any). */ + /* */ + /* */ + /* face :: A handle to the target source face. */ + /* */ + /* ppem :: The pixel size. */ + /* */ + /* */ + /* A pointer to the advance with table. NULL if it doesn't exist. */ + /* */ + static + TT_Byte* Get_Advance_Widths( TT_Face face, + TT_UShort ppem ) + { + TT_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 ( TT_Vector ) ) + +#define org_to_cur( n, zone ) \ + MEM_Copy( (zone)->cur, (zone)->org, n * sizeof ( TT_Vector ) ) + + + /*************************************************************************/ + /* */ + /* */ + /* translate_array */ + /* */ + /* */ + /* Translates an array of coordinates. */ + /* */ + /* */ + /* n :: The number of points to translate. */ + /* */ + /* delta_x :: The horizontal coordinate of the shift vector. */ + /* */ + /* delta_y :: The vertical coordinate of the shift vector. */ + /* */ + /* */ + /* coords :: The vector array to translate. */ + /* */ + static + void translate_array( TT_UShort n, + TT_Vector* coords, + TT_Pos delta_x, + TT_Pos delta_y ) + { + TT_UShort 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* mount_zone */ + /* */ + /* */ + /* Mounts one glyph zone on top of another. This is needed to */ + /* assemble composite glyphs. */ + /* */ + /* */ + /* source :: The source glyph zone. */ + /* */ + /* */ + /* target :: The target glyph zone. */ + /* */ + static + void mount_zone( TT_GlyphZone* source, + TT_GlyphZone* target ) + { + TT_UShort np; + TT_Short nc; + + + np = source->n_points; + nc = source->n_contours; + + target->org = source->org + np; + target->cur = source->cur + np; + target->touch = source->touch + np; + + target->contours = source->contours + nc; + + target->n_points = 0; + target->n_contours = 0; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Load_Simple_Glyph */ + /* */ + /* */ + /* Loads a simple (i.e, non-composite) glyph. This function is used */ + /* for the `Load_Simple' state of TT_Load_Glyph(). All composite */ + /* glyphs elements will be loaded with routine. */ + /* */ + static + TT_Error Load_Simple_Glyph( TT_ExecContext exec, + FT_Stream stream, + TT_ULong byte_count, + TT_Short n_contours, + TT_Short left_contours, + TT_UShort left_points, + TT_UInt load_flags, + TT_SubGlyphRec* subg, + TT_Bool debug ) + { + TT_Error error; + TT_GlyphZone* pts; + TT_Short k; + TT_UShort j; + TT_UShort n_points, n_ins; + TT_Face face; + TT_Byte* flag; + TT_Vector* vec; + TT_F26Dot6 x, y; + + TT_Vector *pp1, *pp2; + + + face = exec->face; + + /*********************************************************************/ + /* simple check */ + + if ( n_contours > left_contours ) + { + FT_TRACE0(( "ERROR: Glyph index %ld has %d contours > left %d\n", + subglyph.index, + n_contours, + left_contours )); + return TT_Err_Too_Many_Contours; + } + + /* preparing the execution context */ + mount_zone( &subg->zone, &exec->pts ); + + + /*********************************************************************/ + /* reading the contours endpoints */ + + if ( ACCESS_Frame( byte_count ) ) + return error; + + for ( k = 0; k < n_contours; k++ ) + exec->pts.contours[k] = GET_UShort(); + + n_points = 0; + if ( n_contours > 0 ) + n_points = exec->pts.contours[n_contours - 1] + 1; + + + /*********************************************************************/ + /* reading the bytecode instructions */ + + n_ins = GET_UShort(); + + if ( n_points > left_points ) + { + FT_TRACE0(( "ERROR: Too many points in glyph %ld\n", subg->index )); + error = TT_Err_Too_Many_Points; + goto Fail; + } + + FT_TRACE4(( "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; + } + MEM_Copy( exec->glyphIns, stream->cursor, n_ins ); + stream->cursor += n_ins; + + error = TT_Set_CodeRange( exec, tt_coderange_glyph, + exec->glyphIns, n_ins ); + if (error) goto Fail; + + + /*********************************************************************/ + /* reading the point flags */ + + j = 0; + flag = exec->pts.touch; + + while ( j < n_points ) + { + TT_Byte c, cnt; + + flag[j] = c = GET_Byte(); + j++; + + if ( c & 8 ) + { + cnt = GET_Byte(); + + while( cnt > 0 ) + { + flag[j++] = c; + cnt--; + } + } + } + + /*********************************************************************/ + /* reading the X coordinates */ + + x = 0; + vec = exec->pts.org; + + for ( j = 0; j < n_points; j++ ) + { + if ( flag[j] & 2 ) + { + if ( flag[j] & 16 ) + x += GET_Byte(); + else + x -= GET_Byte(); + } + else + { + if ( (flag[j] & 16) == 0 ) + x += GET_Short(); + } + + vec[j].x = x; + } + + + /*********************************************************************/ + /* reading the YX coordinates */ + + y = 0; + + for ( j = 0; j < n_points; j++ ) + { + if ( flag[j] & 4 ) + { + if ( flag[j] & 32 ) + y += GET_Byte(); + else + y -= GET_Byte(); + } + else + { + if ( (flag[j] & 32) == 0 ) + y += GET_Short(); + } + + vec[j].y = y; + } + + FORGET_Frame(); + + /*********************************************************************/ + /* Add shadow points */ + + /* Now add the two shadow points at n and n + 1. */ + /* We need the left side bearing and advance width. */ + + /* pp1 = xMin - lsb */ + pp1 = vec + n_points; + pp1->x = subg->bbox.xMin - subg->left_bearing; + pp1->y = 0; + + /* pp2 = pp1 + aw */ + pp2 = pp1 + 1; + pp2->x = pp1->x + subg->advance; + pp2->y = 0; + + /* clear the touch flags */ + for ( j = 0; j < n_points; j++ ) + exec->pts.touch[j] &= FT_Curve_Tag_On; + + exec->pts.touch[n_points ] = 0; + exec->pts.touch[n_points + 1] = 0; + + /* Note that we return two more points that are not */ + /* part of the glyph outline. */ + + n_points += 2; + + /* now eventually scale and hint the glyph */ + + pts = &exec->pts; + pts->n_points = n_points; + pts->n_contours = n_contours; + + if (load_flags & FT_LOAD_NO_SCALE) + { + /* no scaling, just copy the orig arrays into the cur ones */ + org_to_cur( n_points, pts ); + } + else + { + /* first scale the glyph points */ + for ( j = 0; j < n_points; j++ ) + { + pts->org[j].x = SCALE_X( pts->org[j].x ); + pts->org[j].y = SCALE_Y( pts->org[j].y ); + } + + /* if hinting, round pp1, and shift the glyph accordingly */ + if ( subg->is_hinted ) + { + x = pts->org[n_points - 2].x; + x = ((x + 32) & -64) - x; + translate_array( n_points, pts->org, x, 0 ); + + org_to_cur( n_points, pts ); + + pts->cur[n_points - 1].x = (pts->cur[n_points - 1].x + 32) & -64; + + /* now consider hinting */ + if ( n_ins > 0 ) + { + exec->is_composite = FALSE; + exec->pedantic_hinting = load_flags & FT_LOAD_PEDANTIC; + + error = TT_Run_Context( exec, debug ); + if ( error && exec->pedantic_hinting ) + return error; + } + } + else + org_to_cur( n_points, pts ); + } + + /* save glyph phantom points */ + if ( !subg->preserve_pps ) + { + subg->pp1 = pts->cur[n_points - 2]; + subg->pp2 = pts->cur[n_points - 1]; + } + + return TT_Err_Ok; + + Fail: + FORGET_Frame(); + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Load_Composite_End */ + /* */ + /* */ + /* Finalizes the loading process of a composite glyph element. This */ + /* function is used for the `Load_End' state of TT_Load_Glyph(). */ + /* */ + static + TT_Error Load_Composite_End( TT_UShort n_points, + TT_Short n_contours, + TT_ExecContext exec, + TT_SubGlyphRec* subg, + FT_Stream stream, + TT_UInt load_flags, + TT_Bool debug ) + { + TT_Error error; + + TT_UShort k, n_ins; + TT_GlyphZone* pts; + + if ( subg->is_hinted && + subg->element_flag & WE_HAVE_INSTR ) + { + if ( READ_UShort( n_ins ) ) /* read size of instructions */ + return error; + + FT_TRACE4(( "Instructions size = %d\n", n_ins )); + + if ( n_ins > exec->face->max_profile.maxSizeOfInstructions ) + { + FT_TRACE0(( "Too many instructions in composite glyph %ld\n", + subg->index )); + return TT_Err_Too_Many_Ins; + } + + if ( FILE_Read( exec->glyphIns, n_ins ) ) + return error; + + error = TT_Set_CodeRange( exec, + tt_coderange_glyph, + exec->glyphIns, + n_ins ); + if ( error ) + return error; + } + else + n_ins = 0; + + + /* prepare the execution context */ + n_points += 2; + exec->pts = subg->zone; + pts = &exec->pts; + + pts->n_points = n_points; + pts->n_contours = n_contours; + + /* add phantom points */ + pts->cur[n_points - 2] = subg->pp1; + pts->cur[n_points - 1] = subg->pp2; + + pts->touch[n_points - 1] = 0; + pts->touch[n_points - 2] = 0; + + /* if hinting, round the phantom points */ + if ( subg->is_hinted ) + { + pts->cur[n_points - 2].x = ((subg->pp1.x + 32) & -64); + pts->cur[n_points - 1].x = ((subg->pp2.x + 32) & -64); + } + + for ( k = 0; k < n_points; k++ ) + pts->touch[k] &= FT_Curve_Tag_On; + + cur_to_org( n_points, pts ); + + /* now consider hinting */ + if ( subg->is_hinted && n_ins > 0 ) + { + exec->is_composite = TRUE; + exec->pedantic_hinting = load_flags & FT_LOAD_PEDANTIC; + + error = TT_Run_Context( exec, debug ); + if ( error && exec->pedantic_hinting ) + return error; + } + + /* save glyph origin and advance points */ + subg->pp1 = pts->cur[n_points - 2]; + subg->pp2 = pts->cur[n_points - 1]; + + return TT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Init_Glyph_Component */ + /* */ + /* */ + /* Initializes a glyph component for further processing. */ + /* */ + static + void Init_Glyph_Component( TT_SubGlyphRec* element, + TT_SubGlyphRec* original, + TT_ExecContext exec ) + { + element->index = -1; + element->is_scaled = FALSE; + element->is_hinted = FALSE; + + if ( original ) + mount_zone( &original->zone, &element->zone ); + else + element->zone = exec->pts; + + element->zone.n_contours = 0; + element->zone.n_points = 0; + + element->arg1 = 0; + element->arg2 = 0; + + element->element_flag = 0; + element->preserve_pps = FALSE; + + element->transform.xx = 1 << 16; + element->transform.xy = 0; + element->transform.yx = 0; + element->transform.yy = 1 << 16; + + element->transform.ox = 0; + element->transform.oy = 0; + + element->left_bearing = 0; + element->advance = 0; + } + + + /*************************************************************************/ + /* */ + /* */ + /* 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). */ + /* */ + /* result :: A set of bit flags indicating the type of data that */ + /* was loaded in the glyph slot (outline or bitmap, */ + /* etc). */ + /* */ + /* You can set this field to 0 if you don't want this */ + /* information. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + TT_Error TT_Load_Glyph( TT_Size size, + TT_GlyphSlot glyph, + TT_UShort glyph_index, + TT_UInt load_flags ) + { + typedef enum TPhases_ + { + Load_Exit, + Load_Glyph, + Load_Header, + Load_Simple, + Load_Composite, + Load_End + + } TPhases; + + TT_Error error = 0; + FT_Stream stream; + + TT_Face face; + + TT_UShort num_points; + TT_Short num_contours; + TT_UShort left_points; + TT_Short left_contours; + + TT_ULong load_top; + TT_Long k, l; + TT_Int new_flags; + TT_UShort index; + TT_UShort u; + TT_Long count; + + TT_Long glyph_offset, offset; + + TT_F26Dot6 x, y, nx, ny; + + TT_Fixed xx, xy, yx, yy; + TT_BBox bbox; + + TT_ExecContext exec; + + TT_SubGlyphRec *subglyph, *subglyph2; + + TT_GlyphZone base_pts; + + TPhases phase; + TT_Byte* widths; + + SFNT_Interface* sfnt; + + /* first of all, check arguments */ + if ( !glyph ) + return TT_Err_Invalid_Glyph_Handle; + + face = (TT_Face)glyph->face; + if ( !face ) + return TT_Err_Invalid_Glyph_Handle; + + sfnt = (SFNT_Interface*)face->sfnt; + stream = face->root.stream; + count = 0; + + if ( glyph_index >= face->root.num_glyphs ) + return TT_Err_Invalid_Glyph_Index; + + if ( !size || (load_flags & FT_LOAD_NO_SCALE) ) + { + size = NULL; + load_flags |= FT_LOAD_NO_SCALE | + FT_LOAD_NO_HINTING | + FT_LOAD_NO_BITMAP; + } + + /* 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, + stream, + &glyph->bitmap, + &metrics ); + if ( !error ) + { + glyph->outline.n_points = 0; + glyph->outline.n_contours = 0; + + glyph->metrics.width = (TT_Pos)metrics.width << 6; + glyph->metrics.height = (TT_Pos)metrics.height << 6; + + glyph->metrics.horiBearingX = (TT_Pos)metrics.horiBearingX << 6; + glyph->metrics.horiBearingY = (TT_Pos)metrics.horiBearingY << 6; + glyph->metrics.horiAdvance = (TT_Pos)metrics.horiAdvance << 6; + + glyph->metrics.vertBearingX = (TT_Pos)metrics.vertBearingX << 6; + glyph->metrics.vertBearingY = (TT_Pos)metrics.vertBearingY << 6; + glyph->metrics.vertAdvance = (TT_Pos)metrics.vertAdvance << 6; + + glyph->format = ft_glyph_format_bitmap; + return error; + } + } + + if ( load_flags & FT_LOAD_NO_OUTLINE ) + return ( error ? error : TT_Err_Unavailable_Bitmap ); + + error = face->goto_table( face, TTAG_glyf, stream, 0 ); + if (error) + { + FT_ERROR(( "TT.GLoad: could not access glyph table\n" )); + return error; + } + + glyph_offset = FILE_Pos(); + + /* query new execution context */ + + if ( size && size->debug ) + exec = size->context; + else + exec = TT_New_Context( face ); + + if ( !exec ) + return TT_Err_Could_Not_Find_Context; + + TT_Load_Context( exec, face, size ); + + if ( size ) + { + /* load default graphics state - if needed */ + if ( size->GS.instruct_control & 2 ) + exec->GS = tt_default_graphics_state; + + glyph->outline.high_precision = ( size->root.metrics.y_ppem < 24 ); + } + + /* save its critical pointers, as they'll be modified during load */ + base_pts = exec->pts; + + /* init variables */ + left_points = face->root.max_points; /* remove phantom points */ + left_contours = face->root.max_contours; + + num_points = 0; + num_contours = 0; + + load_top = 0; + subglyph = exec->loadStack; + + Init_Glyph_Component( subglyph, NULL, exec ); + + subglyph->index = glyph_index; + subglyph->is_hinted = !(load_flags & FT_LOAD_NO_HINTING); + + /* when the cvt program has disabled hinting, the argument */ + /* is ignored. */ + if ( size && (size->GS.instruct_control & 1) ) + subglyph->is_hinted = FALSE; + + /* Main loading loop */ + + phase = Load_Glyph; + index = 0; + + while ( phase != Load_Exit ) + { + subglyph = exec->loadStack + load_top; + + switch ( phase ) + { + + /************************************************************/ + /* */ + /* Load_Glyph state */ + /* */ + /* reading a glyph's generic data, checking whether the */ + /* glyph is cached already (not implemented yet) */ + /* */ + /* exit states: Load_Header and Load_End */ + /* */ + case Load_Glyph: + /* check glyph index and table */ + + index = (TT_UInt)subglyph->index; + if ( index >= face->root.num_glyphs ) + { + error = TT_Err_Invalid_Glyph_Index; + goto Fail; + } + + /* get horizontal metrics */ + { + TT_Short left_bearing; + TT_UShort advance_width; + + + Get_HMetrics( face, index, TRUE, + &left_bearing, + &advance_width ); + + subglyph->left_bearing = left_bearing; + subglyph->advance = advance_width; + } + + phase = Load_Header; + break; + + /************************************************************/ + /* */ + /* Load_Header state */ + /* */ + /* reading a glyph's generic header to determine whether */ + /* it is a simple or composite glyph */ + /* */ + /* exit states: Load_Simple and Load_Composite */ + /* */ + case Load_Header: + /* load glyph */ + + offset = face->glyph_locations[index]; + count = 0; + if (index < face->num_locations-1) + count = face->glyph_locations[index+1] - offset; + + if ( index < ( face->num_locations - 1 ) && count == 0 ) + { + /* as described by Frederic Loyer, these are spaces, and */ + /* not the unknown glyph. */ + + num_contours = 0; + num_points = 0; + + subglyph->bbox.xMin = 0; + subglyph->bbox.xMax = 0; + subglyph->bbox.yMin = 0; + subglyph->bbox.yMax = 0; + + subglyph->pp1.x = 0; + subglyph->pp2.x = subglyph->advance; + + if ( !(load_flags & FT_LOAD_NO_SCALE) ) + subglyph->pp2.x = SCALE_X( subglyph->pp2.x ); + + exec->glyphSize = 0; + phase = Load_End; + break; + } + + offset = glyph_offset + offset; + + /* read first glyph header */ + if ( FILE_Seek( offset ) || + ACCESS_Frame( 10L ) ) + goto Fail_File; + + num_contours = GET_Short(); + + subglyph->bbox.xMin = GET_Short(); + subglyph->bbox.yMin = GET_Short(); + subglyph->bbox.xMax = GET_Short(); + subglyph->bbox.yMax = GET_Short(); + + FORGET_Frame(); + + FT_TRACE6(( "Glyph %ld\n", index )); + FT_TRACE6(( " # of contours : %d\n", num_contours )); + FT_TRACE6(( " xMin: %4d xMax: %4d\n", + subglyph->bbox.xMin, + subglyph->bbox.xMax )); + FT_TRACE6(( " yMin: %4d yMax: %4d\n", + subglyph->bbox.yMin, + subglyph->bbox.yMax )); + FT_TRACE6(( "-" )); + + count -= 10; + + if ( num_contours > left_contours ) + { + FT_TRACE0(( "ERROR: Too many contours for glyph %ld\n", index )); + error = TT_Err_Too_Many_Contours; + goto Fail; + } + + subglyph->pp1.x = subglyph->bbox.xMin - subglyph->left_bearing; + subglyph->pp1.y = 0; + subglyph->pp2.x = subglyph->pp1.x + subglyph->advance; + if (!(load_flags & FT_LOAD_NO_SCALE)) + { + subglyph->pp1.x = SCALE_X( subglyph->pp1.x ); + subglyph->pp2.x = SCALE_X( subglyph->pp2.x ); + } + + /* is it a simple glyph ? */ + if ( num_contours > 0 ) + phase = Load_Simple; + else + phase = Load_Composite; + + break; + + /************************************************************/ + /* */ + /* Load_Simple state */ + /* */ + /* reading a simple glyph (num_contours must be set to */ + /* the glyph's number of contours.) */ + /* */ + /* exit state: Load_End */ + /* */ + case Load_Simple: + new_flags = load_flags; + + /* disable hinting when scaling */ + if ( !subglyph->is_hinted ) + new_flags |= FT_LOAD_NO_HINTING; + + error = Load_Simple_Glyph( exec, + stream, + count, + num_contours, + left_contours, + left_points, + new_flags, + subglyph, + (TT_Bool)(size && size->debug && + load_top == 0) ); + if ( error ) + goto Fail; + + /* Note: We could have put the simple loader source there */ + /* but the code is fat enough already :-) */ + + num_points = exec->pts.n_points - 2; + + phase = Load_End; + + break; + + /************************************************************/ + /* */ + /* Load_Composite state */ + /* */ + /* reading a composite glyph header and pushing a new */ + /* load element on the stack. */ + /* */ + /* exit state: Load_Glyph */ + /* */ + case Load_Composite: + + /* create a new element on the stack */ + load_top++; + + if ( load_top > face->max_components ) + { + error = TT_Err_Invalid_Composite; + goto Fail; + } + + subglyph2 = exec->loadStack + load_top; + + Init_Glyph_Component( subglyph2, subglyph, NULL ); + subglyph2->is_hinted = subglyph->is_hinted; + + /* now read composite header */ + + if ( ACCESS_Frame( 4L ) ) + goto Fail_File; + + subglyph->element_flag = new_flags = GET_UShort(); + + subglyph2->index = GET_UShort(); + + FORGET_Frame(); + + k = 1+1; + + if ( new_flags & ARGS_ARE_WORDS ) + k *= 2; + + if ( new_flags & WE_HAVE_A_SCALE ) + k += 2; + + else if ( new_flags & WE_HAVE_AN_XY_SCALE ) + k += 4; + + else if ( new_flags & WE_HAVE_A_2X2 ) + k += 8; + + if ( ACCESS_Frame( k ) ) + goto Fail_File; + + if ( new_flags & ARGS_ARE_WORDS ) + { + k = GET_Short(); + l = GET_Short(); + } + else + { + k = GET_Char(); + l = GET_Char(); + } + + subglyph->arg1 = k; + subglyph->arg2 = l; + + if ( new_flags & ARGS_ARE_XY_VALUES ) + { + subglyph->transform.ox = k; + subglyph->transform.oy = l; + } + + xx = 1 << 16; + xy = 0; + yx = 0; + yy = 1 << 16; + + if ( new_flags & WE_HAVE_A_SCALE ) + { + xx = (TT_Fixed)GET_Short() << 2; + yy = xx; + subglyph2->is_scaled = TRUE; + } + else if ( new_flags & WE_HAVE_AN_XY_SCALE ) + { + xx = (TT_Fixed)GET_Short() << 2; + yy = (TT_Fixed)GET_Short() << 2; + subglyph2->is_scaled = TRUE; + } + else if ( new_flags & WE_HAVE_A_2X2 ) + { + xx = (TT_Fixed)GET_Short() << 2; + xy = (TT_Fixed)GET_Short() << 2; + yx = (TT_Fixed)GET_Short() << 2; + yy = (TT_Fixed)GET_Short() << 2; + subglyph2->is_scaled = TRUE; + } + + FORGET_Frame(); + + subglyph->transform.xx = xx; + subglyph->transform.xy = xy; + subglyph->transform.yx = yx; + subglyph->transform.yy = yy; + + k = FT_MulFix( xx, yy ) - FT_MulFix( xy, yx ); + + /* disable hinting in case of scaling/slanting */ + if ( ABS( k ) != (1 << 16) ) + subglyph2->is_hinted = FALSE; + + subglyph->file_offset = FILE_Pos(); + + phase = Load_Glyph; + + break; + + /************************************************************/ + /* */ + /* Load_End state */ + /* */ + /* after loading a glyph, apply transformation and offset */ + /* where necessary, pop element and continue or stop */ + /* process. */ + /* */ + /* exit states: Load_Composite and Load_Exit */ + /* */ + case Load_End: + if ( load_top > 0 ) + { + subglyph2 = subglyph; + + load_top--; + subglyph = exec->loadStack + load_top; + + /* check advance width and left side bearing */ + + if ( !subglyph->preserve_pps && + subglyph->element_flag & USE_MY_METRICS ) + { + subglyph->left_bearing = subglyph2->left_bearing; + subglyph->advance = subglyph2->advance; + + subglyph->pp1 = subglyph2->pp1; + subglyph->pp2 = subglyph2->pp2; + + subglyph->preserve_pps = TRUE; + } + + /* apply scale */ + + if ( subglyph2->is_scaled ) + { + TT_Vector* cur = subglyph2->zone.cur; + TT_Vector* org = subglyph2->zone.org; + + + for ( u = 0; u < num_points; u++ ) + { + nx = FT_MulFix( cur->x, subglyph->transform.xx ) + + FT_MulFix( cur->y, subglyph->transform.yx ); + + ny = FT_MulFix( cur->x, subglyph->transform.xy ) + + FT_MulFix( cur->y, subglyph->transform.yy ); + + cur->x = nx; + cur->y = ny; + + nx = FT_MulFix( org->x, subglyph->transform.xx ) + + FT_MulFix( org->y, subglyph->transform.yx ); + + ny = FT_MulFix( org->x, subglyph->transform.xy ) + + FT_MulFix( org->y, subglyph->transform.yy ); + + org->x = nx; + org->y = ny; + + cur++; + org++; + } + } + + /* adjust counts */ + + for ( k = 0; k < num_contours; k++ ) + subglyph2->zone.contours[k] += subglyph->zone.n_points; + + subglyph->zone.n_points += num_points; + subglyph->zone.n_contours += num_contours; + + left_points -= num_points; + left_contours -= num_contours; + + /* apply offset */ + + if ( !(subglyph->element_flag & ARGS_ARE_XY_VALUES) ) + { + k = subglyph->arg1; + l = subglyph->arg2; + + if ( k >= subglyph->zone.n_points || + l >= num_points ) + { + error = TT_Err_Invalid_Composite; + goto Fail; + } + + l += subglyph->zone.n_points; + + x = subglyph->zone.cur[k].x - subglyph->zone.cur[l].x; + y = subglyph->zone.cur[k].y - subglyph->zone.cur[l].y; + } + else + { + x = subglyph->transform.ox; + y = subglyph->transform.oy; + + if (!(load_flags & FT_LOAD_NO_SCALE)) + { + x = SCALE_X( x ); + y = SCALE_Y( y ); + } + } + + if ( subglyph->element_flag & ROUND_XY_TO_GRID ) + { + x = (x + 32) & -64; + y = (y + 32) & -64; + } + + translate_array( num_points, subglyph2->zone.cur, x, y ); + + cur_to_org( num_points, &subglyph2->zone ); + + num_points = subglyph->zone.n_points; + num_contours = subglyph->zone.n_contours; + + /* check for last component */ + + if ( FILE_Seek( subglyph->file_offset ) ) + goto Fail_File; + + if ( subglyph->element_flag & MORE_COMPONENTS ) + phase = Load_Composite; + else + { + error = Load_Composite_End( num_points, + num_contours, + exec, + subglyph, + stream, + load_flags, + (TT_Bool)(size && size->debug && + load_top == 0) ); + if ( error ) + goto Fail; + + phase = Load_End; + } + } + else + phase = Load_Exit; + + break; + + case Load_Exit: + break; + } + } + + /* finally, copy the points arrays to the glyph object */ + + exec->pts = base_pts; + + for ( u = 0; u < num_points; u++ ) + { + glyph->outline.points[u] = exec->pts.cur[u]; + glyph->outline.flags [u] = exec->pts.touch[u]; + } + + for ( k = 0; k < num_contours; k++ ) + glyph->outline.contours[k] = exec->pts.contours[k]; + + glyph->outline.n_points = num_points; + glyph->outline.n_contours = num_contours; + glyph->outline.second_pass = TRUE; + + /* translate array so that (0,0) is the glyph's origin */ + translate_array( num_points, glyph->outline.points, + -subglyph->pp1.x, 0 ); + + FT_Get_Outline_CBox( &glyph->outline, &bbox ); + + if ( subglyph->is_hinted ) + { + /* grid-fit the bounding box */ + bbox.xMin &= -64; + bbox.yMin &= -64; + bbox.xMax = (bbox.xMax + 63) & -64; + bbox.yMax = (bbox.yMax + 63) & -64; + } + + /* get the device-independent scaled horizontal metrics */ + /* take care of fixed-pitch fonts... */ + { + TT_Pos left_bearing; + TT_Pos advance; + + + left_bearing = subglyph->left_bearing; + advance = subglyph->advance; + + if ( face->postscript.isFixedPitch ) + advance = face->horizontal.advance_Width_Max; + + if ( !(load_flags & FT_LOAD_NO_SCALE) ) + { + left_bearing = SCALE_X( left_bearing ); + advance = SCALE_X( advance ); + } + + glyph->metrics2.horiBearingX = left_bearing; + glyph->metrics2.horiAdvance = advance; + } + + glyph->metrics.horiBearingX = bbox.xMin; + glyph->metrics.horiBearingY = bbox.yMax; + glyph->metrics.horiAdvance = subglyph->pp2.x - subglyph->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'... */ + + { + TT_Short top_bearing; /* vertical top side bearing (EM units) */ + TT_UShort advance_height; /* vertical advance height (EM units) */ + + TT_Pos left; /* scaled vertical left side bearing */ + TT_Pos top; /* scaled vertical top side bearing */ + TT_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, when 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 = (TT_UShort)(face->os2.sTypoAscender - + face->os2.sTypoDescender + + face->os2.sTypoLineGap); + } + else + { + top_bearing = face->horizontal.Line_Gap / 2; + advance_height = (TT_UShort)(face->horizontal.Ascender + + face->horizontal.Descender + + face->horizontal.Line_Gap); + } + } + + /* scale the metrics */ + if ( !(load_flags & FT_LOAD_NO_SCALE) ) + { + top = SCALE_Y( top_bearing ); + advance = SCALE_X( advance_height ); + } + else + { + top = top_bearing; + advance = advance_height; + } + + glyph->metrics2.vertBearingY = top; + glyph->metrics2.vertAdvance = advance; + + /* 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 ( subglyph->is_hinted ) + { + 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 ( !exec->face->postscript.isFixedPitch && size && + subglyph->is_hinted ) + { + widths = Get_Advance_Widths( exec->face, + exec->size->root.metrics.x_ppem ); + if ( widths ) + glyph->metrics.horiAdvance = widths[glyph_index] << 6; + } + + glyph->outline.dropout_mode = (TT_Char)exec->GS.scan_type; + + /* set glyph dimensions */ + glyph->metrics.width = bbox.xMax - bbox.xMin; + glyph->metrics.height = bbox.yMax - bbox.yMin; + + glyph->format = ft_glyph_format_outline; + + error = TT_Err_Ok; + + Fail_File: + Fail: + + /* reset the execution context */ + exec->pts = base_pts; + + if ( !size || !size->debug ) + TT_Done_Context( exec ); + + return error; + } + + +/* END */ diff --git a/src/truetype/ttgload.h b/src/truetype/ttgload.h new file mode 100644 index 000000000..d544cee85 --- /dev/null +++ b/src/truetype/ttgload.h @@ -0,0 +1,109 @@ +/***************************************************************************/ +/* */ +/* ttgload.h */ +/* */ +/* TrueType Glyph Loader (specification). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef TTGLOAD_H +#define TTGLOAD_H + +#include + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /* */ + /* */ + /* 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_DEF + void TT_Get_Metrics( TT_HoriHeader* header, + TT_UShort index, + TT_Short* bearing, + TT_UShort* advance ); + + + /*************************************************************************/ + /* */ + /* */ + /* 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). */ + /* */ + /* result :: A set of bit flags indicating the type of data that */ + /* was loaded in the glyph slot (outline or bitmap, */ + /* etc). */ + /* */ + /* You can set this field to 0 if you don't want this */ + /* information. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_DEF + TT_Error TT_Load_Glyph( TT_Size size, + TT_GlyphSlot glyph, + TT_UShort glyph_index, + TT_UInt load_flags ); + +#ifdef __cplusplus + } +#endif + + +#endif /* TTGLOAD_H */ + + +/* END */ diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c new file mode 100644 index 000000000..c9be4f21e --- /dev/null +++ b/src/truetype/ttinterp.c @@ -0,0 +1,7954 @@ +/***************************************************************************/ +/* */ +/* ttinterp.c */ +/* */ +/* TrueType bytecode intepreter (body). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 + +#define TT_MULFIX FT_MulFix +#define TT_MULDIV FT_MulDiv + +#define TT_INT64 FT_Int64 + +/* required by the tracing mode */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_ttinterp + + + /*************************************************************************/ + /* */ + /* 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 limited */ + /* to a maximum number of opcodes defined below. */ + /* */ +#define MAX_RUNNABLE_OPCODES 1000000 + + + /*************************************************************************/ + /* */ + /* 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 */ + + + /*************************************************************************/ + /* */ + /* Most of FreeType builds don't use engine compensations. We thus */ + /* introduce a macro, FT_CONFIG_OPTION_INTERPRETER_QUICK, which controls */ + /* the use of these values. */ + /* */ +#define INS_ARG EXEC_OP_ TT_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 UNUSED_EXEC (void)CUR + + + /*************************************************************************/ + /* */ + /* This macro is used whenever `args' is unused in a function, to avoid */ + /* stupid warnings from pedantic compilers. */ + /* */ +#define UNUSED_ARG UNUSED_EXEC; (void)args; + + + /*************************************************************************/ + /* */ + /* The following macros hide the use of EXEC_ARG and EXEC_ARG_ to */ + /* increase readabiltyof 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 ) ((TT_UInt)(x) >= (TT_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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + EXPORT_FUNC + TT_Error TT_Goto_CodeRange( TT_ExecContext exec, + TT_Int range, + TT_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( (TT_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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + EXPORT_FUNC + TT_Error TT_Set_CodeRange( TT_ExecContext exec, + TT_Int range, + void* base, + TT_Long length ) + { + FT_Assert( range >= 1 && range <= 3 ); + + exec->codeRangeTable[range - 1].base = (TT_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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + /* */ + /* Does not set the Error variable. */ + /* */ + EXPORT_FUNC + TT_Error TT_Clear_CodeRange( TT_ExecContext exec, + TT_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. */ + /* system :: A handle to the parent system object. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + /* */ + /* Only the glyph loader and debugger should call this function. */ + /* */ + LOCAL_FUNC + TT_Error TT_Destroy_Context( TT_ExecContext exec, + FT_Memory memory ) + { + /* free composite load stack */ + FREE( exec->loadStack ); + exec->loadSize = 0; + + /* points zone */ + TT_Done_GlyphZone( exec->memory, &exec->pts ); + 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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + static + TT_Error Init_Context( TT_ExecContext exec, + TT_Face face, + FT_Memory memory ) + { + TT_Error error; + + + FT_TRACE1(( "TT.Create_Create: new object at 0x%08lx, parent = 0x%08lx\n", + (long)exec, (long)face )); + + /* XXX: We don't reserve arrays anymore, this is done automatically */ + /* during a call to Context_Load(). */ + + 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(( "TT.Context_Create: not enough memory for 0x%08lx\n", + (long)exec )); + TT_Destroy_Context( exec, memory ); + + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Update_Max */ + /* */ + /* */ + /* Checks the size of a buffer and reallocates it if necessary. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + static + TT_Error Update_Max( FT_Memory memory, + TT_ULong* size, + TT_Long multiplier, + void** buff, + TT_ULong new_max ) + { + TT_Error error; + + + if ( *size < new_max ) + { + FREE( *buff ); + if ( ALLOC( *buff, new_max * multiplier ) ) + return error; + *size = new_max; + } + + return TT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Update_Zone */ + /* */ + /* */ + /* Checks the size of a zone and reallocates it if necessary. */ + /* */ + /* */ + /* newPoints :: The new capacity for points. We add two slots for */ + /* phantom points. */ + /* */ + /* newContours :: The new capacity for contours. */ + /* */ + /* */ + /* zone :: The address of the target zone. */ + /* */ + /* maxPoints :: The address of the zone's current capacity for */ + /* points. */ + /* */ + /* maxContours :: The address of the zone's current capacity for */ + /* contours. */ + /* */ + static + TT_Error Update_Zone( FT_Memory memory, + TT_GlyphZone* zone, + TT_UShort* maxPoints, + TT_Short* maxContours, + TT_UShort newPoints, + TT_Short newContours ) + { + newPoints += 2; + + if ( *maxPoints < newPoints || *maxContours < newContours ) + { + TT_Error error; + + + TT_Done_GlyphZone( memory, zone ); + + error = TT_New_GlyphZone( memory, zone, newPoints, newContours ); + if ( error ) + return error; + + *maxPoints = newPoints; + *maxContours = newContours; + } + + 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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + /* */ + /* Only the glyph loader and debugger should call this function. */ + /* */ + EXPORT_FUNC + TT_Error TT_Load_Context( TT_ExecContext exec, + TT_Face face, + TT_Size size ) + { + TT_Int i; + TT_ULong tmp; + TT_MaxProfile* maxp; + TT_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 ( TT_F26Dot6 ), + (void**)&exec->stack, + maxp->maxStackElements + 32 ); + exec->stackSize = (TT_UInt)tmp; + if ( error ) + return error; + + tmp = exec->glyphSize; + error = Update_Max( exec->memory, + &tmp, + sizeof ( TT_Byte ), + (void**)&exec->glyphIns, + maxp->maxSizeOfInstructions ); + exec->glyphSize = (TT_UShort)tmp; + if ( error ) + return error; + + /* XXX: Update_Zone() reserves two positions for the phantom points! */ + error = Update_Zone( exec->memory, + &exec->pts, + &exec->maxPoints, + &exec->maxContours, + exec->face->root.max_points, + exec->face->root.max_contours ); + 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. */ + /* */ + /* */ + /* ins :: A handle to the target size object. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + /* */ + /* Only the glyph loader and debugger should call this function. */ + /* */ + EXPORT_FUNC + TT_Error TT_Save_Context( TT_ExecContext exec, + TT_Size size ) + { + TT_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. */ + /* */ + /* */ + /* exec :: A handle to the target execution context. */ + /* */ + /* */ + /* TrueTyoe error code. 0 means success. */ + /* */ + /* */ + /* Only the glyph loader and debugger should call this function. */ + /* */ + EXPORT_FUNC + TT_Error TT_Run_Context( TT_ExecContext exec, + TT_Bool debug ) + { + TT_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 + return exec->face->interpreter( exec ); +#else + if ( !debug ) + return TT_RunIns( exec ); + else + return TT_Err_Ok; +#endif + } + + + LOCAL_FUNC + 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. */ + /* */ + EXPORT_FUNC + TT_ExecContext TT_New_Context( TT_Face face ) + { + TT_Driver driver = (TT_Driver)face->root.driver; + TT_ExecContext exec; + FT_Memory memory = driver->root.memory; + + + exec = driver->context; + + if ( !driver->context ) + { + TT_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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + /* */ + /* Only the glyph loader and debugger should call this function. */ + /* */ + EXPORT_FUNC + TT_Error TT_Done_Context( TT_ExecContext exec ) + { + /* Nothing at all for now */ + UNUSED( exec ); + + return TT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* 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 TT_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 TT_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 TT_Vector Null_Vector = {0,0}; + + +#undef PACK + + +#undef NULL_Vector +#define NULL_Vector (TT_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 + TT_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 + { + TT_Long x, y; +#if 0 + 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 + } + + return CUR.tt_metrics.ratio; + } + + + static + TT_Long Current_Ppem( EXEC_OP ) + { + return TT_MULFIX( CUR.tt_metrics.ppem, CURRENT_Ratio() ); + } + + + /*************************************************************************/ + /* */ + /* Functions related to the control value table (CVT). */ + /* */ + /*************************************************************************/ + + + static + TT_F26Dot6 Read_CVT( EXEC_OP_ TT_ULong index ) + { + return CUR.cvt[index]; + } + + + static + TT_F26Dot6 Read_CVT_Stretched( EXEC_OP_ TT_ULong index ) + { + return TT_MULFIX( CUR.cvt[index], CURRENT_Ratio() ); + } + + + static + void Write_CVT( EXEC_OP_ TT_ULong index, + TT_F26Dot6 value ) + { + CUR.cvt[index] = value; + } + + static + void Write_CVT_Stretched( EXEC_OP_ TT_ULong index, + TT_F26Dot6 value ) + { + CUR.cvt[index] = FT_DivFix( value, CURRENT_Ratio() ); + } + + + static + void Move_CVT( EXEC_OP_ TT_ULong index, + TT_F26Dot6 value ) + { + CUR.cvt[index] += value; + } + + + static + void Move_CVT_Stretched( EXEC_OP_ TT_ULong index, + TT_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 TT_Short GetShortIns( EXEC_OP ) + { + /* Reading a byte stream so there is no endianess (DaveP) */ + CUR.IP += 2; + return (TT_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 + TT_Bool Ins_Goto_CodeRange( EXEC_OP_ TT_Int aRange, + TT_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, + TT_UShort point, + TT_F26Dot6 distance ) + { + TT_F26Dot6 v; + + + v = CUR.GS.freeVector.x; + + if ( v != 0 ) + { + zone->cur[point].x += TT_MULDIV( distance, + v * 0x10000L, + CUR.F_dot_P ); + + zone->touch[point] |= FT_Curve_Tag_Touch_X; + } + + v = CUR.GS.freeVector.y; + + if ( v != 0 ) + { + zone->cur[point].y += TT_MULDIV( distance, + v * 0x10000L, + CUR.F_dot_P ); + + zone->touch[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% cases. */ + /* */ + /*************************************************************************/ + + static + void Direct_Move_X( EXEC_OP_ TT_GlyphZone* zone, + TT_UShort point, + TT_F26Dot6 distance ) + { + UNUSED_EXEC; + + zone->cur[point].x += distance; + zone->touch[point] |= FT_Curve_Tag_Touch_X; + } + + + static + void Direct_Move_Y( EXEC_OP_ TT_GlyphZone* zone, + TT_UShort point, + TT_F26Dot6 distance ) + { + UNUSED_EXEC; + + zone->cur[point].y += distance; + zone->touch[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 + TT_F26Dot6 Round_None( EXEC_OP_ TT_F26Dot6 distance, + TT_F26Dot6 compensation ) + { + TT_F26Dot6 val; + + + 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 + TT_F26Dot6 Round_To_Grid( EXEC_OP_ TT_F26Dot6 distance, + TT_F26Dot6 compensation ) + { + TT_F26Dot6 val; + + + 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 + TT_F26Dot6 Round_To_Half_Grid( EXEC_OP_ TT_F26Dot6 distance, + TT_F26Dot6 compensation ) + { + TT_F26Dot6 val; + + + 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 + TT_F26Dot6 Round_Down_To_Grid( EXEC_OP_ TT_F26Dot6 distance, + TT_F26Dot6 compensation ) + { + TT_F26Dot6 val; + + + 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 + TT_F26Dot6 Round_Up_To_Grid( EXEC_OP_ TT_F26Dot6 distance, + TT_F26Dot6 compensation ) + { + TT_F26Dot6 val; + + + 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 + TT_F26Dot6 Round_To_Double_Grid( EXEC_OP_ TT_F26Dot6 distance, + TT_F26Dot6 compensation ) + { + TT_F26Dot6 val; + + 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 + TT_F26Dot6 Round_Super( EXEC_OP_ TT_F26Dot6 distance, + TT_F26Dot6 compensation ) + { + TT_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 + TT_F26Dot6 Round_Super_45( EXEC_OP_ TT_F26Dot6 distance, + TT_F26Dot6 compensation ) + { + TT_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_ TT_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_ TT_F26Dot6 GridPeriod, + TT_Long selector ) + { + switch ( (TT_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 ( (TT_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 = ( (TT_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 + TT_F26Dot6 Project( EXEC_OP_ TT_Vector* v1, + TT_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 + TT_F26Dot6 Dual_Project( EXEC_OP_ TT_Vector* v1, + TT_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 + TT_F26Dot6 Free_Project( EXEC_OP_ TT_Vector* v1, + TT_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 + TT_F26Dot6 Project_x( EXEC_OP_ TT_Vector* v1, + TT_Vector* v2 ) + { + 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 + TT_F26Dot6 Project_y( EXEC_OP_ TT_Vector* v1, + TT_Vector* v2 ) + { + 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 = (TT_Long)CUR.GS.projVector.x * CUR.GS.freeVector.x * 4 + + (TT_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. */ + /* */ + static + TT_Bool Normalize( EXEC_OP_ TT_F26Dot6 Vx, + TT_F26Dot6 Vy, + TT_UnitVector* R ) + { + TT_F26Dot6 u, v, d; + TT_Int shift; + TT_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're 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 = (TT_ULong)u >> 16; + lo = (TT_ULong)u & 0xFFFF; + med = hi*lo; + + H = hi*hi + (med >> 15); + med <<= 17; + L = lo*lo + med; + if (L < med) H++; + + hi = (TT_ULong)v >> 16; + lo = (TT_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 & 0xC0000000) == 0) + { + L <<= 2; + shift++; + } + + d = FT_Sqrt32(L); + R->x = (TT_F2Dot14)TT_MULDIV( Vx << shift, 0x4000, d ); + R->y = (TT_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 = (TT_F2Dot14)TT_MULDIV( Vx >> shift, 0x4000, d ); + R->y = (TT_F2Dot14)TT_MULDIV( Vy >> shift, 0x4000, d ); + } + + return SUCCESS; + } + + + /*************************************************************************/ + /* */ + /* Here we start with the implementation of the various opcodes. */ + /* */ + /*************************************************************************/ + + + static + TT_Bool Ins_SxVTL( EXEC_OP_ TT_UShort aIdx1, + TT_UShort aIdx2, + TT_Int aOpc, + TT_UnitVector* Vec ) + { + TT_Long A, B, C; + TT_Vector* p1; + TT_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; /* CounterClockwise 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're all defined there. */ + +#define DO_SVTCA \ + { \ + TT_Short A, B; \ + \ + \ + A = (TT_Short)(CUR.opcode & 1) << 14; \ + B = A ^ (TT_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 \ + { \ + TT_Short A, B; \ + \ + \ + A = (TT_Short)(CUR.opcode & 1) << 14; \ + B = A ^ (TT_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 \ + { \ + TT_Short A, B; \ + \ + \ + A = (TT_Short)(CUR.opcode & 1) << 14; \ + B = A ^ (TT_Short)0x4000; \ + \ + CUR.GS.freeVector.x = A; \ + CUR.GS.freeVector.y = B; \ + \ + COMPUTE_Funcs(); \ + } + + +#define DO_SPVTL \ + if ( INS_SxVTL( (TT_UShort)args[1], \ + (TT_UShort)args[0], \ + CUR.opcode, \ + &CUR.GS.projVector) == SUCCESS ) \ + { \ + CUR.GS.dualVector = CUR.GS.projVector; \ + COMPUTE_Funcs(); \ + } + + +#define DO_SFVTL \ + if ( INS_SxVTL( (TT_UShort)(args[1]), \ + (TT_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 \ + { \ + TT_Short S; \ + TT_Long X, Y; \ + \ + \ + /* Only use low 16bits, then sign extend */ \ + S = (TT_Short)args[1]; \ + Y = (TT_Long)S; \ + S = (TT_Short)args[0]; \ + X = (TT_Long)S; \ + \ + NORMalize( X, Y, &CUR.GS.projVector ); \ + \ + CUR.GS.dualVector = CUR.GS.projVector; \ + COMPUTE_Funcs(); \ + } + + +#define DO_SFVFS \ + { \ + TT_Short S; \ + TT_Long X, Y; \ + \ + \ + /* Only use low 16bits, then sign extend */ \ + S = (TT_Short)args[1]; \ + Y = (TT_Long)S; \ + S = (TT_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 = (TT_UShort)(args[0]); + + +#define DO_SRP1 \ + CUR.GS.rp1 = (TT_UShort)(args[0]); + + +#define DO_SRP2 \ + CUR.GS.rp2 = (TT_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 = (TT_F26Dot6)args[0]; + + +#define DO_SSWCI \ + CUR.GS.single_width_cutin = (TT_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 = (TT_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 = (TT_Short)args[0]; + + +#define DO_SDS \ + CUR.GS.delta_shift = (TT_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 + +#define DO_DUP \ + args[1] = args[0]; + + +#define DO_CLEAR \ + CUR.new_top = 0; + + +#define DO_SWAP \ + { \ + TT_Long L; \ + \ + L = args[0]; \ + args[0] = args[1]; \ + args[1] = L; \ + } + + +#define DO_DEPTH \ + args[0] = CUR.top; + + +#define DO_CINDEX \ + { \ + TT_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 \ + { \ + TT_ULong I = (TT_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 \ + { \ + TT_ULong I = (TT_ULong)args[0]; \ + \ + \ + if ( BOUNDS( I, CUR.storeSize ) ) \ + { \ + if ( CUR.pedantic_hinting ) \ + { \ + ARRAY_BOUND_ERROR; \ + } \ + } \ + else \ + CUR.storage[I] = args[1]; \ + } + + +#define DO_RCVT \ + { \ + TT_ULong I = (TT_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 \ + { \ + TT_ULong I = (TT_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 \ + { \ + TT_ULong I = (TT_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 top stack element */ + /* Opcode range: 0x20 */ + /* Stack: StkElt --> StkElt StkElt */ + /* */ + static + void Ins_DUP( INS_ARG ) + { + DO_DUP + } + + + /*************************************************************************/ + /* */ + /* POP[]: POP the stack's top elt */ + /* 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 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 ) + { + /* Intentional - 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 ) + { + TT_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 ( TT_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 ) + { + TT_Long A, B, C; + + + 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 specs' order. */ + /* */ + /*************************************************************************/ + + + static + TT_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 ) + { + TT_Int nIfs; + TT_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 ) + { + TT_Int nIfs; + + + 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 specs' order. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* FDEF[]: Function DEFinition */ + /* Opcode range: 0x2C */ + /* Stack: uint32 --> */ + /* */ + static + void Ins_FDEF( INS_ARG ) + { + TT_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; + + + 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: When 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's 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 ) + { + TT_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 ) + { + TT_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 = (TT_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 == (TT_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 ( (TT_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 specs' order. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* NPUSHB[]: PUSH N Bytes */ + /* Opcode range: 0x40 */ + /* Stack: --> uint32... */ + /* */ + static + void Ins_NPUSHB( INS_ARG ) + { + TT_UShort L, K; + + + L = (TT_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 ) + { + TT_UShort L, K; + + + L = (TT_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 ) + { + TT_UShort L, K; + + + L = (TT_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 ) + { + TT_UShort L, K; + + + L = (TT_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 ) + { + TT_ULong L; + TT_F26Dot6 R; + + + L = (TT_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 ) + { + TT_Long K; + TT_UShort L; + + + L = (TT_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 ) + { + TT_UShort K, L; + TT_F26Dot6 D; + + + K = (TT_UShort)args[1]; + L = (TT_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 ) + { + TT_Long A, B, C; + TT_UShort p1, p2; /* was TT_Int in pas type ERROR */ + + + p1 = (TT_UShort)args[1]; + p2 = (TT_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; + } + + { + TT_Vector* v1 = CUR.zp1.org + p2; + TT_Vector* v2 = CUR.zp2.org + p1; + + + A = v1->x - v2->x; + B = v1->y - v2->y; + } + + if ( (CUR.opcode & 1) != 0 ) + { + C = B; /* CounterClockwise rotation */ + B = A; + A = -C; + } + + NORMalize( A, B, &CUR.GS.dualVector ); + + { + TT_Vector* v1 = CUR.zp1.cur + p2; + TT_Vector* v2 = CUR.zp2.cur + p1; + + + A = v1->x - v2->x; + B = v1->y - v2->y; + } + + if ( (CUR.opcode & 1) != 0 ) + { + C = B; /* CounterClockwise 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 ( (TT_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 = (TT_UShort)(args[0]); + } + + + /*************************************************************************/ + /* */ + /* SZP1[]: Set Zone Pointer 1 */ + /* Opcode range: 0x14 */ + /* Stack: uint32 --> */ + /* */ + static + void Ins_SZP1( INS_ARG ) + { + switch ( (TT_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 = (TT_UShort)(args[0]); + } + + + /*************************************************************************/ + /* */ + /* SZP2[]: Set Zone Pointer 2 */ + /* Opcode range: 0x15 */ + /* Stack: uint32 --> */ + /* */ + static + void Ins_SZP2( INS_ARG ) + { + switch ( (TT_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 = (TT_UShort)(args[0]); + } + + + /*************************************************************************/ + /* */ + /* SZPS[]: Set Zone PointerS */ + /* Opcode range: 0x16 */ + /* Stack: uint32 --> */ + /* */ + static + void Ins_SZPS( INS_ARG ) + { + switch ( (TT_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 = (TT_UShort)(args[0]); + CUR.GS.gep1 = (TT_UShort)(args[0]); + CUR.GS.gep2 = (TT_UShort)(args[0]); + } + + + /*************************************************************************/ + /* */ + /* INSTCTRL[]: INSTruction ConTRoL */ + /* Opcode range: 0x8e */ + /* Stack: int32 int32 --> */ + /* */ + static + void Ins_INSTCTRL( INS_ARG ) + { + TT_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 = + (TT_Byte)( CUR.GS.instruct_control & ~(TT_Byte)K ) | (TT_Byte)L; + } + + + /*************************************************************************/ + /* */ + /* SCANCTRL[]: SCAN ConTRoL */ + /* Opcode range: 0x85 */ + /* Stack: uint32? --> */ + /* */ + static + void Ins_SCANCTRL( INS_ARG ) + { + TT_Int A; + + + /* Get Threshold */ + A = (TT_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 ( (args[0] & 0x100) != 0 && CUR.metrics.pointSize <= A ) + CUR.GS.scan_control = TRUE; + */ + + 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 ( (args[0] & 0x800) != 0 && CUR.metrics.pointSize > A ) + CUR.GS.scan_control = FALSE; + */ + + 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 = (TT_Int)args[0]; + } + } + + + /*************************************************************************/ + /* */ + /* MANAGING OUTLINES */ + /* */ + /* Instructions appear in the specs' order. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* FLIPPT[]: FLIP PoinT */ + /* Opcode range: 0x80 */ + /* Stack: uint32... --> */ + /* */ + static + void Ins_FLIPPT( INS_ARG ) + { + TT_UShort point; + + + UNUSED_ARG; + + if ( CUR.top < CUR.GS.loop ) + { + CUR.error = TT_Err_Too_Few_Arguments; + return; + } + + while ( CUR.GS.loop > 0 ) + { + CUR.args--; + + point = (TT_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.touch[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 ) + { + TT_UShort I, K, L; + + + K = (TT_UShort)args[1]; + L = (TT_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.touch[I] |= FT_Curve_Tag_On; + } + + + /*************************************************************************/ + /* */ + /* FLIPRGOFF: FLIP RanGe OFF */ + /* Opcode range: 0x82 */ + /* Stack: uint32 uint32 --> */ + /* */ + static + void Ins_FLIPRGOFF( INS_ARG ) + { + TT_UShort I, K, L; + + + K = (TT_UShort)args[1]; + L = (TT_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.touch[I] &= ~FT_Curve_Tag_On; + } + + + static + TT_Bool Compute_Point_Displacement( EXEC_OP_ TT_F26Dot6* x, + TT_F26Dot6* y, + TT_GlyphZone* zone, + TT_UShort* refp ) + { + TT_GlyphZone zp; + TT_UShort p; + TT_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 ); + + *x = TT_MULDIV( d, + (TT_Long)CUR.GS.freeVector.x * 0x10000L, + CUR.F_dot_P ); + *y = TT_MULDIV( d, + (TT_Long)CUR.GS.freeVector.y * 0x10000L, + CUR.F_dot_P ); + + return SUCCESS; + } + + + static + void Move_Zp2_Point( EXEC_OP_ TT_UShort point, + TT_F26Dot6 dx, + TT_F26Dot6 dy, + TT_Bool touch ) + { + if ( CUR.GS.freeVector.x != 0 ) + { + CUR.zp2.cur[point].x += dx; + if ( touch ) + CUR.zp2.touch[point] |= FT_Curve_Tag_Touch_X; + } + + if ( CUR.GS.freeVector.y != 0 ) + { + CUR.zp2.cur[point].y += dy; + if ( touch ) + CUR.zp2.touch[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; + TT_UShort refp; + + TT_F26Dot6 dx, + dy; + TT_UShort point; + + + 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 = (TT_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; + TT_UShort refp; + TT_F26Dot6 dx, + dy; + + TT_Short contour; + TT_UShort first_point, last_point, i; + + + contour = (TT_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; + TT_UShort refp; + TT_F26Dot6 dx, + dy; + + TT_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 ) + { + TT_F26Dot6 dx, dy; + TT_UShort point; + + + if ( CUR.top < CUR.GS.loop + 1 ) + { + CUR.error = TT_Err_Invalid_Reference; + return; + } + + dx = TT_MULDIV( args[0], + (TT_Long)CUR.GS.freeVector.x, + 0x4000 ); + dy = TT_MULDIV( args[0], + (TT_Long)CUR.GS.freeVector.y, + 0x4000 ); + + while ( CUR.GS.loop > 0 ) + { + CUR.args--; + + point = (TT_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 ) + { + TT_UShort point; + TT_F26Dot6 distance; + + + point = (TT_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 ) + { + TT_UShort point; + TT_F26Dot6 cur_dist, + distance; + + + point = (TT_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 ) + { + TT_ULong cvtEntry; + TT_UShort point; + TT_F26Dot6 distance, + org_dist; + + + cvtEntry = (TT_ULong)args[1]; + point = (TT_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 */ + /* specs :) */ + /* */ + /* 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 ) + { + TT_UShort point; + TT_F26Dot6 org_dist, distance; + + + point = (TT_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 ) + { + TT_UShort point; + TT_ULong cvtEntry; + + TT_F26Dot6 cvt_dist, + distance, + cur_dist, + org_dist; + + + point = (TT_UShort)args[0]; + cvtEntry = (TT_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 ) + { + TT_UShort point; + TT_F26Dot6 distance; + + + 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 = (TT_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 ) + { + TT_UShort point, + a0, a1, + b0, b1; + + TT_F26Dot6 discriminant; + + TT_F26Dot6 dx, dy, + dax, day, + dbx, dby; + + TT_F26Dot6 val; + + TT_Vector R; + + + point = (TT_UShort)args[0]; + + a0 = (TT_UShort)args[1]; + a1 = (TT_UShort)args[2]; + b0 = (TT_UShort)args[3]; + b1 = (TT_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.touch[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 ) + { + TT_UShort p1, p2; + TT_F26Dot6 distance; + + + p1 = (TT_UShort)args[0]; + p2 = (TT_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 ) + { + TT_F26Dot6 org_a, org_b, org_x, + cur_a, cur_b, cur_x, + distance; + TT_UShort point; + + + 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 = (TT_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 ) + { + TT_UShort point; + TT_Byte mask; + + + point = (TT_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.touch[point] &= mask; + } + + + /* Local variables for Ins_IUP: */ + struct LOC_Ins_IUP + { + TT_Vector* orgs; /* original and current coordinate */ + TT_Vector* curs; /* arrays */ + }; + + + static void Shift( TT_UInt p1, + TT_UInt p2, + TT_UInt p, + struct LOC_Ins_IUP* LINK ) + { + TT_UInt i; + TT_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( TT_UInt p1, + TT_UInt p2, + TT_UInt ref1, + TT_UInt ref2, + struct LOC_Ins_IUP* LINK ) + { + TT_UInt i; + TT_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; + TT_Byte mask; + + TT_UInt first_point; /* first point of contour */ + TT_UInt end_point; /* end point (last+1) of contour */ + + TT_UInt first_touched; /* first touched point in contour */ + TT_UInt cur_touched; /* current touched point in contour */ + + TT_UInt point; /* current point */ + TT_Short contour; /* current contour */ + + + 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 = (TT_Vector*)( ((TT_F26Dot6*)CUR.pts.org) + 1 ); + V.curs = (TT_Vector*)( ((TT_F26Dot6*)CUR.pts.cur) + 1 ); + } + + contour = 0; + point = 0; + + do + { + end_point = CUR.pts.contours[contour]; + first_point = point; + + while ( point <= end_point && (CUR.pts.touch[point] & mask) == 0 ) + point++; + + if ( point <= end_point ) + { + first_touched = point; + cur_touched = point; + + point++; + + while ( point <= end_point ) + { + if ( (CUR.pts.touch[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( (TT_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 ) + { + TT_ULong k, nump; + TT_UShort A; + TT_ULong C; + TT_Long B; + + + nump = (TT_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 = (TT_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 = ((TT_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() == (TT_Long)C ) + { + B = ((TT_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 ) + { + TT_ULong nump, k; + TT_ULong A, C; + TT_Long B; + + + nump = (TT_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 = (TT_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 = ((TT_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() == (TT_Long)C ) + { + B = ((TT_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 ) + { + TT_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; + + 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 specs' order. */ + /* */ + /*************************************************************************/ + + + EXPORT_FUNC +#ifndef DEBUG_INTERPRETER + TT_Error TT_RunIns( TT_ExecContext exc ) +#else + TT_Error TT_RunIns2( TT_ExecContext exc ) +#endif + { + TT_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( (TT_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 + { + TT_Long* args = CUR.stack + CUR.args; + TT_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 */ + { + TT_Short AA, BB; + + + AA = (TT_Short)(opcode & 1) << 14; + BB = AA ^ (TT_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 + 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_; +/* break; Unreachable code warning suppress. Leave in case a later + change to remind the editor to consider break; */ + + default: + goto LErrorLabel_; +/* break; */ + } + } + + 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; + } + + +#if 0 + + /* This function must be declared by the debugger front end */ + /* in order to specify which code range to debug. */ + + int debug_coderange = tt_coderange_glyph; + + static char tempStr[128]; + + static const char* OpStr[256] = + { + "SVTCA y", /* Set vectors to coordinate axis y */ + "SVTCA x", /* Set vectors to coordinate axis x */ + "SPvTCA y", /* Set Proj. vec. to coord. axis y */ + "SPvTCA x", /* Set Proj. vec. to coord. axis x */ + "SFvTCA y", /* Set Free. vec. to coord. axis y */ + "SFvTCA x", /* Set Free. vec. to coord. axis x */ + "SPvTL //", /* Set Proj. vec. parallel to segment */ + "SPvTL +", /* Set Proj. vec. normal to segment */ + "SFvTL //", /* Set Free. vec. parallel to segment */ + "SFvTL +", /* Set Free. vec. normal to segment */ + "SPvFS", /* Set Proj. vec. from stack */ + "SFvFS", /* Set Free. vec. from stack */ + "GPV", /* Get projection vector */ + "GFV", /* Get freedom vector */ + "SFvTPv", /* Set free. vec. to proj. vec. */ + "ISECT", /* compute intersection */ + + "SRP0", /* Set reference point 0 */ + "SRP1", /* Set reference point 1 */ + "SRP2", /* Set reference point 2 */ + "SZP0", /* Set Zone Pointer 0 */ + "SZP1", /* Set Zone Pointer 1 */ + "SZP2", /* Set Zone Pointer 2 */ + "SZPS", /* Set all zone pointers */ + "SLOOP", /* Set loop counter */ + "RTG", /* Round to Grid */ + "RTHG", /* Round to Half-Grid */ + "SMD", /* Set Minimum Distance */ + "ELSE", /* Else */ + "JMPR", /* Jump Relative */ + "SCvTCi", /* Set CVT */ + "SSwCi", /* */ + "SSW", /* */ + + "DUP", + "POP", + "CLEAR", + "SWAP", + "DEPTH", + "CINDEX", + "MINDEX", + "AlignPTS", + "INS_$28", + "UTP", + "LOOPCALL", + "CALL", + "FDEF", + "ENDF", + "MDAP[-]", + "MDAP[r]", + + "IUP[y]", + "IUP[x]", + "SHP[0]", + "SHP[1]", + "SHC[0]", + "SHC[1]", + "SHZ[0]", + "SHZ[1]", + "SHPIX", + "IP", + "MSIRP[0]", + "MSIRP[1]", + "AlignRP", + "RTDG", + "MIAP[-]", + "MIAP[r]", + + "NPushB", + "NPushW", + "WS", + "RS", + "WCvtP", + "RCvt", + "GC[0]", + "GC[1]", + "SCFS", + "MD[0]", + "MD[1]", + "MPPEM", + "MPS", + "FlipON", + "FlipOFF", + "DEBUG", + + "LT", + "LTEQ", + "GT", + "GTEQ", + "EQ", + "NEQ", + "ODD", + "EVEN", + "IF", + "EIF", + "AND", + "OR", + "NOT", + "DeltaP1", + "SDB", + "SDS", + + "ADD", + "SUB", + "DIV", + "MUL", + "ABS", + "NEG", + "FLOOR", + "CEILING", + "ROUND[G]", + "ROUND[B]", + "ROUND[W]", + "ROUND[?]", + "NROUND[G]", + "NROUND[B]", + "NROUND[W]", + "NROUND[?]", + + "WCvtF", + "DeltaP2", + "DeltaP3", + "DeltaC1", + "DeltaC2", + "DeltaC3", + "SROUND", + "S45Round", + "JROT", + "JROF", + "ROFF", + "INS_$7B", + "RUTG", + "RDTG", + "SANGW", + "AA", + + "FlipPT", + "FlipRgON", + "FlipRgOFF", + "INS_$83", + "INS_$84", + "ScanCTRL", + "SDPVTL[0]", + "SDPVTL[1]", + "GetINFO", + "IDEF", + "ROLL", + "MAX", + "MIN", + "ScanTYPE", + "IntCTRL", + "INS_$8F", + + "INS_$90", + "INS_$91", + "INS_$92", + "INS_$93", + "INS_$94", + "INS_$95", + "INS_$96", + "INS_$97", + "INS_$98", + "INS_$99", + "INS_$9A", + "INS_$9B", + "INS_$9C", + "INS_$9D", + "INS_$9E", + "INS_$9F", + + "INS_$A0", + "INS_$A1", + "INS_$A2", + "INS_$A3", + "INS_$A4", + "INS_$A5", + "INS_$A6", + "INS_$A7", + "INS_$A8", + "INS_$A9", + "INS_$AA", + "INS_$AB", + "INS_$AC", + "INS_$AD", + "INS_$AE", + "INS_$AF", + + "PushB[0]", + "PushB[1]", + "PushB[2]", + "PushB[3]", + "PushB[4]", + "PushB[5]", + "PushB[6]", + "PushB[7]", + "PushW[0]", + "PushW[1]", + "PushW[2]", + "PushW[3]", + "PushW[4]", + "PushW[5]", + "PushW[6]", + "PushW[7]", + + "MDRP[G]", + "MDRP[B]", + "MDRP[W]", + "MDRP[?]", + "MDRP[rG]", + "MDRP[rB]", + "MDRP[rW]", + "MDRP[r?]", + "MDRP[mG]", + "MDRP[mB]", + "MDRP[mW]", + "MDRP[m?]", + "MDRP[mrG]", + "MDRP[mrB]", + "MDRP[mrW]", + "MDRP[mr?]", + "MDRP[pG]", + "MDRP[pB]", + + "MDRP[pW]", + "MDRP[p?]", + "MDRP[prG]", + "MDRP[prB]", + "MDRP[prW]", + "MDRP[pr?]", + "MDRP[pmG]", + "MDRP[pmB]", + "MDRP[pmW]", + "MDRP[pm?]", + "MDRP[pmrG]", + "MDRP[pmrB]", + "MDRP[pmrW]", + "MDRP[pmr?]", + + "MIRP[G]", + "MIRP[B]", + "MIRP[W]", + "MIRP[?]", + "MIRP[rG]", + "MIRP[rB]", + "MIRP[rW]", + "MIRP[r?]", + "MIRP[mG]", + "MIRP[mB]", + "MIRP[mW]", + "MIRP[m?]", + "MIRP[mrG]", + "MIRP[mrB]", + "MIRP[mrW]", + "MIRP[mr?]", + "MIRP[pG]", + "MIRP[pB]", + + "MIRP[pW]", + "MIRP[p?]", + "MIRP[prG]", + "MIRP[prB]", + "MIRP[prW]", + "MIRP[pr?]", + "MIRP[pmG]", + "MIRP[pmB]", + "MIRP[pmW]", + "MIRP[pm?]", + "MIRP[pmrG]", + "MIRP[pmrB]", + "MIRP[pmrW]", + "MIRP[pmr?]" + }; + + + const char* Cur_U_Line( TT_ExecContext exec ) + { + char s[32]; + + int op, i, n; + + op = exec->code[exec->IP]; + + sprintf( tempStr, "%s", OpStr[op] ); + + if ( op == 0x40 ) + { + n = exec->code[exec->IP + 1]; + sprintf( s, "(%d)", n ); + strncat( tempStr, s, 8 ); + + if ( n > 20 ) n = 20; /* limit output */ + + for ( i = 0; i < n; i++ ) + { + sprintf( s, " $%02hx", exec->code[exec->IP + i + 2] ); + strncat( tempStr, s, 8 ); + } + } + else if ( op == 0x41 ) + { + n = exec->code[exec->IP + 1]; + sprintf( s, "(%d)", n ); + strncat( tempStr, s, 8 ); + + if ( n > 20 ) n = 20; /* limit output */ + + for ( i = 0; i < n; i++ ) + { + sprintf( s, " $%02hx%02hx", exec->code[exec->IP + i*2 + 2], + exec->code[exec->IP + i*2 + 3] ); + strncat( tempStr, s, 8 ); + } + } + else if ( (op & 0xF8) == 0xB0 ) + { + n = op - 0xB0; + + for ( i = 0; i <= n; i++ ) + { + sprintf( s, " $%02hx", exec->code[exec->IP + i + 1] ); + strncat( tempStr, s, 8 ); + } + } + else if ( (op & 0xF8) == 0xB8 ) + { + n = op-0xB8; + + for ( i = 0; i <= n; i++ ) + { + sprintf( s, " $%02hx%02hx", exec->code[exec->IP + i*2 + 1], + exec->code[exec->IP + i*2 + 2] ); + strncat( tempStr, s, 8 ); + } + } + + return (char*)tempStr; + } + + + EXPORT_FUNC + TT_Error TT_RunIns( TT_ExecContext exc ) + { + TT_Int A, diff; + TT_ULong next_IP; + TT_Char ch, oldch; + char *temp; + int key; + FT_Memory memory; + + TT_Error error = 0; + + TT_GlyphZone save; + TT_GlyphZone pts; + +#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 + + const char* round_str[8] = + { + "to half-grid", + "to grid", + "to double grid", + "down to grid", + "up to grid", + "off", + "super", + "super 45" + }; + + /* Check that we're running the code range that is effectively */ + /* asked by the debugger front end. */ + if ( exc->curRange != debug_coderange ) + return TT_RunIns2( exc ); + + pts = exc->pts; + + memory = exc->face->root.memory; + + save.n_points = pts.n_points; + save.n_contours = pts.n_contours; + + MEM_Alloc( save.org, sizeof ( TT_Vector ) * save.n_points ); + MEM_Alloc( save.cur, sizeof ( TT_Vector ) * save.n_points ); + MEM_Alloc( save.touch, sizeof ( TT_Byte ) * save.n_points ); + + exc->instruction_trap = 1; + + oldch = '\0'; + + do + { + if ( exc->IP < exc->codeSize ) + { +#ifdef TT_CONFIG_OPTION_STATIC_INTERPRETER + cur = *exc; +#endif + if ( ( CUR.length = opcode_length[CUR.opcode] ) < 0 ) + { + if ( CUR.IP + 1 > CUR.codeSize ) + goto LErrorCodeOverflow_; + + CUR.length = CUR.code[CUR.IP + 1] + 2; + } + + exc->args = exc->top - (Pop_Push_Count[exc->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. */ + + /* Print the current line. We use a 80-columns console with the */ + /* following formatting: */ + /* */ + /* [loc]:[addr] [opcode] [disassemby] [a][b]|[c][d] */ + /* */ + + { + char temp[80]; + int n, col, pop; + int args = CUR.args; + + + sprintf( temp, "%78c\n", ' ' ); + + /* first letter of location */ + switch ( CUR.curRange ) + { + case tt_coderange_glyph: + temp[0] = 'g'; + break; + case tt_coderange_cvt: + temp[0] = 'c'; + break; + default: + temp[0] = 'f'; + } + + /* current IP */ + sprintf( temp+1, "%04lx: %02x %-36.36s", + CUR.IP, + CUR.opcode, + Cur_U_Line(&CUR) ); + + strncpy( temp+46, " (", 2 ); + + args = CUR.top - 1; + pop = Pop_Push_Count[CUR.opcode] >> 4; + col = 48; + for ( n = 6; n > 0; n-- ) + { + if ( pop == 0 ) + temp[col-1] = (temp[col-1] == '(' ? ' ' : ')' ); + + if ( args < CUR.top && args >= 0 ) + sprintf( temp+col, "%04lx", CUR.stack[args] ); + else + sprintf( temp+col, " " ); + + temp[col+4] = ' '; + col += 5; + pop--; + args--; + } + temp[78] = '\n'; + temp[79] = '\0'; + FT_TRACE0(( temp )); + } + + /* First, check for empty stack and overflow */ + if ( CUR.args < 0 ) + { + FT_TRACE0(( "ERROR : Too few arguments\n" )); + exc->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 'case' */ + + if ( CUR.new_top > CUR.stackSize ) + { + FT_TRACE0(( "ERROR : Stack overflow\n" )); + exc->error = TT_Err_Stack_Overflow; + goto LErrorLabel_; + } + } + else + FT_TRACE0(( "End of program reached.\n" )); + + key = 0; + do + { + /* read keyboard */ + + ch = getch(); + + switch ( ch ) + { + /* Help - show keybindings */ + case '?': + FT_TRACE0(( "FDebug Help\n\n" )); + FT_TRACE0(( "? Show this page\n" )); + FT_TRACE0(( "q Quit debugger\n" )); + FT_TRACE0(( "n Skip to next instruction\n" )); + FT_TRACE0(( "s Step into\n" )); + FT_TRACE0(( "v Show vector info\n" )); + FT_TRACE0(( "g Show graphics state\n" )); + FT_TRACE0(( "p Show points zone\n\n" )); + break; + + /* Show vectors */ + case 'v': + FT_TRACE0(( "freedom (%04hx,%04hx)\n", exc->GS.freeVector.x, + exc->GS.freeVector.y )); + FT_TRACE0(( "projection (%04hx,%04hx)\n", exc->GS.projVector.x, + exc->GS.projVector.y )); + FT_TRACE0(( "dual (%04hx,%04hx)\n\n", exc->GS.dualVector.x, + exc->GS.dualVector.y )); + break; + + /* Show graphics state */ + case 'g': + FT_TRACE0(( "rounding %s\n", round_str[exc->GS.round_state] )); + FT_TRACE0(( "min dist %04lx\n", exc->GS.minimum_distance )); + FT_TRACE0(( "cvt_cutin %04lx\n", exc->GS.control_value_cutin )); + break; + + /* Show points table */ + case 'p': + for ( A = 0; A < exc->pts.n_points; A++ ) + { + FT_TRACE0(( "%02hx ", A )); + FT_TRACE0(( "%08lx,%08lx - ", pts.org[A].x, pts.org[A].y )); + FT_TRACE0(( "%08lx,%08lx\n", pts.cur[A].x, pts.cur[A].y )); + } + FT_TRACE0(( "\n" )); + break; + + default: + key = 1; + } + } while ( !key ); + + MEM_Copy( save.org, pts.org, pts.n_points * sizeof ( TT_Vector ) ); + MEM_Copy( save.cur, pts.cur, pts.n_points * sizeof ( TT_Vector ) ); + MEM_Copy( save.touch, pts.touch, pts.n_points ); + + /* a return indicate the last command */ + if (ch == '\r') + ch = oldch; + + switch ( ch ) + { + /* Quit debugger */ + case 'q': + goto LErrorLabel_; + + /* Step over */ + case 'n': + if ( exc->IP < exc->codeSize ) + { + /* `step over' is equivalent to `step into' except if */ + /* the current opcode is a CALL or LOOPCALL */ + if ( CUR.opcode != 0x2a && CUR.opcode != 0x2b ) + goto Step_into; + + /* otherwise, loop execution until we reach the next opcode */ + next_IP = CUR.IP + CUR.length; + while ( exc->IP != next_IP ) + { + if ( ( error = TT_RunIns2( exc ) ) ) + goto LErrorLabel_; + } + } + oldch = ch; + break; + + /* Step into */ + case 's': + if ( exc->IP < exc->codeSize ) + + Step_into: + if ( ( error = TT_RunIns2( exc ) ) ) + goto LErrorLabel_; + oldch = ch; + break; + + default: + FT_TRACE0(( "unknown command. Press ? for help\n" )); + oldch = '\0'; + } + + for ( A = 0; A < pts.n_points; A++ ) + { + diff = 0; + if ( save.org[A].x != pts.org[A].x ) diff |= 1; + if ( save.org[A].y != pts.org[A].y ) diff |= 2; + if ( save.cur[A].x != pts.cur[A].x ) diff |= 4; + if ( save.cur[A].y != pts.cur[A].y ) diff |= 8; + if ( save.touch[A] != pts.touch[A] ) diff |= 16; + + if ( diff ) + { + FT_TRACE0(( "%02hx ", A )); + + if ( diff & 16 ) temp = "(%01hx)"; else temp = " %01hx "; + FT_TRACE0(( temp, save.touch[A] & 7 )); + + if ( diff & 1 ) temp = "(%08lx)"; else temp = " %08lx "; + FT_TRACE0(( temp, save.org[A].x )); + + if ( diff & 2 ) temp = "(%08lx)"; else temp = " %08lx "; + FT_TRACE0(( temp, save.org[A].y )); + + if ( diff & 4 ) temp = "(%08lx)"; else temp = " %08lx "; + FT_TRACE0(( temp, save.cur[A].x )); + + if ( diff & 8 ) temp = "(%08lx)"; else temp = " %08lx "; + FT_TRACE0(( temp, save.cur[A].y )); + + FT_TRACE0(( "\n" )); + + FT_TRACE0(( "%02hx ", A )); + + if ( diff & 16 ) temp = "[%01hx]"; else temp = " %01hx "; + FT_TRACE0(( temp, pts.touch[A] & 7 )); + + if ( diff & 1 ) temp = "[%08lx]"; else temp = " %08lx "; + FT_TRACE0(( temp, pts.org[A].x )); + + if ( diff & 2 ) temp = "[%08lx]"; else temp = " %08lx "; + FT_TRACE0(( temp, pts.org[A].y )); + + if ( diff & 4 ) temp = "[%08lx]"; else temp = " %08lx "; + FT_TRACE0(( temp, pts.cur[A].x )); + + if ( diff & 8 ) temp = "[%08lx]"; else temp = " %08lx "; + FT_TRACE0(( temp, pts.cur[A].y )); + + FT_TRACE0(( "\n\n" )); + } + } + } while ( TRUE ); + + LErrorLabel_: + + return error; + + LErrorCodeOverflow_: + error = TT_Err_Code_Overflow; + return error; + } + +#endif /* DEBUG_INTERPRETER */ + + +/* END */ diff --git a/src/truetype/ttinterp.h b/src/truetype/ttinterp.h new file mode 100644 index 000000000..96cd4a519 --- /dev/null +++ b/src/truetype/ttinterp.h @@ -0,0 +1,470 @@ +/***************************************************************************/ +/* */ +/* ttinterp.h */ +/* */ +/* TrueType bytecode intepreter (specification). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef TTINTERP_H +#define TTINTERP_H + +#include + + +#ifdef __cplusplus + extern "C" { +#endif + + +#ifndef TT_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_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 TT_F26Dot6 (*TT_Round_Func)( EXEC_OP_ TT_F26Dot6 distance, + TT_F26Dot6 compensation ); + + /* Point displacement along the freedom vector routine */ + typedef void (*TT_Move_Func)( EXEC_OP_ TT_GlyphZone* zone, + TT_UInt point, + TT_F26Dot6 distance ); + + /* Distance projection along one of the projection vectors */ + typedef TT_F26Dot6 (*TT_Project_Func)( EXEC_OP_ TT_Vector* v1, + TT_Vector* v2 ); + + /* reading a cvt value. Take care of non-square pixels if necessary */ + typedef TT_F26Dot6 (*TT_Get_CVT_Func)( EXEC_OP_ TT_ULong index ); + + /* setting or moving a cvt value. Take care of non-square pixels */ + /* if necessary */ + typedef void (*TT_Set_CVT_Func)( EXEC_OP_ TT_ULong index, + TT_F26Dot6 value ); + + + /*************************************************************************/ + /* */ + /* This structure defines a call record, used to manage function calls. */ + /* */ + typedef struct TT_CallRec_ + { + TT_Int Caller_Range; + TT_Long Caller_IP; + TT_Long Cur_Count; + TT_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 */ + + TT_Error error; /* last execution error */ + + TT_Long top; /* top of exec. stack */ + + TT_UInt stackSize; /* size of exec. stack */ + TT_Long* stack; /* current exec. stack */ + + TT_Long args; + TT_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 */ + + TT_Int curRange; /* current code range number */ + TT_Byte* code; /* current code range */ + TT_Long IP; /* current instruction pointer */ + TT_Long codeSize; /* size of current range */ + + TT_Byte opcode; /* current opcode */ + TT_Int length; /* length of current opcode */ + + TT_Bool step_ins; /* true if the interpreter must */ + /* increment IP after ins. exec */ + TT_Long cvtSize; + TT_Long* cvt; + + TT_UInt glyphSize; /* glyph instructions buffer size */ + TT_Byte* glyphIns; /* glyph instructions buffer */ + + TT_UInt numFDefs; /* number of function defs */ + TT_UInt maxFDefs; /* maximum number of function defs */ + TT_DefArray FDefs; /* table of FDefs entries */ + + TT_UInt numIDefs; /* number of instruction defs */ + TT_UInt maxIDefs; /* maximum number of ins defs */ + TT_DefArray IDefs; /* table of IDefs entries */ + + TT_UInt maxFunc; /* maximum function index */ + TT_UInt maxIns; /* maximum instruction index */ + + TT_Int callTop, /* top of call stack during execution */ + callSize; /* size of call stack */ + TT_CallStack callStack; /* call stack */ + + TT_UShort maxPoints; /* capacity of this context's `pts' */ + TT_Short maxContours; /* record, expressed in points and */ + /* contours. */ + + TT_CodeRangeTable codeRangeTable; /* table of valid code ranges */ + /* useful for the debugger */ + + TT_UShort storeSize; /* size of current storage */ + TT_Long* storage; /* storage area */ + + TT_F26Dot6 period; /* values used for the */ + TT_F26Dot6 phase; /* `SuperRounding' */ + TT_F26Dot6 threshold; + + /* this seems to be unused */ +#if 0 + TT_Int cur_ppem; /* ppem along the current proj vector */ +#endif + TT_Bool instruction_trap; /* If `True', the interpreter will */ + /* exit after each instruction */ + + TT_GraphicsState default_GS; /* graphics state resulting from */ + /* the prep program */ + TT_Bool is_composite; /* true if the glyph is composite */ + TT_Bool pedantic_hinting; /* true for pedantic interpretation */ + + /* latest interpreter additions */ + + TT_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) */ + + TT_ULong loadSize; + TT_SubGlyph_Stack loadStack; /* loading subglyph stack */ + + } TT_ExecContextRec; + + + + LOCAL_DEF + const TT_GraphicsState tt_default_graphics_state; + + + /*************************************************************************/ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_DEF + TT_Error TT_Goto_CodeRange( TT_ExecContext exec, + TT_Int range, + TT_Long IP ); + + /*************************************************************************/ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_DEF + TT_Error TT_Set_CodeRange( TT_ExecContext exec, + TT_Int range, + void* base, + TT_Long length ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Clear_CodeRange */ + /* */ + /* */ + /* Clears a code range. */ + /* */ + /* */ + /* range :: The code range index. */ + /* */ + /* */ + /* exec :: The target execution context. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + /* */ + /* Does not set the Error variable. */ + /* */ + LOCAL_DEF + TT_Error TT_Clear_CodeRange( TT_ExecContext exec, + TT_Int range ); + + + /*************************************************************************/ + /* */ + /* */ + /* 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. */ + /* */ + EXPORT_DEF + TT_ExecContext TT_New_Context( TT_Face face ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Done_Context */ + /* */ + /* */ + /* Discards an execution context. */ + /* */ + /* */ + /* exec :: A handle to the target execution context. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + /* */ + /* Only the glyph loader and debugger should call this function. */ + /* */ + EXPORT_DEF + TT_Error TT_Done_Context( TT_ExecContext exec ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Destroy_Context */ + /* */ + /* */ + /* Destroys a given context. */ + /* */ + /* */ + /* exec :: A handle to the target execution context. */ + /* memory :: A handle to the parent memory object. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + /* */ + /* Only the glyph loader and debugger should call this function. */ + /* */ + LOCAL_DEF + TT_Error TT_Destroy_Context( TT_ExecContext exec, + FT_Memory memory ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Context */ + /* */ + /* */ + /* Prepare an execution context for glyph hinting. */ + /* */ + /* */ + /* exec :: A handle to the target execution context. */ + /* face :: A handle to the source face object. */ + /* size :: A handle to the source size object. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + /* */ + /* Only the glyph loader and debugger should call this function. */ + /* */ + EXPORT_DEF + TT_Error TT_Load_Context( TT_ExecContext exec, + TT_Face face, + TT_Size size ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Save_Context */ + /* */ + /* */ + /* Saves the code ranges in a `size' object. */ + /* */ + /* */ + /* exec :: A handle to the source execution context. */ + /* */ + /* */ + /* ins :: A handle to the target size object. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + /* */ + /* Only the glyph loader and debugger should call this function. */ + /* */ + LOCAL_DEF + TT_Error TT_Save_Context( TT_ExecContext exec, + TT_Size ins ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Run_Context */ + /* */ + /* */ + /* Executes one or more instructions in the execution context. */ + /* */ + /* */ + /* exec :: A handle to the target execution context. */ + /* */ + /* debug :: A Boolean flag. If set, the function sets some internal */ + /* variables and returns immediately, otherwise TT_RunIns() */ + /* is called. */ + /* */ + /* */ + /* TrueTyoe error code. 0 means success. */ + /* */ + /* */ + /* Only the glyph loader and debugger should call this function. */ + /* */ + LOCAL_DEF + TT_Error TT_Run_Context( TT_ExecContext exec, + TT_Bool debug ); + + + /*************************************************************************/ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + /* */ + /* Only object manager and debugger should call this function. */ + /* */ + EXPORT_DEF + TT_Error TT_RunIns( TT_ExecContext exec ); + + +#ifdef __cplusplus + } +#endif + +#endif /* TTINTERP_H */ + + +/* END */ diff --git a/src/truetype/ttnameid.h b/src/truetype/ttnameid.h new file mode 100644 index 000000000..98b19abc9 --- /dev/null +++ b/src/truetype/ttnameid.h @@ -0,0 +1,603 @@ +/***************************************************************************/ +/* */ +/* ttnameid.h */ +/* */ +/* TrueType name ID definitions (specification only). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 +#error "Don't include this file! Use freetype.h instead." +#endif + + +#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 +#define TT_PLATFORM_MICROSOFT 3 + + + /*************************************************************************/ + /* */ + /* Possible values of the platform specific encoding identifier field in */ + /* the name records of the TTF `name' table when the `Platform' */ + /* identifier code is TT_PLATFORM_APPLE_UNICODE. */ + /* */ +#define TT_APPLE_ID_DEFAULT 0 +#define TT_APPLE_ID_UNICODE_1_1 1 +#define TT_APPLE_ID_ISO_10646 2 +#define TT_APPLE_ID_UNICODE_2_0 3 + + + /*************************************************************************/ + /* */ + /* Possible values of the platform specific encoding identifier field in */ + /* the name records of the TTF `name' table when 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 when the `Platform' */ + /* identifier code is TT_PLATFORM_ISO. */ + /* */ +#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 when 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 when 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_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_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 +#define TT_MAC_LANGID_SCOTTISH_GAELIC 140 +#define TT_MAC_LANGID_IRISH_GAELIC 141 +#define TT_MAC_LANGID_BRETON 142 +#define TT_MAC_LANGID_INUKTITUT 143 + + + /*************************************************************************/ + /* */ + /* Possible values of the language identifier field in the name records */ + /* of the TTF `name' table when 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 + + + /*************************************************************************/ + /* */ + /* Bit mask values for the Unicode ranges from the TTF `OS2 ' table. */ + /* */ + /*************************************************************************/ + + +/* General Scripts Area */ + +/* Bit 0 C0 Controls and Basic Latin */ +#define TT_UCR_BASIC_LATIN (1 << 0) /* U+0000-U+007F */ +/* Bit 1 C1 Controls and Latin-1 Supplement */ +#define TT_UCR_LATIN1_SUPPLEMENT (1 << 1) /* U+0080-U+00FF */ +/* Bit 2 Latin Extended-A */ +#define TT_UCR_LATIN_EXTENDED_A (1 << 2) /* U+0100-U+017F */ +/* Bit 3 Latin Extended-B */ +#define TT_UCR_LATIN_EXTENDED_B (1 << 3) /* U+0180-U+024F */ +/* Bit 4 IPA Extensions */ +#define TT_UCR_IPA_EXTENSIONS (1 << 4) /* U+0250-U+02AF */ +/* Bit 5 Spacing Modifier Letters */ +#define TT_UCR_SPACING_MODIFIER (1 << 5) /* U+02B0-U+02FF */ +/* Bit 6 Combining Diacritical Marks */ +#define TT_UCR_COMBINING_DIACRITICAL_MARKS (1 << 6) /* U+0300-U+036F */ +/* Bit 7 Greek */ +#define TT_UCR_GREEK (1 << 7) /* U+0370-U+03FF */ +/* Bit 8 is reserved (was: Greek Symbols and Coptic) */ +/* Bit 9 Cyrillic */ +#define TT_UCR_CYRILLIC (1 << 9) /* U+0400-U+04FF */ +/* Bit 10 Armenian */ +#define TT_UCR_ARMENIAN (1 << 10) /* U+0530-U+058F */ +/* Bit 11 Hebrew */ +#define TT_UCR_HEBREW (1 << 11) /* U+0590-U+05FF */ +/* Bit 12 is reserved (was: Hebrew Extended) */ +/* Bit 13 Arabic */ +#define TT_UCR_ARABIC (1 << 13) /* U+0600-U+06FF */ +/* Bit 14 is reserved (was: Arabic Extended) */ +/* Bit 15 Devanagari */ +#define TT_UCR_DEVANAGARI (1 << 15) /* U+0900-U+097F */ +/* Bit 16 Bengali */ +#define TT_UCR_BENGALI (1 << 16) /* U+0980-U+09FF */ +/* Bit 17 Gurmukhi */ +#define TT_UCR_GURMUKHI (1 << 17) /* U+0A00-U+0A7F */ +/* Bit 18 Gujarati */ +#define TT_UCR_GUJARATI (1 << 18) /* U+0A80-U+0AFF */ +/* Bit 19 Oriya */ +#define TT_UCR_ORIYA (1 << 19) /* U+0B00-U+0B7F */ +/* Bit 20 Tamil */ +#define TT_UCR_TAMIL (1 << 20) /* U+0B80-U+0BFF */ +/* Bit 21 Telugu */ +#define TT_UCR_TELUGU (1 << 21) /* U+0C00-U+0C7F */ +/* Bit 22 Kannada */ +#define TT_UCR_KANNADA (1 << 22) /* U+0C80-U+0CFF */ +/* Bit 23 Malayalam */ +#define TT_UCR_MALAYALAM (1 << 23) /* U+0D00-U+0D7F */ +/* Bit 24 Thai */ +#define TT_UCR_THAI (1 << 24) /* U+0E00-U+0E7F */ +/* Bit 25 Lao */ +#define TT_UCR_LAO (1 << 25) /* U+0E80-U+0EFF */ +/* Bit 26 Georgian */ +#define TT_UCR_GEORGIAN (1 << 26) /* U+10A0-U+10FF */ +/* Bit 27 is reserved (was Georgian Extended) */ +/* Bit 28 Hangul Jamo */ +#define TT_UCR_HANGUL_JAMO (1 << 28) /* U+1100-U+11FF */ +/* Bit 29 Latin Extended Additional */ +#define TT_UCR_LATIN_EXTENDED_ADDITIONAL (1 << 29) /* U+1E00-U+1EFF */ +/* Bit 30 Greek Extended */ +#define TT_UCR_GREEK_EXTENDED (1 << 30) /* U+1F00-U+1FFF */ + +/* Symbols Area */ + +/* Bit 31 General Punctuation */ +#define TT_UCR_GENERAL_PUNCTUATION (1 << 31) /* U+2000-U+206F */ +/* Bit 32 Superscripts And Subscripts */ +#define TT_UCR_SUPERSCRIPTS_SUBSCRIPTS (1 << 0) /* U+2070-U+209F */ +/* Bit 33 Currency Symbols */ +#define TT_UCR_CURRENCY_SYMBOLS (1 << 1) /* U+20A0-U+20CF */ +/* Bit 34 Combining Diacritical Marks For Symbols */ +#define TT_UCR_COMBINING_DIACRITICAL_MARKS_SYMB (1 << 2) /* U+20D0-U+20FF */ +/* Bit 35 Letterlike Symbols */ +#define TT_UCR_LETTERLIKE_SYMBOLS (1 << 3) /* U+2100-U+214F */ +/* Bit 36 Number Forms */ +#define TT_UCR_NUMBER_FORMS (1 << 4) /* U+2150-U+218F */ +/* Bit 37 Arrows */ +#define TT_UCR_ARROWS (1 << 5) /* U+2190-U+21FF */ +/* Bit 38 Mathematical Operators */ +#define TT_UCR_MATHEMATICAL_OPERATORS (1 << 6) /* U+2200-U+22FF */ +/* Bit 39 Miscellaneous Technical */ +#define TT_UCR_MISCELLANEOUS_TECHNICAL (1 << 7) /* U+2300-U+23FF */ +/* Bit 40 Control Pictures */ +#define TT_UCR_CONTROL_PICTURES (1 << 8) /* U+2400-U+243F */ +/* Bit 41 Optical Character Recognition */ +#define TT_UCR_OCR (1 << 9) /* U+2440-U+245F */ +/* Bit 42 Enclosed Alphanumerics */ +#define TT_UCR_ENCLOSED_ALPHANUMERICS (1 << 10) /* U+2460-U+24FF */ +/* Bit 43 Box Drawing */ +#define TT_UCR_BOX_DRAWING (1 << 11) /* U+2500-U+257F */ +/* Bit 44 Block Elements */ +#define TT_UCR_BLOCK_ELEMENTS (1 << 12) /* U+2580-U+259F */ +/* Bit 45 Geometric Shapes */ +#define TT_UCR_GEOMETRIC_SHAPES (1 << 13) /* U+25A0-U+25FF */ +/* Bit 46 Miscellaneous Symbols */ +#define TT_UCR_MISCELLANEOUS_SYMBOLS (1 << 14) /* U+2600-U+26FF */ +/* Bit 47 Dingbats */ +#define TT_UCR_DINGBATS (1 << 15) /* U+2700-U+27BF */ + +/* CJK Phonetics and Symbols Area */ + +/* Bit 48 CJK Symbols And Punctuation */ +#define TT_UCR_CJK_SYMBOLS (1 << 16) /* U+3000-U+303F */ +/* Bit 49 Hiragana */ +#define TT_UCR_HIRAGANA (1 << 17) /* U+3040-U+309F */ +/* Bit 50 Katakana */ +#define TT_UCR_KATAKANA (1 << 18) /* U+30A0-U+30FF */ +/* Bit 51 Bopomofo */ +#define TT_UCR_BOPOMOFO (1 << 19) /* U+3100-U+312F */ +/* Bit 52 Hangul Compatibility Jamo */ +#define TT_UCR_HANGUL_COMPATIBILITY_JAMO (1 << 20) /* U+3130-U+318F */ +/* Bit 53 CJK Miscellaneous */ +#define TT_UCR_CJK_MISC (1 << 21) /* U+3190-U+319F */ +/* Bit 54 Enclosed CJK Letters And Months */ +#define TT_UCR_ENCLOSED_CJK_LETTERS_MONTHS (1 << 22) /* U+3200-U+32FF */ +/* Bit 55 CJK Compatibility */ +#define TT_UCR_CJK_COMPATIBILITY (1 << 23) /* U+3300-U+33FF */ + +/* Hangul Syllables Area */ + +/* Bit 56 Hangul */ +#define TT_UCR_HANGUL (1 << 24) /* U+AC00-U+D7A3 */ + +/* Surrogates Area */ + +/* Bit 57 Surrogates */ +#define TT_UCR_SURROGATES (1 << 25) /* U+D800-U+DFFF */ +/* Bit 58 is reserved for Unicode SubRanges */ + +/* CJK Ideographs Area */ + +/* Bit 59 CJK Unified Ideographs */ +#define TT_UCR_CJK_UNIFIED_IDEOGRAPHS (1 << 27) /* U+4E00-U+9FFF */ + +/* Private Use Area */ + +/* Bit 60 Private Use */ +#define TT_UCR_PRIVATE_USE (1 << 28) /* U+E000-U+F8FF */ + +/* Compatibility Area and Specials */ + +/* Bit 61 CJK Compatibility Ideographs */ +#define TT_UCR_CJK_COMPATIBILITY_IDEOGRAPHS (1 << 29) /* U+F900-U+FAFF */ +/* Bit 62 Alphabetic Presentation Forms */ +#define TT_UCR_ALPHABETIC_PRESENTATION_FORMS (1 << 30) /* U+FB00-U+FB4F */ +/* Bit 63 Arabic Presentation Forms-A */ +#define TT_UCR_ARABIC_PRESENTATION_FORMS_A (1 << 31) /* U+FB50-U+FSFF */ +/* Bit 64 Combining Half Marks */ +#define TT_UCR_COMBINING_HALF_MARKS (1 << 0) /* U+FE20-U+FE2F */ +/* Bit 65 CJK Compatibility Forms */ +#define TT_UCR_CJK_COMPATIBILITY_FORMS (1 << 1) /* U+FE30-U+FE4F */ +/* Bit 66 Small Form Variants */ +#define TT_UCR_SMALL_FORM_VARIANTS (1 << 2) /* U+FE50-U+FE6F */ +/* Bit 67 Arabic Presentation Forms-B */ +#define TT_UCR_ARABIC_PRESENTATION_FORMS_B (1 << 3) /* U+FE70-U+FEFF */ +/* Bit 68 Halfwidth And Fullwidth Forms */ +#define TT_UCR_HALFWIDTH_FULLWIDTH_FORMS (1 << 4) /* U+FF00-U+FFEF */ +/* Bit 69 Specials */ +#define TT_UCR_SPECIALS (1 << 5) /* U+FEFF, + U+FFF0-U+FFFF */ +/* Bit 70 Tibetan */ +#define TT_UCR_TIBETAN (1 << 6) /* U+0F00-U+0FBF */ + + +#endif /* TTNAMEID_H */ + + +/* END */ diff --git a/src/truetype/ttobjs.c b/src/truetype/ttobjs.c new file mode 100644 index 000000000..caa14ab6c --- /dev/null +++ b/src/truetype/ttobjs.c @@ -0,0 +1,888 @@ +/***************************************************************************/ +/* */ +/* ttobjs.c */ +/* */ +/* Objects manager (body). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 +#include + +/* required by tracing mode */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_ttobjs + + + /*************************************************************************/ + /* */ + /* GLYPH ZONE FUNCTIONS */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* pts :: A pointer to the target glyph zone record. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_FUNC + TT_Error TT_New_GlyphZone( FT_Memory memory, + TT_GlyphZone* pts, + TT_UShort maxPoints, + TT_Short maxContours ) + { + TT_Error error; + + + if ( ALLOC( pts->org, maxPoints * 2 * sizeof ( TT_F26Dot6 ) ) || + ALLOC( pts->cur, maxPoints * 2 * sizeof ( TT_F26Dot6 ) ) || + ALLOC( pts->touch, maxPoints * sizeof ( TT_Byte ) ) || + ALLOC( pts->contours, maxContours * sizeof ( TT_UShort ) ) ) + return error; + + return TT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Done_GlyphZone */ + /* */ + /* */ + /* Deallocates a glyph zone. */ + /* */ + /* */ + /* memory :: A handle to the current memory object. */ + /* */ + /* pts :: A pointer to the target glyph zone record. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_FUNC + TT_Error TT_Done_GlyphZone( FT_Memory memory, + TT_GlyphZone* pts ) + { + FREE( pts->contours ); + FREE( pts->touch ); + FREE( pts->cur ); + FREE( pts->org ); + + return TT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* Char string. NULL if no name is present. */ + /* */ + static + FT_String* Get_Name( TT_Face face, + TT_UShort nameid ) + { + FT_Memory memory = face->root.memory; + TT_UShort n; + TT_NameRec* rec; + TT_Bool wide_chars = 1; + + /* first pass, look for a given name record */ + + 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 */ + TT_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 ) + { + TT_String* string; + TT_UInt len; + + if ( wide_chars ) + { + TT_UInt m; + + len = (TT_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; + } + + +#undef LOAD_ +#define LOAD_(x) ( (error = sfnt->load_##x( face, stream )) != TT_Err_Ok ) + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Init_Face */ + /* */ + /* */ + /* Initializes a given TrueType face object. */ + /* */ + /* */ + /* resource :: The source font resource. */ + /* face_index :: The index of the font face in the resource. */ + /* face :: The newly built face object. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_DEF + TT_Error TT_Init_Face( FT_Stream stream, + TT_Long face_index, + TT_Face face ) + { + TT_Error error; + SFNT_Interface* sfnt; + + sfnt = (SFNT_Interface*)face->sfnt; + if (!sfnt) + { + /* look-up the SFNT driver */ + FT_Driver sfnt_driver; + + sfnt_driver = FT_Get_Driver( face->root.driver->library, "sfnt" ); + if (!sfnt_driver) + return FT_Err_Invalid_File_Format; + + sfnt = (SFNT_Interface*)(sfnt_driver->interface.format_interface); + if (!sfnt) + return FT_Err_Invalid_File_Format; + + face->sfnt = sfnt; + face->goto_table = sfnt->goto_table; + } + + /* create input stream from resource */ + if ( FILE_Seek(0) ) + goto Exit; + + /* Load collection directory if present, then font directory */ + error = sfnt->load_directory( face, stream, face_index ); + if ( error ) goto Exit; + + face->root.num_faces = face->ttc_header.DirCount; + if ( face->root.num_faces < 1 ) + face->root.num_faces = 1; + + /* If we're performing a simple font format check, exit immediately */ + if ( face_index < 0 ) + return TT_Err_Ok; + + /* Load tables */ + + if ( LOAD_( header ) || + LOAD_( max_profile ) || + + (error = sfnt->load_metrics( face, stream, 0 )) != TT_Err_Ok || + /* load the `hhea' & `hmtx' tables at once */ + + (error = sfnt->load_metrics( face, stream, 1 )) != TT_Err_Ok || + /* try to load the `vhea' & `vmtx' at once if present */ + + LOAD_( charmaps ) || + LOAD_( names ) || + LOAD_( os2 ) || + LOAD_( psnames ) || + + /* the optional tables */ +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + LOAD_( sbits ) || +#endif + LOAD_( hdmx ) || + LOAD_( gasp ) || + LOAD_( kerning ) || + + (error = TT_Load_Locations( face, stream )) != TT_Err_Ok || + (error = TT_Load_CVT ( face, stream )) != TT_Err_Ok || + (error = TT_Load_Programs ( face, stream )) != TT_Err_Ok ) + + 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 ); + + Exit: + return error; + } + + +#undef LOAD_ + + + /*************************************************************************/ + /* */ + /* */ + /* 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 ) + { + TT_UShort n; + FT_Memory memory = face->root.memory; + + SFNT_Interface* sfnt = face->sfnt; + + if (sfnt) + { + /* destroy the postscript names table if it is supported */ + if (sfnt->load_psnames) + sfnt->free_psnames( face ); + + /* destroy the embedded bitmaps table if it is supported */ + if (sfnt->load_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.TableDirectory ); + face->ttc_header.DirCount = 0; + + /* freeing table directory */ + FREE( face->dir_tables ); + face->num_tables = 0; + + /* freeing the locations table */ + FREE( face->glyph_locations ); + face->num_locations = 0; + + /* freeing the character mapping tables */ + if (sfnt && sfnt->load_charmaps ) + { + 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 CVT */ + FREE( face->cvt ); + face->cvt_size = 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 programs */ + FREE( face->font_program ); + FREE( face->cvt_program ); + face->font_program_size = 0; + face->cvt_program_size = 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 ); + + face->sfnt = 0; + } + + + /*************************************************************************/ + /* */ + /* SIZE FUNCTIONS */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Init_Size */ + /* */ + /* */ + /* Initializes a new TrueType size object. */ + /* */ + /* */ + /* size :: A handle to the size object. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_DEF + TT_Error TT_Init_Size( TT_Size size ) + { + TT_Face face = (TT_Face)size->root.face; + FT_Memory memory = face->root.memory; + TT_Error error; + TT_Int i; + TT_UShort n_twilight; + + TT_MaxProfile* maxp = &face->max_profile; + TT_ExecContext exec; + + 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, TT_Long ) || + + ALLOC_ARRAY( size->storage, + size->storage_size, TT_Long ) ) + + goto Fail_Memory; + + /* reserve twilight zone */ + n_twilight = maxp->maxTwilightPoints; + error = TT_New_GlyphZone( memory, &size->twilight, n_twilight, 0 ); + 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->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; + if (!size->debug) + exec = TT_New_Context( face ); + /* size objects used during debugging have their own context */ + + 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 = 0x10000; + } + + 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 ); + + size->ttmetrics.valid = FALSE; + return error; + + Fail_Exec: + if ( !size->debug ) + TT_Done_Context( exec ); + + Fail_Memory: + 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 ) + { + 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( memory, &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; + + 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 + TT_Error TT_Reset_Size( TT_Size size ) + { + TT_ExecContext exec; + TT_Error error; + TT_UShort i, j; + TT_Face face; + + 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 = 0x10000; + 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 = 0x10000; + } + + /* 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; + + /* 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 Fin; + + if ( !size->debug ) + error = face->interpreter( exec ); + } + else + error = TT_Err_Ok; + + size->GS = exec->GS; + /* save default graphics state */ + + Fin: + TT_Save_Context( exec, size ); + + if ( !size->debug ) + TT_Done_Context( exec ); + /* debugging instances keep their context */ + + if ( !error ) + size->ttmetrics.valid = TRUE; + + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Init_GlyphSlot */ + /* */ + /* */ + /* The TrueType glyph slot initializer. */ + /* */ + /* */ + /* slot :: The glyph record to build. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_FUNC + TT_Error TT_Init_GlyphSlot( TT_GlyphSlot slot ) + { + /* allocate the outline space */ + FT_Face face = slot->face; + FT_Library library = face->driver->library; + + + FT_TRACE4(( "TT.Init_GlyphSlot: Creating outline maxp = %d, maxc = %d\n", + face->max_points, face->max_contours )); + + return FT_New_Outline( library, + face->max_points + 2, + face->max_contours, + &slot->outline ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Done_GlyphSlot */ + /* */ + /* */ + /* The TrueType glyph slot finalizer. */ + /* */ + /* */ + /* slot :: A handle to the glyph slot object. */ + /* */ + LOCAL_FUNC + void TT_Done_GlyphSlot( TT_GlyphSlot slot ) + { + FT_Library library = slot->face->driver->library; + + + FT_Done_Outline( library, &slot->outline ); + return; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Init_Driver */ + /* */ + /* */ + /* Initializes a given TrueType driver object. */ + /* */ + /* */ + /* driver :: A handle to the target driver object. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_FUNC + TT_Error TT_Init_Driver( TT_Driver driver ) + { + /* init extension registry if needed */ +#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE + return TT_Init_Extensions( driver ); +#else + UNUSED( driver ); + + return TT_Err_Ok; +#endif + } + + + /*************************************************************************/ + /* */ + /* */ + /* 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 + + /* destroy the execution context */ + if ( driver->context ) + { + TT_Destroy_Context( driver->context, driver->root.memory ); + driver->context = NULL; + } + } + + +/* END */ diff --git a/src/truetype/ttobjs.h b/src/truetype/ttobjs.h new file mode 100644 index 000000000..e4befb576 --- /dev/null +++ b/src/truetype/ttobjs.h @@ -0,0 +1,594 @@ +/***************************************************************************/ +/* */ +/* ttobjs.h */ +/* */ +/* Objects manager (specification). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 +#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_ + { + TT_UShort rp0; + TT_UShort rp1; + TT_UShort rp2; + + TT_UnitVector dualVector; + TT_UnitVector projVector; + TT_UnitVector freeVector; + + TT_Long loop; + TT_F26Dot6 minimum_distance; + TT_Int round_state; + + TT_Bool auto_flip; + TT_F26Dot6 control_value_cutin; + TT_F26Dot6 single_width_cutin; + TT_F26Dot6 single_width_value; + TT_Short delta_base; + TT_Short delta_shift; + + TT_Byte instruct_control; + TT_Bool scan_control; + TT_Int scan_type; + + TT_UShort gep0; + TT_UShort gep1; + TT_UShort gep2; + + } TT_GraphicsState; + + + /*************************************************************************/ + /* */ + /* 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_ + { + TT_Byte* base; + TT_ULong size; + + } TT_CodeRange; + + typedef TT_CodeRange TT_CodeRangeTable[TT_MAX_CODE_RANGES]; + + + /*************************************************************************/ + /* */ + /* Defines a function/instruction definition record. */ + /* */ + typedef struct TT_DefRecord_ + { + TT_Int range; /* in which code range is it located? */ + TT_Long start; /* where does it start? */ + TT_UInt opc; /* function #, or instruction code */ + TT_Bool active; /* is it active? */ + + } TT_DefRecord, *TT_DefArray; + + + /*************************************************************************/ + /* */ + /* This type defining a set of glyph points will be used to represent */ + /* each zone (regular and twilight) during instructions decoding. */ + /* */ + typedef struct TT_GlyphZone_ + { + TT_UShort n_points; /* number of points in zone */ + TT_Short n_contours; /* number of contours */ + + TT_Vector* org; /* original point coordinates */ + TT_Vector* cur; /* current point coordinates */ + + TT_Byte* touch; /* current touch flags */ + TT_UShort* contours; /* contour end points */ + + } TT_GlyphZone; + + + /*************************************************************************/ + /* */ + /* Subglyph transformation record. */ + /* */ + typedef struct TT_Transform_ + { + TT_Fixed xx, xy; /* transformation matrix coefficients */ + TT_Fixed yx, yy; + TT_F26Dot6 ox, oy; /* offsets */ + + } TT_Transform; + + + /*************************************************************************/ + /* */ + /* Subglyph loading record. Used to load composite components. */ + /* */ + typedef struct TT_SubglyphRec_ + { + TT_Long index; /* subglyph index; initialized with -1 */ + TT_Bool is_scaled; /* is the subglyph scaled? */ + TT_Bool is_hinted; /* should it be hinted? */ + TT_Bool preserve_pps; /* preserve phantom points? */ + + TT_Long file_offset; + + TT_BBox bbox; + TT_Pos left_bearing; + TT_Pos advance; + + TT_GlyphZone zone; + + TT_Long arg1; /* first argument */ + TT_Long arg2; /* second argument */ + + TT_UShort element_flag; /* current load element flag */ + + TT_Transform transform; /* transformation matrix */ + + TT_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 */ + TT_Long x_ratio; + TT_Long y_ratio; + + TT_UShort ppem; /* maximum ppem size */ + TT_Long ratio; /* current ratio */ + TT_Fixed scale; + + TT_F26Dot6 compensations[4]; /* device-specific compensations */ + + TT_Bool valid; + + TT_Bool rotated; /* `is the glyph rotated?'-flag */ + TT_Bool stretched; /* `is the glyph stretched?'-flag */ + + } TT_Size_Metrics; + + + /*************************************************************************/ + /* */ + /* FreeType execution context type. */ + /* */ + /* This is a forward declaration; the full specification is in the file */ + /* `ttinterp.h'. */ + /* */ + typedef struct TT_ExecContextRec_* TT_ExecContext; + + + /***********************************************************************/ + /* */ + /* TrueType size class. */ + /* */ + typedef struct TT_SizeRec_ + { + FT_SizeRec root; + + TT_Size_Metrics ttmetrics; + + TT_UInt num_function_defs; /* number of function definitions */ + TT_UInt max_function_defs; + TT_DefArray function_defs; /* table of function definitions */ + + TT_UInt num_instruction_defs; /* number of ins. definitions */ + TT_UInt max_instruction_defs; + TT_DefArray instruction_defs; /* table of ins. definitions */ + + TT_UInt max_func; + TT_UInt max_ins; + + TT_CodeRangeTable codeRangeTable; + + TT_GraphicsState GS; + + TT_ULong cvt_size; /* the scaled control value table */ + TT_Long* cvt; + + TT_UShort storage_size; /* The storage area is now part of */ + TT_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. */ + + TT_Bool debug; + TT_ExecContext context; + + } TT_SizeRec; + + + /***********************************************************************/ + /* */ + /* TrueType driver class. */ + /* */ + typedef struct TT_DriverRec_ + { + FT_DriverRec root; + TT_ExecContext context; /* execution context */ + + void* extension_component; + + } TT_DriverRec; + + + /*************************************************************************/ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* pts :: A pointer to the target glyph zone record. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_DEF + TT_Error TT_New_GlyphZone( FT_Memory memory, + TT_GlyphZone* pts, + TT_UShort maxPoints, + TT_Short maxContours ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Done_GlyphZone */ + /* */ + /* */ + /* Deallocates a glyph zone. */ + /* */ + /* */ + /* memory :: A handle to the current memory object. */ + /* */ + /* pts :: A pointer to the target glyph zone record. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_FUNC + TT_Error TT_Done_GlyphZone( FT_Memory memory, + TT_GlyphZone* pts ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Init_Face */ + /* */ + /* */ + /* Initializes a given TrueType face object. */ + /* */ + /* */ + /* resource :: The source font resource. */ + /* face_index :: The index of the font face in the resource. */ + /* face :: The newly built face object. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_DEF + TT_Error TT_Init_Face( FT_Stream stream, + TT_Long face_index, + TT_Face face ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Done_Face */ + /* */ + /* */ + /* Finalizes a given face object. */ + /* */ + /* */ + /* face :: The target face object to finalize. */ + /* */ + LOCAL_DEF + void TT_Done_Face( TT_Face face ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Init_Size */ + /* */ + /* */ + /* Initializes a new TrueType size object. */ + /* */ + /* */ + /* size :: A handle to the size object. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_DEF + TT_Error TT_Init_Size( TT_Size size ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Done_Size */ + /* */ + /* */ + /* The TrueType size object finalizer. */ + /* */ + /* */ + /* size :: A handle to the target size object. */ + /* */ + LOCAL_DEF + void TT_Done_Size( TT_Size size ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Reset_Size */ + /* */ + /* */ + /* Resets a TrueType size when resolutions and character dimensions */ + /* have been changed. */ + /* */ + /* */ + /* size :: A handle to the target size object. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_DEF + TT_Error TT_Reset_Size( TT_Size size ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Init_GlyphSlot */ + /* */ + /* */ + /* The TrueType glyph slot initializer. */ + /* */ + /* */ + /* glyph :: The glyph record to build. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_DEF + TT_Error TT_Init_GlyphSlot( TT_GlyphSlot slot ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Done_GlyphSlot */ + /* */ + /* */ + /* The TrueType glyph slot finalizer. */ + /* */ + /* */ + /* glyph :: A handle to the glyph slot object. */ + /* */ + LOCAL_DEF + void TT_Done_GlyphSlot( TT_GlyphSlot slot ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Init_Driver */ + /* */ + /* */ + /* Initializes a given TrueType driver object. */ + /* */ + /* */ + /* driver :: A handle to the target driver object. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_DEF + TT_Error TT_Init_Driver( TT_Driver driver ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Done_Driver */ + /* */ + /* */ + /* Finalizes a given TrueType driver. */ + /* */ + /* */ + /* driver :: A handle to the target TrueType driver. */ + /* */ + LOCAL_DEF + void TT_Done_Driver( TT_Driver driver ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* TTOBJS_H */ + + +/* END */ diff --git a/src/truetype/ttpload.c b/src/truetype/ttpload.c new file mode 100644 index 000000000..7b4a69071 --- /dev/null +++ b/src/truetype/ttpload.c @@ -0,0 +1,260 @@ +/***************************************************************************/ +/* */ +/* ttpload.h */ +/* */ +/* TrueType glyph data/program tables loader (body). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 + +#undef FT_COMPONENT +#define FT_COMPONENT trace_ttload + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Locations */ + /* */ + /* */ + /* Loads the locations table. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_FUNC + TT_Error TT_Load_Locations( TT_Face face, + FT_Stream stream ) + { + TT_Error error; + FT_Memory memory = stream->memory; + TT_Short LongOffsets; + TT_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 = (TT_UShort)(table_len >> 2); + + FT_TRACE2(( "(32 bits offsets): %12d ", face->num_locations )); + + if ( ALLOC_ARRAY( face->glyph_locations, + face->num_locations, + TT_Long ) ) + goto Exit; + + if ( ACCESS_Frame( face->num_locations * 4L ) ) + goto Exit; + + { + TT_Long* loc = face->glyph_locations; + TT_Long* limit = loc + face->num_locations; + + for ( ; loc < limit; loc++ ) + *loc = GET_Long(); + } + + FORGET_Frame(); + } + else + { + face->num_locations = (TT_UShort)(table_len >> 1); + + FT_TRACE2(( "(16 bits offsets): %12d ", + face->num_locations )); + + if ( ALLOC_ARRAY( face->glyph_locations, + face->num_locations, + TT_Long ) ) + goto Exit; + + if ( ACCESS_Frame( face->num_locations * 2L ) ) + goto Exit; + { + TT_Long* loc = face->glyph_locations; + TT_Long* limit = loc + face->num_locations; + + for ( ; loc < limit; loc++ ) + *loc = (TT_Long)((TT_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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_FUNC + TT_Error TT_Load_CVT( TT_Face face, + FT_Stream stream ) + { + TT_Error error; + FT_Memory memory = stream->memory; + TT_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, + TT_Short ) ) + goto Exit; + + if ( ACCESS_Frame( face->cvt_size * 2L ) ) + goto Exit; + + { + TT_Short* cur = face->cvt; + TT_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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_FUNC + TT_Error TT_Load_Programs( TT_Face face, + FT_Stream stream ) + { + TT_Error error; + FT_Memory memory = stream->memory; + TT_ULong table_len; + + FT_TRACE2(( "Font program " )); + + error = TT_Err_Ok; + + /* 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 ( ALLOC( face->font_program, + face->font_program_size ) || + + FILE_Read( (void*)face->font_program, + face->font_program_size ) ) + 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; + + FT_TRACE2(( "is missing!\n" )); + } + else + { + face->cvt_program_size = table_len; + + if ( ALLOC( face->cvt_program, + face->cvt_program_size ) || + + FILE_Read( (void*)face->cvt_program, + face->cvt_program_size ) ) + return error; + + FT_TRACE2(( "loaded, %12d bytes\n", face->cvt_program_size )); + } + + Exit: + return error; + } + + +/* END */ diff --git a/src/truetype/ttpload.h b/src/truetype/ttpload.h new file mode 100644 index 000000000..bb7c51777 --- /dev/null +++ b/src/truetype/ttpload.h @@ -0,0 +1,92 @@ +/***************************************************************************/ +/* */ +/* ttpload.h */ +/* */ +/* TrueType glyph data/program tables loader (specification). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Locations */ + /* */ + /* */ + /* Loads the locations table. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_DEF + TT_Error TT_Load_Locations( TT_Face face, + FT_Stream stream ); + + + /*************************************************************************/ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_DEF + TT_Error TT_Load_CVT( TT_Face face, + FT_Stream stream ); + + + /*************************************************************************/ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + LOCAL_DEF + TT_Error TT_Load_Programs( TT_Face face, + FT_Stream stream ); + +#endif /* TTPLOAD_H */ + + +/* END */ diff --git a/src/truetype/tttags.h b/src/truetype/tttags.h new file mode 100644 index 000000000..73bbfc0ef --- /dev/null +++ b/src/truetype/tttags.h @@ -0,0 +1,60 @@ +/***************************************************************************/ +/* */ +/* tttags.h */ +/* */ +/* Tags for TrueType tables (specification only). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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_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_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_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/src/type1/rules.mk b/src/type1/rules.mk new file mode 100644 index 000000000..adae99c86 --- /dev/null +++ b/src/type1/rules.mk @@ -0,0 +1,167 @@ +#**************************************************************************** +#* * +#* Type1 driver Makefile * +#* * +#* Copyright 1996-1999 by * +#* David Turner, Robert Wilhelm, and Werner Lemberg. * +#* * +#* This file is part of the FreeType project, and may only be used * +#* modified and distributed under the terms of the FreeType project * +#* license, LICENSE.TXT. By continuing to use, modify, or distribute * +#* this file you indicate that you have read the license and * +#* understand and accept it fully. * +#* * +#**************************************************************************** + + +#**************************************************************************** +#* * +#* IMPORTANT NOTE: This Makefile is intended for GNU Make! * +#* If you provide Makefiles for other make utilities, * +#* please place them in `freetype/lib/arch/'. * +#* * +#* * +#* This file is to be included by the FreeType Makefile.lib, located in * +#* the `freetype/lib' directory. Here is the list of the variables that * +#* must be defined to use it: * +#* * +#* * +#* BASE_DIR: The location of the base layer's directory. This is * +#* usually `freetype/lib/base'. * +#* * +#* ARCH_DIR: The location of the architecture-dependent directory. * +#* This is usually `freetype/lib/arch/'. * +#* * +#* DRIVERS_DIR: The location of the font driver sub-dirs, usually * +#* `freetype/lib/drivers'. * +#* * +#* OBJ_DIR: The location where the compiled object(s) file will be * +#* placed. * +#* * +#* BASE_H: A list of pathnames to the base layer's header files on * +#* which the driver depends. * +#* * +#* FT_CFLAGS: A set of flags used for compilation of object files. * +#* This contains at least the include paths of the arch * +#* and base directories + optimization + warnings + ANSI * +#* compliance. * +#* * +#* FT_IFLAG: The flag used to specify an include path on the * +#* compiler command line. For example, with GCC, this is * +#* `-I', while some other compilers use `/i=' or `-J', * +#* etc. * +#* * +#* FT_OBJ: The suffix of an object file for the platform; can be * +#* `o', `obj', `coff', `tco', etc. depending on the * +#* platform. * +#* * +#* * +#* It also updates the following variables defined and used in the main * +#* Makefile: * +#* * +#* DRV_OBJ_S: The list of driver object files in * +#* single-object mode. * +#* * +#* DRV_OBJ_M: The list of driver object files in * +#* multiple-objects mode. * +#* * +#* FTINIT_DRIVER_PATHS: The list of include paths used to compile the * +#* `ftinit' component which registers all font * +#* drivers in the FT_Init_FreeType() function. * +#* * +#* FTINIT_DRIVER_H: The list of header dependencies used to * +#* compile the `ftinit' component. * +#* * +#* FTINIT_DRIVER_MACROS: The list of macros to be defined when * +#* compiling the `ftinit' component. * +#* * +#* `Single-object compilation' means that each font driver is compiled * +#* into a single object file. This is useful to get rid of all * +#* driver-specific entries. * +#* * +#**************************************************************************** + + +# Type1 driver directory +# +T1_DIR := $(SRC_)type1 +T1_DIR_ := $(T1_DIR)$(SEP) + + +# additional include flags used when compiling the driver +# +T1_INCLUDE := $(SHARED) $(T1_DIR) +T1_COMPILE := $(FT_CC) $(T1_INCLUDE:%=$I%) + + +# 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_)t1encode.c \ + $(T1_DIR_)t1hinter.c \ + $(T1_DIR_)t1gload.c + + +# Type1 driver headers +# +T1_DRV_H := $(T1_DIR_)t1errors.h \ + $(T1_DIR_)t1config.h \ + $(T1SHARED_H) \ + $(T1_DRV_SRC:%.c=%.h) + + +# driver object(s) +# +# T1_DRV_OBJ_M is used during `debug' builds +# T1_DRV_OBJ_S is used during `release' builds +# +T1_DRV_OBJ_M := $(T1_DRV_SRC:$(T1_DIR_)%.c=$(OBJ_)%.$O) \ + $(T1SHARED:$(T1SHARED_DIR_)%.c=$(OBJ_)%.$O) +T1_DRV_OBJ_S := $(OBJ_)type1.$O + + + +# driver root source file(s) +# +T1_DRV_SRC_M := $(T1_DRV_SRC) $(T1SHARED_SRC) +T1_DRV_SRC_S := $(T1_DIR_)type1.c + + +# driver - single object +# +# the driver is recompiled if any of the header or source files is changed +# +$(T1_DRV_OBJ_S): $(BASE_H) $(T1_DRV_H) $(T1_DRV_SRC) $(T1_DRV_SRC_S) + $(T1_COMPILE) $T$@ $(T1_DRV_SRC_S) + + + +# driver - multiple objects +# +# All objects are recompiled if any of the header files is changed +# +$(OBJ_)t1%.$O: $(T1_DIR_)t1%.c $(BASE_H) $(T1_DRV_H) + $(T1_COMPILE) $T$@ $< + +$(OBJ_)t1%.$O: $(T1SHARED_DIR_)t1%.c $(BASE_H) $(T1SHARED_H) + $(T1_COMPILE) $T$@ $< + + +# update main driver object lists +# +DRV_OBJS_S += $(T1_DRV_OBJ_S) +DRV_OBJS_M += $(T1_DRV_OBJ_M) + + +# update 'ftinit' variables +# +FTINIT_DRIVER_PATHS += $(T1_DIR) $(T1SHARED_DIR) +FTINIT_DRIVER_H += $(T1_DRV_H) +FTINIT_DRIVER_MACROS += FT_SUPPORT_TYPE1 + + +# END diff --git a/src/type1/t1config.h b/src/type1/t1config.h new file mode 100644 index 000000000..a72b177b2 --- /dev/null +++ b/src/type1/t1config.h @@ -0,0 +1,45 @@ +/******************************************************************* + * + * t1config.h + * + * Type 1 driver configuration file + * + * Copyright 1996-1998 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.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 T1CONFIG_H +#define T1CONFIG_H + +/* 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 + +#endif /* T1CONFIG_H */ diff --git a/src/type1/t1driver.c b/src/type1/t1driver.c new file mode 100644 index 000000000..0c974be67 --- /dev/null +++ b/src/type1/t1driver.c @@ -0,0 +1,279 @@ +/******************************************************************* + * + * t1driver.c + * + * High-level Type1 driver interface for FreeType 2.0 + * + * Copyright 1996-1998 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.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 + +#undef FT_COMPONENT +#define FT_COMPONENT trace_t1driver + + /******************************************************************/ + /* */ + /* Set_Char_Sizes */ + /* */ + /* */ + /* A driver method used to reset a size's character sizes */ + /* (horizontal and vertical) expressed in fractional points. */ + /* */ + /* */ + /* size :: handle to target size object */ + /* char_width :: character width expressed in 26.6 points */ + /* char_height :: character height expressed in 26.6 points */ + /* */ + /* */ + /* FreeType error code. 0 means success */ + /* */ + static + T1_Error Set_Char_Sizes( T1_Size size, + T1_F26Dot6 char_width, + T1_F26Dot6 char_height, + T1_UInt horz_resolution, + T1_UInt vert_resolution ) + { + FT_Size_Metrics* metrics; + T1_Face face; + + if (!size) + return T1_Err_Invalid_Size_Handle; + + if ( char_width < 1*64 ) char_width = 1*64; + if ( char_height < 1*64 ) char_height = 1*64; + + metrics = &size->root.metrics; + face = (T1_Face)size->root.face; + + metrics->x_ppem = ( char_width * horz_resolution + 36 )/72; + metrics->y_ppem = ( char_height * vert_resolution + 36 )/72; + + metrics->x_ppem = ( metrics->x_ppem + 32 ) & -64; + metrics->y_ppem = ( metrics->y_ppem + 32 ) & -64; + + metrics->x_scale = FT_MulDiv( metrics->x_ppem, 0x10000, + face->root.units_per_EM ); + + metrics->y_scale = FT_MulDiv( metrics->y_ppem, 0x10000, + face->root.units_per_EM ); + + metrics->x_ppem >>= 6; + metrics->y_ppem >>= 6; + + 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. */ + /* */ + /* */ + /* size :: handle to target size object */ + /* */ + /* pixel_width :: character width expressed in 26.6 points */ + /* */ + /* pixel_height :: character height expressed in 26.6 points */ + /* */ + /* char_size :: the corresponding character size in points */ + /* This value is only sent to the TrueType */ + /* bytecode interpreter, even though 99% of */ + /* glyph programs will simply ignore it. A */ + /* safe value there is the maximum of the */ + /* pixel width and height (multiplied by */ + /* 64 to make it a 26.6 fixed float !) */ + /* */ + /* FreeType error code. 0 means success */ + /* */ + static + T1_Error Set_Pixel_Sizes( T1_Size size, + T1_Int pixel_width, + T1_Int pixel_height ) + { + FT_Size_Metrics* metrics; + T1_Face face; + + if (!size) + return T1_Err_Invalid_Size_Handle; + + if ( pixel_width < 1 ) pixel_width = 1; + if ( pixel_height < 1 ) pixel_height = 1; + + metrics = &size->root.metrics; + face = (T1_Face)size->root.face; + + metrics->x_ppem = pixel_width; + metrics->y_ppem = pixel_height; + + metrics->x_scale = FT_MulDiv( metrics->x_ppem * 64, + 0x10000, face->root.units_per_EM ); + + metrics->y_scale = FT_MulDiv( metrics->y_ppem * 64, + 0x10000, face->root.units_per_EM ); + + size->valid = 0; + + return T1_Reset_Size(size); + } + + + /******************************************************************/ + /* */ + /* FT_DriverInterface */ + /* */ + /* */ + /* A structure used to hold a font driver's basic interface */ + /* used by the high-level parts of FreeType (or other apps) */ + /* */ + /* Most scalable drivers provide a specialized interface to */ + /* access format-specific features. It can be retrieved with */ + /* a call to the "get_format_interface", and should be defined */ + /* in each font driver header (e.g. ttdriver.h, t1driver.h,..) */ + /* */ + /* All fields are function pointers .. */ + /* */ + /* */ + /* */ + /* */ + /* new_engine :: */ + /* used to create and initialise a new driver object */ + /* */ + /* done_engine :: */ + /* used to finalise and destroy a given driver object */ + /* */ + /* get_format_interface :: */ + /* return a typeless pointer to the format-specific */ + /* driver interface. */ + /* */ + /* new_face :: */ + /* create a new face object from a resource */ + /* */ + /* done_face :: */ + /* discards a face object, as well as all child objects */ + /* ( sizes, charmaps, glyph slots ) */ + /* */ + /* get_face_properties :: */ + /* return generic face properties */ + /* */ + /* get_kerning :: */ + /* return the kerning vector corresponding to a pair */ + /* of glyphs, expressed in unscaled font units. */ + /* */ + /* new_size :: */ + /* create and initialise a new scalable size object. */ + /* */ + /* new_fixed_size :: */ + /* create and initialise a new fixed-size object. */ + /* */ + /* done_size :: */ + /* finalize a given face size object. */ + /* */ + /* set_size_resolutions :: */ + /* reset a scalable size object's output resolutions */ + /* */ + /* set_size_char_sizes :: */ + /* reset a scalable size object's character size */ + /* */ + /* set_pixel_sizes :: */ + /* reset a face size object's pixel dimensions. Applies */ + /* to both scalable and fixed faces. */ + /* */ + /* new_glyph_slot :: */ + /* create and initialise a new glyph slot */ + /* */ + /* done_glyph_slot :: */ + /* discard a given glyph slot */ + /* */ + /* load_glyph :: */ + /* load a given glyph into a given slot */ + /* */ + /* get_glyph_metrics :: */ + /* return a loaded glyph's metrics. */ + /* */ + + EXPORT_FUNC + const FT_DriverInterface t1_driver_interface = + { + sizeof( FT_DriverRec ), + sizeof( T1_FaceRec ), + sizeof( T1_SizeRec ), + sizeof( T1_GlyphSlotRec ), + + "type1", + 1, + 2, + + 0, /* format interface */ + + (FTDriver_initDriver) T1_Init_Driver, + (FTDriver_doneDriver) T1_Done_Driver, + (FTDriver_getInterface) 0, + + (FTDriver_initFace) T1_Init_Face, + (FTDriver_doneFace) T1_Done_Face, + (FTDriver_getKerning) 0, + + (FTDriver_initSize) T1_Init_Size, + (FTDriver_doneSize) T1_Done_Size, + (FTDriver_setCharSizes) Set_Char_Sizes, + (FTDriver_setPixelSizes) Set_Pixel_Sizes, + + (FTDriver_initGlyphSlot) T1_Init_GlyphSlot, + (FTDriver_doneGlyphSlot) T1_Done_GlyphSlot, + (FTDriver_loadGlyph) T1_Load_Glyph, + + (FTDriver_getCharIndex) 0, + }; + + + /******************************************************************/ + /* */ + /* Get_FreeType_Driver_Interface */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* address of TrueType's driver generic interface. The */ + /* forma-specific interface can then be retrieved through */ + /* the method interface->get_format_interface.. */ + /* */ + +#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS + + EXPORT_FUNC + FT_DriverInterface* getDriverInterface( void ) + { + return &t1_driver_interface; + } + +#endif /* FT_CONFIG_OPTION_DYNAMIC_DRIVERS */ + + diff --git a/src/type1/t1driver.h b/src/type1/t1driver.h new file mode 100644 index 000000000..61a16b0c0 --- /dev/null +++ b/src/type1/t1driver.h @@ -0,0 +1,77 @@ +/******************************************************************* + * + * t1driver.h + * + * High-level Type1 driver interface for FreeType 2.0 + * + * Copyright 1996-1998 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.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 +#include + + EXPORT_DEF + const FT_DriverInterface t1_driver_interface; + + +/************************************************************************* + * + * Here is a template of the code that should appear in each + * font driver's _interface_ file (the one included by "ftinit.c"). + * + * It is used to build, at compile time, a simple linked list of + * the interfaces of the drivers which have been #included in + * "ftinit.c". See the source code of the latter file for details + * + * (Note that this is only required when you want your driver included + * in the set of default drivers loaded by FT_Init_FreeType. Other + * drivers can still be added manually at runtime with FT_Add_Driver. + * + * { + * #ifdef FTINIT_DRIVER_CHAIN + * + * static + * const FT_DriverChain ftinit__driver_chain = + * { + * FT_INIT_LAST_DRIVER_CHAIN, + * &_driver_interface + * }; + * + * #undef FT_INIT_LAST_DRIVER_CHAIN + * #define FT_INIT_LAST_DRIVER_CHAIN &ftinit__driver_chain + * + * #endif + * } + * + * replace with your driver's prefix + * + *************************************************************************/ + +#ifdef FTINIT_DRIVER_CHAIN + + static + const FT_DriverChain ftinit_t1_driver_chain = + { + FT_INIT_LAST_DRIVER_CHAIN, + &t1_driver_interface + }; + +#undef FT_INIT_LAST_DRIVER_CHAIN +#define FT_INIT_LAST_DRIVER_CHAIN &ftinit_t1_driver_chain + +#endif /* FTINIT_DRIVER_CHAIN */ + + +#endif /* T1DRIVER_H */ + diff --git a/src/type1/t1encode.c b/src/type1/t1encode.c new file mode 100644 index 000000000..9c91027a7 --- /dev/null +++ b/src/type1/t1encode.c @@ -0,0 +1,332 @@ +/***************************************************************************/ +/* */ +/* t1encode.c */ +/* */ +/* Type 1 standard encoding tables definitions (body). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 included by both the Type1 and Type2 driver. */ +/* It should never be compiled directly. */ +/* */ +/***************************************************************************/ + +#include +#include + + /*************************************************************************/ + /* */ + /* t1_standard_strings: */ + /* */ + /* This array contains the Adobe Standard Glyph Names ordered by */ + /* SID. It was taken from the CFF specification. */ + /* */ + LOCAL_FUNC + const T1_String* 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", + "height", "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", "quillemotleft", "guilsinglleft", "guilsinglright", "fi", + /* 110 */ + "fl", "endash", "dagger", "daggerdbl", "periodcenter", + "paragraph", "bullet", "quotesinglbase", "quotedblbase", "quotedblright", + /* 120 */ + "quillemotright", "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", + "regitered", "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: */ + /* */ + /* A simple table used to encode the Adobe StandardEncoding. The */ + /* table values are the SID of the standard glyphs; the table index */ + /* is the character code for the encoding. */ + /* */ + /* Example: */ + /* */ + /* t1_standard_encoding[33] == 2 */ + /* */ + /* which means that the glyph name for character code 32 is */ + /* */ + /* t1_standard_strings[2] == "exclam" */ + /* */ + /* (this correspond to the exclamation mark `!'). */ + /* */ + LOCAL_FUNC + T1_Short t1_standard_encoding[256] = + { + /* 0 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, + /* 50 */ + 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, + /* 100 */ + 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, + /* 150 */ + 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, + /* 200 */ + 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, + /* 250 */ + 148, 149, 0, 0, 0, 0 + }; + + + /*************************************************************************/ + /* */ + /* t1_expert_encoding: */ + /* */ + /* A simple table used to encode the Adobe ExpertEncoding. The */ + /* table values are the SID of the standard glyphs; the table index */ + /* is the character code for the encoding. */ + /* */ + /* Example: */ + /* */ + /* t1_expert_encoding[33] == 229 */ + /* */ + /* which means that the glyph name for character code 32 is */ + /* */ + /* t1_standard_strings[229] == "exclamsmall" */ + /* */ + LOCAL_FUNC + T1_Short t1_expert_encoding[256] = + { + /* 0 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 229, 230, 0, 231, 232, 233, 234, + 235, 236, 237, 238, 13, 14, 15, 99, 239, 240, + /* 50 */ + 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, + /* 100 */ + 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, + /* 150 */ + 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, + /* 200 */ + 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, + /* 250 */ + 373, 374, 375, 376, 377, 378 + }; + + + /*************************************************************************/ + /* */ + /* t1_expert_subset_encoding: */ + /* */ + /* A simple table used to encode the Adobe ExpertEncoding subset */ + /* defined in the CFF specification. It will probably evolve into */ + /* another form sooner or later, as we deal with charsets */ + /* differently than with encodings. */ + /* */ + LOCAL_FUNC + FT_Short t1_expert_subset_encoding[256] = + { + /* 0 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 231, 232, 0, 0, + 235, 236, 237, 238, 13, 14, 15, 99, 239, 240, + /* 50 */ + 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, 0, 272, 0, 0, 0, 0, + /* 100 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 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, + /* 150 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 304, 305, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 314, 315, + 0, 0, 0, 0, 0, 0, 0, 0, 158, 155, + 163, 0, 320, 321, 322, 323, 324, 325, 0, 0, + /* 200 */ + 326, 150, 164, 169, 327, 328, 329, 330, 331, 332, + 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, + 343, 344, 345, 346, 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, + /* 250 */ + 0, 0, 0, 0, 0, 0 + }; + + +/* END */ diff --git a/src/type1/t1encode.h b/src/type1/t1encode.h new file mode 100644 index 000000000..4a55acd89 --- /dev/null +++ b/src/type1/t1encode.h @@ -0,0 +1,98 @@ +/***************************************************************************/ +/* */ +/* t1encode.h */ +/* */ +/* Type 1 standard encoding tables definitions (specification). */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 included by both the Type1 and Type2 driver. */ +/* It should never be compiled directly. */ +/* */ +/***************************************************************************/ + + +#ifndef T1ENCODE_H +#define T1ENCODE_H + +#include + + + /*************************************************************************/ + /* */ + /* t1_standard_strings: */ + /* */ + /* This array contains the Adobe Standard Glyph Names ordered by */ + /* SID. It was taken from the CFF specification. */ + /* */ + LOCAL_DEF + const T1_String* t1_standard_strings[]; + + + /*************************************************************************/ + /* */ + /* t1_standard_encoding: */ + /* */ + /* A simple table used to encode the Adobe StandardEncoding. The */ + /* table values are the SID of the standard glyphs; the table index */ + /* is the character code for the encoding. */ + /* */ + /* Example: */ + /* */ + /* t1_standard_encoding[33] == 2 */ + /* */ + /* which means that the glyph name for character code 32 is */ + /* */ + /* t1_standard_strings[2] == "exclam" */ + /* */ + /* (this correspond to the exclamation mark `!'). */ + /* */ + LOCAL_DEF + T1_Short t1_standard_encoding[256]; + + + /*************************************************************************/ + /* */ + /* t1_expert_encoding: */ + /* */ + /* A simple table used to encode the Adobe ExpertEncoding. The */ + /* table values are the SID of the standard glyphs; the table index */ + /* is the character code for the encoding. */ + /* */ + /* Example: */ + /* */ + /* t1_expert_encoding[33] == 229 */ + /* */ + /* which means that the glyph name for character code 32 is */ + /* */ + /* t1_standard_strings[229] == "exclamsmall" */ + /* */ + LOCAL_DEF + T1_Short t1_expert_encoding[256]; + + + /*************************************************************************/ + /* */ + /* t1_expert_subset_encoding: */ + /* */ + /* A simple table used to encode the Adobe ExpertEncoding subset */ + /* defined in the CFF specification. It will probably evolve into */ + /* another form sooner or later, as we deal with charsets */ + /* differently than with encodings. */ + /* */ + LOCAL_DEF + T1_Short t1_expert_subset_encoding[256]; + + +#endif /* T1ENCODE_H */ + + +/* END */ diff --git a/src/type1/t1errors.h b/src/type1/t1errors.h new file mode 100644 index 000000000..01f5e4a27 --- /dev/null +++ b/src/type1/t1errors.h @@ -0,0 +1,77 @@ +/******************************************************************* + * + * t1errors.h + * + * Type1 Error ID definitions + * + * Copyright 1996-1998 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.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 +#error "Don't include this file! Use t1driver.h instead." +#endif + +#ifndef T1ERRORS_H +#define T1ERRORS_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 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_Unavailable_Outline FT_Err_Unavailable_Outline +#define T1_Err_Unavailable_Bitmap FT_Err_Unavailable_Bitmap +#define T1_Err_Unavailable_Pixmap FT_Err_Unavailable_Pixmap +#define T1_Err_File_Is_Not_Collection FT_Err_File_Is_Not_Collection + +#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_Too_Many_Points FT_Err_Too_Many_Points +#define T1_Err_Too_Many_Contours FT_Err_Too_Many_Contours +#define T1_Err_Too_Many_Hints FT_Err_Too_Many_Hints +#define T1_Err_Invalid_Composite FT_Err_Invalid_Composite +#define T1_Err_Too_Many_Edges FT_Err_Too_Many_Edges +#define T1_Err_Too_Many_Strokes FT_Err_Too_Many_Strokes + + +#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 /* TDERRORS_H */ + + +/* END */ diff --git a/src/type1/t1gload.c b/src/type1/t1gload.c new file mode 100644 index 000000000..27fbfdcd4 --- /dev/null +++ b/src/type1/t1gload.c @@ -0,0 +1,1579 @@ +/******************************************************************* + * + * t1gload.c 1.0 + * + * Type1 Glyph Loader. + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.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 + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER +#include +#endif + + /**********************************************************************/ + /**********************************************************************/ + /**********************************************************************/ + /********** *********/ + /********** *********/ + /********** GENERIC CHARSTRINGS PARSING *********/ + /********** *********/ + /********** *********/ + /**********************************************************************/ + /**********************************************************************/ + /**********************************************************************/ + +/********************************************************************* + * + * + * T1_Init_Builder + * + * + * Initialise a given glyph builder. + * + * + * builder :: glyph builder to initialise + * face :: current face object + * size :: current size object + * glyph :: current glyph object + * funcs :: glyph builder functions (or "methods"). + * + *********************************************************************/ + + EXPORT_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) + { + builder->base = glyph->root.outline; + builder->max_points = glyph->max_points; + builder->max_contours = glyph->max_contours; + } + + 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; + + builder->base.n_points = 0; + builder->base.n_contours = 0; + builder->current = builder->base; + + builder->pass = 0; + builder->hint_point = 0; + } + + +/********************************************************************* + * + * + * T1_Done_Builder + * + * + * Finalise a given glyph builder. Its content can still be + * used after the call, but the function saves important information + * within the corresponding glyph slot. + * + * + * builder :: glyph builder to initialise + * + *********************************************************************/ + + EXPORT_FUNC + void T1_Done_Builder( T1_Builder* builder ) + { + T1_GlyphSlot glyph = builder->glyph; + + if (glyph) + { + glyph->root.outline = builder->base; + glyph->max_points = builder->max_points; + glyph->max_contours = builder->max_contours; + } + } + + + +/********************************************************************* + * + * + * T1_Init_Decoder + * + * + * Initialise a given Type 1 decoder for parsing + * + * + * decoder :: Type 1 decoder to initialise + * funcs :: hinter functions interface + * + *********************************************************************/ + + EXPORT_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 + * + * + * Lookup a given glyph by its StandardEncoding charcode. Used + * to implement the SEAC Type 1 operator. + * + * + * face :: current face object + * charcode :: charcode to look for + * + * + * glyph index in font face. Returns -1 if the corresponding + * glyph wasn't found. + * + *********************************************************************/ + + static + T1_Int lookup_glyph_by_stdcharcode( T1_Face face, + T1_Int charcode ) + { + T1_Int n; + const T1_String* glyph_name; + + /* check range of standard char code */ + if (charcode < 0 || charcode > 255) + return -1; + + glyph_name = t1_standard_strings[t1_standard_encoding[charcode]]; + + for ( n = 0; n < face->num_glyphs; n++ ) + { + T1_String* name = (T1_String*)face->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 :: current Type 1 decoder + * asb :: accent's side bearing + * adx :: horizontal position of accent + * ady :: vertical position of accent + * bchar :: base character's StandardEncoding charcode + * achar :: accent character's StandardEncoding charcode + * + * + * Error code. 0 means success. + * + *********************************************************************/ + + static + T1_Error t1operator_seac( T1_Decoder* decoder, + T1_Pos asb, + T1_Pos adx, + T1_Pos ady, + T1_Int bchar, + T1_Int achar ) + { + T1_Error error; + T1_Face face = decoder->builder.face; + T1_Int bchar_index, achar_index, n_base_points; + FT_Outline* cur = &decoder->builder.current; + FT_Outline* base = &decoder->builder.base; + T1_Vector left_bearing, advance; + + 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(( "T1.Parse_Seac : invalid seac character code arguments\n" )); + return T1_Err_Syntax_Error; + } + + /* First load "bchar" in builder */ + /* now load the unscaled outline */ + cur->n_points = 0; + cur->n_contours = 0; + cur->points = base->points + base->n_points; + cur->flags = base->flags + base->n_points; + cur->contours = base->contours + base->n_contours; + + error = T1_Parse_CharStrings( decoder, + face->charstrings [bchar_index], + face->charstrings_len[bchar_index], + face->num_subrs, + face->subrs, + face->subrs_len ); + if (error) return error; + + n_base_points = cur->n_points; + + /* save the left bearing and width of the base character */ + /* as they will be erase 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 */ + /* */ + cur->n_points = 0; + cur->n_contours = 0; + cur->points = base->points + base->n_points; + cur->flags = base->flags + base->n_points; + cur->contours = base->contours + base->n_contours; + + error = T1_Parse_CharStrings( decoder, + face->charstrings [achar_index], + face->charstrings_len[achar_index], + face->num_subrs, + face->subrs, + face->subrs_len ); + if (error) return error; + + /* adjust contours in accented character outline */ + { + T1_Int n; + + for ( n = 0; n < cur->n_contours; n++ ) + cur->contours[n] += n_base_points; + } + + /* 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 */ + FT_Translate_Outline( cur, adx - asb, ady ); + + (void)asb; /* ignore this parameter */ + return T1_Err_Ok; + } + +/********************************************************************* + * + * + * t1operator_flex + * + * + * Implements the "flex" Type 1 operator for a Type 1 decoder + * + * + * decoder :: current Type 1 decoder + * threshold :: threshold + * end_x :: position of final flex point + * end_y :: position of final flex point + * + * + * Error code. 0 means success. + * + *********************************************************************/ + + static + T1_Error t1operator_flex( T1_Decoder* decoder, + T1_Pos threshold, + T1_Pos end_x, + T1_Pos end_y ) + { + T1_Vector vec; + T1_Vector* flex = decoder->flex_vectors; + T1_Int n; + + /* 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++; + } + + + (void)threshold; + (void)end_x; + (void)end_y; + + 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 :: current Type 1 decoder + * charstring_base :: base of the charstring stream + * charstring_len :: length in bytes of the charstring stream + * num_subrs :: number of sub-routines + * subrs_base :: array of sub-routines addresses + * subrs_len :: array of sub-routines lengths + * + * + * Error code. 0 means success. + * + *********************************************************************/ + + EXPORT_FUNC + T1_Error T1_Parse_CharStrings( T1_Decoder* decoder, + T1_Byte* charstring_base, + T1_Int charstring_len, + T1_Int num_subrs, + T1_Byte** subrs_base, + T1_Int* subrs_len ) + { + T1_Error error; + T1_Decoder_Zone* zone; + T1_Byte* ip; + T1_Byte* limit; + T1_Builder* builder = &decoder->builder; + T1_Builder_Funcs* builds = &builder->funcs; + T1_Hinter_Funcs* hints = &decoder->hinter; + + static const T1_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, initialise 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 ) + { + T1_Int* top = decoder->top; + T1_Operator op = op_none; + T1_Long value = 0; + + /* First of all, decompress operator or value */ + switch (*ip++) + { + case 1: op = op_hstem; break; + + case 3: op = op_vstem; break; + case 4: op = op_vmoveto; break; + case 5: op = op_rlineto; break; + case 6: op = op_hlineto; break; + case 7: op = op_vlineto; break; + case 8: op = op_rrcurveto; break; + case 9: op = op_closepath; break; + case 10: op = op_callsubr; break; + case 11: op = op_return; break; + + case 13: op = op_hsbw; break; + case 14: op = op_endchar; break; + + case 21: op = op_rmoveto; break; + case 22: op = op_hmoveto; break; + + case 30: op = op_vhcurveto; break; + case 31: op = op_hvcurveto; break; + + case 12: + { + if (ip > limit) + { + FT_ERROR(( "T1.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 = ((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(( "T1.Parse_CharStrings : 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(( "T1.Parse_CharStrings : invalid byte (%d)\n", + ip[-1] )); + goto Syntax_Error; + } + } + + /* push value if needed */ + 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 ------------------------------- */ + { + T1_Int index; + T1_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: '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 + { + T1_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]; + else + { + FT_ERROR(( "T1.Parse_CHarStrings : division by 0\n" )); + goto Syntax_Error; + } + break; + + case op_callsubr: + { + T1_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 : 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 :: pointer to glyph builder object */ +/* num_points :: number of points that will be added later */ +/* */ +/* */ +/* Type1 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 is */ +/* invoked.. */ +/* */ + LOCAL_FUNC + T1_Error T1_Add_Points( T1_Builder* builder, + T1_Int num_points ) + { + T1_Int new_points; + + new_points = builder->base.n_points + + builder->current.n_points + + num_points; + + if ( new_points > builder->max_points ) + { + FT_Memory memory = builder->memory; + T1_Error error; + T1_Int increment = builder->current.points - builder->base.points; + T1_Int current = builder->max_points; + + while ( builder->max_points < new_points ) + builder->max_points += 16; + + if ( REALLOC_ARRAY( builder->base.points, + current, builder->max_points, T1_Vector ) || + + REALLOC_ARRAY( builder->base.flags, + current, builder->max_points, T1_Byte ) ) + return error; + + builder->current.points = builder->base.points + increment; + builder->current.flags = builder->base.flags + increment; + } + + return T1_Err_Ok; + } + +/*************************************************************************/ +/* */ +/* T1_Add_Contours */ +/* */ +/* */ +/* Checks that there is enough room in the current load glyph outline */ +/* to accept "num_contours" additional contours. If not, this func */ +/* the load outline's arrays accordingly.. */ +/* */ +/* */ +/* builder :: pointer to glyph builder object */ +/* num_contours :: number of contours that will be added later */ +/* */ +/* */ +/* Type1 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 + T1_Error T1_Add_Contours( T1_Builder* builder, + T1_Int num_contours ) + { + T1_Int new_contours; + + new_contours = builder->base.n_contours + + builder->current.n_contours + + num_contours; + + if ( new_contours > builder->max_contours && builder->load_points ) + { + T1_Error error; + FT_Memory memory = builder->memory; + T1_Int increment = builder->current.contours - builder->base.contours; + T1_Int current = builder->max_contours; + + while ( builder->max_contours < new_contours ) + builder->max_contours += 4; + + if ( REALLOC_ARRAY( builder->base.contours, + current, builder->max_contours, T1_Short ) ) + return error; + + builder->current.contours = builder->base.contours + increment; + } + + return T1_Err_Ok; + } + + + /**********************************************************************/ + /**********************************************************************/ + /**********************************************************************/ + /********** *********/ + /********** *********/ + /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/ + /********** *********/ + /********** The following code is in charge of computing *********/ + /********** the maximum advance width of the font. It *********/ + /********** quickly process each glyph charstring to *********/ + /********** extract the value from either a "sbw" or "seac" *********/ + /********** operator. *********/ + /********** *********/ + /**********************************************************************/ + /**********************************************************************/ + /**********************************************************************/ + + + + static + T1_Error maxadv_sbw( T1_Decoder* decoder, + T1_Pos sbx, + T1_Pos sby, + T1_Pos wx, + T1_Pos wy ) + { + if (wx > decoder->builder.advance.x) + decoder->builder.advance.x = wx; + + (void)sbx; + (void)sby; + (void)wy; + return -1; /* return an error code to exit the Type 1 parser */ + /* immediately. */ + } + + + static + T1_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_interface is used when computing the maximum advance */ + /* with of the set of glyphs in a given font file. We only process */ + /* the "seac" operator and return immediately.. */ + 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 + T1_Error T1_Compute_Max_Advance( T1_Face face, + T1_Int *max_advance ) + { + T1_Error error; + T1_Decoder decoder; + T1_Int glyph_index; + + *max_advance = 0; + + /* Initialise 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 < face->num_glyphs; glyph_index++ ) + { + /* now get load the unscaled outline */ + error = T1_Parse_CharStrings( &decoder, + face->charstrings [glyph_index], + face->charstrings_len[glyph_index], + face->num_subrs, + face->subrs, + face->subrs_len ); + /* ignore the error if one occured - skip to next glyph */ + (void)error; + } + + *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 + T1_Error close_open_path( T1_Builder* builder ) + { + T1_Error error; + FT_Outline* cur = &builder->current; + T1_Int num_points; + T1_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 ) + { + T1_Vector* source_point; + char* source_flags; + T1_Vector* point; + char* flags; + + error = T1_Add_Points( builder, num_points ); + if (error) return error; + + point = cur->points + cur->n_points; + flags = cur->flags + cur->n_points; + + source_point = point - 2; + source_flags = flags - 2; + + cur->n_points += num_points; + + if ( builder->load_points ) + do + { + *point++ = *source_point--; + *flags++ = *source_flags--; + num_points--; + } + while (num_points > 0); + } + + builder->path_begun = 0; + return T1_Err_Ok; + } + + + static + T1_Error gload_closepath( T1_Builder* builder ) + { + FT_Outline* cur = &builder->current; + + /* 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 latest points if needed - 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 + T1_Error gload_endchar( T1_Builder* builder ) + { + FT_Outline* cur = &builder->current; + T1_Error error; + + /* close path if needed */ + if (builder->path_begun) + { + error = close_open_path( builder ); + if (error) return error; + } + + error = gload_closepath( builder ); + + builder->base.n_points += cur->n_points; + builder->base.n_contours += cur->n_contours; + + return error; + } + + + + static + T1_Error gload_sbw( T1_Builder* builder, + T1_Pos sbx, + T1_Pos sby, + T1_Pos wx, + T1_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 + T1_Error gload_rlineto( T1_Builder* builder, + T1_Pos dx, + T1_Pos dy ) + { + T1_Error error; + FT_Outline* cur = &builder->current; + T1_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->flags [cur->n_points] = FT_Curve_Tag_On; + + builder->last = vec; + } + cur->n_points++; + + builder->path_begun = 1; + return T1_Err_Ok; + } + + + static + T1_Error gload_rmoveto( T1_Builder* builder, + T1_Pos dx, + T1_Pos dy ) + { + T1_Error error; + FT_Outline* cur = &builder->current; + T1_Vector vec; + + /* in the case where "path_begun" is set, we have a rmoveto */ + /* after some normal path definition. When 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 path, so we'll close it explicitely there.. */ + if ( builder->path_begun && builder->face->paint_type == 1 ) + { + if ( builder->face->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->flags [cur->n_points] = FT_Curve_Tag_On; + + builder->last = vec; + } + + cur->n_contours++; + cur->n_points++; + + return T1_Err_Ok; + } + + + static + T1_Error gload_rrcurveto( T1_Builder* builder, + T1_Pos dx1, + T1_Pos dy1, + T1_Pos dx2, + T1_Pos dy2, + T1_Pos dx3, + T1_Pos dy3 ) + { + T1_Error error; + FT_Outline* cur = &builder->current; + T1_Vector vec; + T1_Vector* points; + char* flags; + + /* 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; + flags = cur->flags + cur->n_points; + + vec.x = builder->last.x + dx1; + vec.y = builder->last.y + dy1; + points[0] = vec; flags[0] = FT_Curve_Tag_Cubic; + + vec.x += dx2; + vec.y += dy2; + points[1] = vec; flags[1] = FT_Curve_Tag_Cubic; + + vec.x += dx3; + vec.y += dy3; + points[2] = vec; flags[2] = FT_Curve_Tag_On; + + builder->last = vec; + } + + cur->n_points += 3; + builder->path_begun = 1; + return T1_Err_Ok; + } + + + + + static + T1_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 */ + }; + + + + + LOCAL_FUNC + T1_Error T1_Load_Glyph( T1_GlyphSlot glyph, + T1_Size size, + T1_Int glyph_index, + T1_Int load_flags ) + { + T1_Error error; + T1_Decoder decoder; + T1_Face face = (T1_Face)glyph->root.face; + T1_Bool 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_none; + +#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. */ + /* */ + + if ( hinting ) + { + /* Pass 1 - don't record points, simply stem hints */ + T1_Init_Decoder( &decoder, &t1_hinter_funcs ); + T1_Init_Builder( &decoder.builder, face, size, glyph, + &gload_builder_interface_null ); + + glyph->hints->hori_stems.num_stems = 0; + glyph->hints->vert_stems.num_stems = 0; + + error = T1_Parse_CharStrings( &decoder, + face->charstrings [glyph_index], + face->charstrings_len[glyph_index], + face->num_subrs, + face->subrs, + face->subrs_len ); + + /* All right, pass 1 is finished, now grid-fit all stem hints */ + T1_Hint_Stems( &decoder.builder ); + + /* Pass 2 - record and scale/hint the points */ + T1_Init_Decoder( &decoder, &t1_hinter_funcs ); + T1_Init_Builder( &decoder.builder, face, size, glyph, + &gload_builder_interface ); + + decoder.builder.pass = 1; + + error = T1_Parse_CharStrings( &decoder, + face->charstrings [glyph_index], + face->charstrings_len[glyph_index], + face->num_subrs, + face->subrs, + face->subrs_len ); + + /* save new glyph tables */ + T1_Done_Builder( &decoder.builder ); + } + else +#endif + { + T1_Init_Decoder( &decoder, &gload_hinter_interface ); + + T1_Init_Builder( &decoder.builder, face, size, glyph, + &gload_builder_interface ); + + /* now load the unscaled outline */ + error = T1_Parse_CharStrings( &decoder, + face->charstrings [glyph_index], + face->charstrings_len[glyph_index], + face->num_subrs, + face->subrs, + face->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) + { + FT_BBox cbox; + FT_Glyph_Metrics* metrics = &glyph->root.metrics; + + FT_Get_Outline_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.second_pass = TRUE; + glyph->root.outline.high_precision = ( size->root.metrics.y_ppem < 24 ); + glyph->root.outline.dropout_mode = 2; + + 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 */ + T1_Int n; + FT_Outline* cur = &decoder.builder.base; + T1_Vector* vec = cur->points; + T1_Fixed x_scale = glyph->x_scale; + T1_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->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale ); + + metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale ); + metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale ); + metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, x_scale ); + + } + } + + return error; + } + diff --git a/src/type1/t1gload.h b/src/type1/t1gload.h new file mode 100644 index 000000000..f635b8197 --- /dev/null +++ b/src/type1/t1gload.h @@ -0,0 +1,436 @@ +/******************************************************************* + * + * t1gload.h 1.0 + * + * Type1 Glyph Loader. + * + * Copyright 1996-1998 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.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 glyph loader uses three distinct objects to build + * scaled and hinted outlines from a charstrings program. These are : + * + * - a glyph builder, T1_Builder, used to store the built outline + * + * - a glyph hinter, T1_Hinter, used to record and apply the stem + * hints + * + * - a charstrings interpreter, T1_Decoder, used to parse the + * Type 1 charstrings stream, manage a stack and call the builder + * and/or hinter depending on the opcodes. + * + * Ideally, a Type 2 glyph loader would only need to have its own + * T2_Decoder object (assuming the hinter is able to manage all + * kinds of hints). + * + ******************************************************************/ + +#ifndef T1GLOAD_H +#define T1GLOAD_H + +#include + +#ifdef __cplusplus + extern "C" { +#endif + + +/*************************************************************************/ +/* */ +/* T1_Builder_Funcs */ +/* */ +/* */ +/* a structure used to store the address of various functions */ +/* used by a glyph builder to implement the outline's "path */ +/* construction". */ +/* */ +/* */ + typedef struct T1_Builder_ T1_Builder; + + typedef T1_Error (*T1_Builder_EndChar)( T1_Builder* loader ); + + typedef T1_Error (*T1_Builder_Sbw) ( T1_Builder* loader, + T1_Pos sbx, + T1_Pos sby, + T1_Pos wx, + T1_Pos wy ); + + typedef T1_Error (*T1_Builder_ClosePath)( T1_Builder* loader ); + + typedef T1_Error (*T1_Builder_RLineTo)( T1_Builder* loader, + T1_Pos dx, + T1_Pos dy ); + + typedef T1_Error (*T1_Builder_RMoveTo)( T1_Builder* loader, + T1_Pos dx, + T1_Pos dy ); + + typedef T1_Error (*T1_Builder_RCurveTo)( T1_Builder* loader, + T1_Pos dx1, + T1_Pos dy1, + T1_Pos dx2, + T1_Pos dy2, + T1_Pos dx3, + T1_Pos dy3 ); + + 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. */ +/* */ +/* */ +/* system :: current system object */ +/* face :: current face object */ +/* size :: current size object */ +/* glyph :: current glyph slot */ +/* */ +/* current :: current glyph outline */ +/* base :: base glyph outline */ +/* */ +/* max_points :: maximum points in builder outline */ +/* max_contours :: maximum contours in builder outline */ +/* */ +/* last :: last point position */ +/* */ +/* scale_x :: horizontal scale ( FUnits to sub-pixels ) */ +/* scale_y :: vertical scale ( FUnits to sub-pixels ) */ +/* pos_x :: horizontal translation (composite glyphs) */ +/* pos_y :: vertical translation (composite glyph) */ +/* */ +/* left_bearing :: left side bearing point */ +/* advance :: horizontal advance vector */ +/* */ +/* path_begun :: flag, indicates that a new path has begun */ +/* load_points :: flag, if not set, no points are loaded */ +/* */ +/* pass :: pass number for multi-pass hinters */ +/* */ +/* funcs :: table of builder functions used to perform */ +/* the outline's path construction */ +/* */ +/* hint_point :: index of next point to hint.. */ +/* */ +/* */ +/* */ +/* */ + + struct T1_Builder_ + { + FT_Memory memory; + T1_Face face; + T1_Size size; + T1_GlyphSlot glyph; + + FT_Outline current; /* the current glyph outline */ + FT_Outline base; /* the composite glyph outline */ + + T1_Int max_points; /* capacity of base outline in points */ + T1_Int max_contours; /* capacity of base outline in contours */ + + T1_Vector last; + + T1_Fixed scale_x; + T1_Fixed scale_y; + + T1_Pos pos_x; + T1_Pos pos_y; + + T1_Vector left_bearing; + T1_Vector advance; + + T1_BBox bbox; /* bounding box */ + T1_Bool path_begun; + T1_Bool load_points; + + T1_Int pass; + T1_Int hint_point; + + /* path construction function interface */ + T1_Builder_Funcs funcs; + }; + + +/*************************************************************************/ +/* */ +/* T1_Hinter_Funcs */ +/* */ +/* */ +/* a structure used to store the address of various functions */ +/* used by a Type 1 hinter to perform outline hinting. */ +/* */ + + typedef T1_Error (*T1_Hinter_ChangeHints)( T1_Builder* builder ); + + typedef T1_Error (*T1_Hinter_DotSection)( T1_Builder* builder ); + + typedef T1_Error (*T1_Hinter_Stem)( T1_Builder* builder, + T1_Pos pos, + T1_Pos width, + T1_Bool vertical ); + + + typedef T1_Error (*T1_Hinter_Stem3)( T1_Builder* builder, + T1_Pos pos0, + T1_Pos width0, + T1_Pos pos1, + T1_Pos width1, + T1_Pos pos2, + T1_Pos width2, + T1_Bool vertical ); + + 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_ + { + T1_Byte* base; + T1_Byte* limit; + T1_Byte* cursor; + + } T1_Decoder_Zone; + + + typedef struct T1_Decoder_ + { + T1_Builder builder; + T1_Hinter_Funcs hinter; + + T1_Int stack[ T1_MAX_CHARSTRINGS_OPERANDS ]; + T1_Int* top; + + T1_Decoder_Zone zones[ T1_MAX_SUBRS_CALLS+1 ]; + T1_Decoder_Zone* zone; + + T1_Int flex_state; + T1_Int num_flex_vectors; + T1_Vector flex_vectors[7]; + + } T1_Decoder; + + + +/********************************************************************* + * + * + * T1_Init_Builder + * + * + * Initialise a given glyph builder. + * + * + * builder :: glyph builder to initialise + * face :: current face object + * size :: current size object + * glyph :: current glyph object + * funcs :: glyph builder functions (or "methods"). + * + * + * This function is exported for now because it is used by the + * "t1dump" utility. Later, it will be accessed through a + * format-specific extension + * + *********************************************************************/ + + EXPORT_DEF + void T1_Init_Builder( T1_Builder* builder, + T1_Face face, + T1_Size size, + T1_GlyphSlot glyph, + const T1_Builder_Funcs* funcs ); + +/********************************************************************* + * + * + * T1_Done_Builder + * + * + * Finalise a given glyph builder. Its content can still be + * used after the call, but the function saves important information + * within the corresponding glyph slot. + * + * + * builder :: glyph builder to initialise + * + * + * This function is exported for now because it is used by the + * "t1dump" utility. Later, it will be accessed through a + * format-specific extension + * + *********************************************************************/ + + EXPORT_DEF + void T1_Done_Builder( T1_Builder* builder ); + + +/********************************************************************* + * + * + * T1_Init_Decoder + * + * + * Initialise a given Type 1 decoder for parsing + * + * + * decoder :: Type 1 decoder to initialise + * funcs :: hinter functions interface + * + * + * This function is exported for now because it is used by the + * "t1dump" utility. Later, it will be accessed through a + * format-specific extension + * + *********************************************************************/ + + EXPORT_DEF + void T1_Init_Decoder( T1_Decoder* decoder, + const T1_Hinter_Funcs* funcs ); + + + + /* Compute the maximum advance width of a font through quick parsing */ + LOCAL_DEF + T1_Error T1_Compute_Max_Advance( T1_Face face, + T1_Int *max_advance ); + + + /* This function is exported, because it is used by the T1Dump utility */ + EXPORT_DEF + T1_Error T1_Parse_CharStrings( T1_Decoder* decoder, + T1_Byte* charstring_base, + T1_Int charstring_len, + T1_Int num_subrs, + T1_Byte** subrs_base, + T1_Int* subrs_len ); + + + +/*************************************************************************/ +/* */ +/* 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 :: pointer to glyph builder object */ +/* num_points :: number of points that will be added later */ +/* */ +/* */ +/* Type1 error code. 0 means success */ +/* */ +/* */ +/* This function does NOT update the points count in the glyph loader */ +/* This must be done by the caller itself, after this function is */ +/* invoked.. */ +/* */ + LOCAL_DEF + T1_Error T1_Add_Points( T1_Builder* builder, + T1_Int num_points ); + +/*************************************************************************/ +/* */ +/* T1_Add_Contours */ +/* */ +/* */ +/* Checks that there is enough room in the current load glyph outline */ +/* to accept "num_contours" additional contours. If not, this func */ +/* the load outline's arrays accordingly.. */ +/* */ +/* */ +/* builder :: pointer to glyph builder object */ +/* num_contours :: number of contours that will be added later */ +/* */ +/* */ +/* Type1 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_DEF + T1_Error T1_Add_Contours( T1_Builder* builder, + T1_Int num_contours ); + + + LOCAL_DEF + T1_Error T1_Load_Glyph( T1_GlyphSlot glyph, + T1_Size size, + T1_Int glyph_index, + T1_Int load_flags ); + + +#ifdef __cplusplus + } +#endif + +#endif /* T1GLOAD_H */ diff --git a/src/type1/t1hinter.c b/src/type1/t1hinter.c new file mode 100644 index 000000000..7e2d0ab3f --- /dev/null +++ b/src/type1/t1hinter.c @@ -0,0 +1,1269 @@ +/******************************************************************* + * + * t1hinter.c 1.2 + * + * Type1 hinter. + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.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 +#include +#include + +#undef FT_COMPONENT +#define FT_COMPONENT trace_t1hint /* for debugging/tracing */ + + +#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 + + +/************************************************************************ + * + * + * t1_set_blue_zones + * + * + * Set a size object's blue zones during reset. This will compute + * the "snap" zone corresponding to each blue zone. + * + * + * size :: handle to target size object + * + * + * 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. + * + ************************************************************************/ + + /* ultra simple bubble sort (not a lot of elements, mostly */ + /* pre-sorted, no need for quicksort) */ + static + void t1_sort_blues( T1_Int* blues, + T1_Int count ) + { + T1_Int i, swap; + T1_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 ); + } + } + + + static + T1_Error t1_set_blue_zones( T1_Size size ) + { + T1_Face face = (T1_Face)size->root.face; + T1_Private* priv = &face->private_dict; + T1_Int n; + T1_Int blues[24]; + T1_Int num_bottom; + T1_Int num_top; + T1_Int num_blues; + T1_Size_Hints* hints = size->hints; + T1_Snap_Zone* zone; + T1_Pos pix, orus; + T1_Pos min, max, threshold; + T1_Fixed scale; + T1_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_blues & 1 ) + { + FT_ERROR(( "T1.Copy_Blues : 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_blues - 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 wether to supress overshoots.. */ + + hints->supress_overshoots = + ( size->root.metrics.y_ppem < FT_MulFix(1000,priv->blue_scale) ); + + /* Now print the new blue values in tracing mode */ +#ifdef FT_DEBUG_LEVEL_TRACE + + 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(( "\nOver shoots 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 :: handle to target size object + * + * + * 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 a 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 + T1_Error t1_set_snap_zones( T1_Size size ) + { + T1_Int n, direction, n_zones, num_zones; + T1_Snap_Zone* zone; + T1_Snap_Zone* base_zone; + T1_Short* orgs; + T1_Pos standard_width; + T1_Fixed scale; + + T1_Face face = (T1_Face)size->root.face; + T1_Private* priv = &face->private_dict; + T1_Size_Hints* hints = size->hints; + + /* start with horizontal snap zones */ + direction = 0; + standard_width = priv->standard_width; + n_zones = priv->num_snap_widths; + base_zone = hints->snap_widths; + orgs = priv->stem_snap_widths; + scale = size->root.metrics.x_scale; + + while (direction < 2) + { + /*****************************************************************/ + /* */ + /* Read and scale stem snap widths table from the physical */ + /* font record. */ + /* */ + T1_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; + } + + /* print the scaled stem snap values in tracing modes */ +#ifdef FT_DEBUG_LEVEL_TRACE + + 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 + + /*****************************************************************/ + /* */ + /* 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; + T1_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; + + /* print the scaled stem snap values in tracing modes */ +#ifdef FT_DEBUG_LEVEL_TRACE + + 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 + + /* continue with vertical snap zone */ + direction++; + standard_width = priv->standard_height; + n_zones = priv->num_snap_heights; + base_zone = hints->snap_heights; + orgs = priv->stem_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 :: handle to target size object + * + * + * Error code. 0 means success + * + ************************************************************************/ + + LOCAL_FUNC + T1_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 :: handle to 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 :: handle to size object + * + * + * Error code. 0 means success + * + ************************************************************************/ + + LOCAL_FUNC + T1_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 :: handle to target glyph slot + * + * + * Error code. 0 means success + * + ************************************************************************/ + + LOCAL_FUNC + T1_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 :: handle to 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 + T1_Error t1_hinter_ignore( void ) + { + /* do nothing, used for "dotsection" which is unsupported for now */ + return 0; + } + + static + T1_Error t1_hinter_stem( T1_Builder* builder, + T1_Pos pos, + T1_Int width, + T1_Bool vertical ) + { + T1_Stem_Table* stem_table; + T1_Stem_Hint* stems; + T1_Stem_Hint* cur_stem; + T1_Int min, max, n, num_stems; + T1_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 orus 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 when necessary */ + if (new_stem) + { + if (cur_stem >= stems + T1_HINTER_MAX_EDGES) + { + FT_ERROR(( "T1.Hinter : 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 : fatal glyph loader bug - pass2-stem\n" )); + return T1_Err_Syntax_Error; + } + } + + return T1_Err_Ok; + } + + + static + T1_Error t1_hinter_stem3( T1_Builder* builder, + T1_Pos pos0, + T1_Int width0, + T1_Pos pos1, + T1_Int width1, + T1_Pos pos2, + T1_Int width2, + T1_Bool vertical ) + { + /* For now, don't be elitist and 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 + T1_Error t1_hinter_changehints( T1_Builder* builder ) + { + T1_Int dimension; + T1_Stem_Table* stem_table; + T1_Glyph_Hints* hinter = builder->glyph->hints; + + /* if we're 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; + } + + + LOCAL_FUNC + 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 + * + * + * Sort 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 ) + { + T1_Int num_stems = table->num_stems; + T1_Int num_active = 0; + T1_Int* sort = table->sort; + T1_Stem_Hint* stems = table->stems; + T1_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++ ) + { + T1_Int p = n-1; + T1_Stem_Hint* cur = stems + sort[n]; + + do + { + T1_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, 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 + * + * + * Compute 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, + T1_Pos blueShift, + T1_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++ ) + { + T1_Pos bottom_orus = stem->min_edge.orus; + T1_Pos top_orus = stem->max_edge.orus; + + T1_Pos top_pix = SCALE( top_orus ); + T1_Pos bottom_pix = SCALE( bottom_orus ); + T1_Pos width_pix = top_pix - bottom_pix; + + T1_Pos bottom = bottom_pix; + T1_Pos top = top_pix; + T1_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; + + for ( ; zone < zone_limit; zone++ ) + { + if ( width_pix < zone->min ) + break; + + if ( width_pix <= zone->max ) + { + width_pix = zone->pix; + break; + } + } + } + + /******************************************************************/ + /* 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 */ + { + T1_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 ); + + /* implements blue shift */ + if (!hints->supress_overshoots) + { + T1_Pos delta = blue->pix - bottom_pix; + + delta = ( delta < blueShift ? 0 : ROUND( delta ) ); + bottom -= delta; + } + } + } + } + + + /******************************************************************/ + /* Check for top blue zones alignement */ + { + T1_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 ); + + /* implements blue shift */ + if (!hints->supress_overshoots) + { + T1_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 alignement */ + bottom_pix = bottom; + top_pix = bottom + width_pix; + break; + + case T1_ALIGN_TOP: /* top zone alignement */ + top_pix = top; + bottom_pix = top - width_pix; + + break; + + case T1_ALIGN_BOTH: /* bottom+top zone alignement */ + bottom_pix = bottom; + top_pix = top; + break; + + default: /* no alignement */ + + /* XXXX : 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 + * + * + * Compute 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. + * + ************************************************************************/ + + /* compute the location of each scaled vertical stem hint. */ + /* Take care of blue zones and stem snap table */ + static + void t1_hint_vertical_stems( T1_Stem_Table* table, + T1_Size_Hints* hints, + T1_Fixed scale ) + { + T1_Stem_Hint* stem = table->stems; + T1_Stem_Hint* limit = stem + table->num_stems; + + for ( ; stem < limit; stem++ ) + { + T1_Pos stem_left = stem->min_edge.orus; + T1_Pos stem_right = stem->max_edge.orus; + T1_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_widths; + T1_Snap_Zone* zone_limit = zone + hints->num_snap_widths; + + for ( ; zone < zone_limit; zone++ ) + { + if ( width_pix < zone->min ) + break; + + if ( width_pix <= zone->max ) + { + width_pix = zone->pix; + break; + } + } + } + + /* 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 */ + + /* XXXX : 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 :: 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 + T1_Pos t1_hint_point( T1_Stem_Table* table, + T1_Pos coord, + T1_Fixed scale ) + { + T1_Int num_active = table->num_active; + T1_Int n; + T1_Stem_Hint* prev = 0; + T1_Stem_Hint* cur = 0; + T1_Edge* min; + T1_Edge* max; + T1_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 ); + } + + + + + + +#if 1 + +/************************************************************************ + * + * + * T1_Hint_Points + * + * + * this function grid-fits several points in a given Type 1 builder + * at once. + * + * + * builder :: handle to target Type 1 builder + * first :: first point to hint in builder's current outline + * last :: last point to hint in builder's current outline + * + ************************************************************************/ + + LOCAL_FUNC + void T1_Hint_Points( T1_Builder* builder ) + { + T1_Int first = builder->hint_point; + T1_Int last = builder->current.n_points-1; + + T1_Size size = builder->size; + T1_Fixed scale_x = size->root.metrics.x_scale; + T1_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; + + T1_Vector* cur = builder->current.points + first; + T1_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 :: handle to target builder + * + ************************************************************************/ + + LOCAL_FUNC + void T1_Hint_Stems( T1_Builder* builder ) + { + T1_Glyph_Hints* hints = builder->glyph->hints; + T1_Private* priv = &builder->face->private_dict; + + T1_Size size = builder->size; + T1_Fixed scale_x = size->root.metrics.x_scale; + T1_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 ); + } + +#endif diff --git a/src/type1/t1hinter.h b/src/type1/t1hinter.h new file mode 100644 index 000000000..4bf753af9 --- /dev/null +++ b/src/type1/t1hinter.h @@ -0,0 +1,380 @@ +/******************************************************************* + * + * t1hinter.h 1.2 + * + * Type1 hinter. + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.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.. + * + ******************************************************************/ + +#ifndef T1HINTER_H +#define T1HINTER_H + +#include +#include + +#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 one "original" and + * "scaled" position. + * + * the position corresponds to the stem width (for stem snap zones) + * or to the blue position (for blue zones) + * + * + * orus :: original position in font units + * pix :: current position in sub-pixel units + * min :: minimum boundary in sub-pixel units + * max :: maximim boundary in sub-pixel units + * + ************************************************************************/ + + typedef struct T1_Snap_Zone_ + { + T1_Pos orus; + T1_Pos pix; + T1_Pos min; + T1_Pos max; + + } T1_Snap_Zone; + + +/************************************************************************ + * + * + * T1_Edge + * + * + * A very simply structure used to model an stem edge + * + * + * orus :: original edge position in font units + * pix :: scaled edge position in sub-pixel units + * + ************************************************************************/ + + typedef struct T1_Edge_ + { + T1_Pos orus; + T1_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're coded in a weird way in the charstrings + * + ************************************************************************/ + + typedef struct T1_Stem_Hint_ + { + T1_Edge min_edge; + T1_Edge max_edge; + T1_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 when 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_stem_snapH :: number of horizontal stem snap zones + * stem_snapH :: horizontal stem snap zones + * + * num_stem_snapV :: number of vertical stem snap zones + * stem_snapV :: vertical stem snap zones + * + ************************************************************************/ + + struct T1_Size_Hints_ + { + T1_Bool supress_overshoots; + + T1_Int num_blue_zones; + T1_Int num_bottom_zones; + T1_Snap_Zone blue_zones[ T1_HINTER_MAX_BLUES ]; + + T1_Int num_snap_widths; + T1_Snap_Zone snap_widths[ T1_HINTER_MAX_SNAPS ]; + + T1_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 :: total number of stems in table + * num_active :: number of active stems in table + * + * stems :: the 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_ + { + T1_Int num_stems; + T1_Int num_active; + + T1_Stem_Hint stems[ T1_HINTER_MAX_EDGES ]; + T1_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 :: horizontal stem hints table + * vert_stems :: 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 + * + ************************************************************************/ + + LOCAL_DEF + const T1_Hinter_Funcs t1_hinter_funcs; + + +/************************************************************************ + * + * + * T1_New_Size_Hinter + * + * + * Allocates a new hinter structure for a given size object + * + * + * size :: handle to target size object + * + * + * Error code. 0 means success + * + ************************************************************************/ + + LOCAL_DEF + T1_Error T1_New_Size_Hinter( T1_Size size ); + + +/************************************************************************ + * + * + * T1_Done_Size_Hinter + * + * + * Releases a given size object's hinter structure + * + * + * size :: handle to target size object + * + ************************************************************************/ + + LOCAL_DEF + void T1_Done_Size_Hinter( T1_Size size ); + + +/************************************************************************ + * + * + * T1_Reset_Size_Hinter + * + * + * Recomputes hinting information when a given size object has + * changed its resolutions/char sizes/pixel sizes + * + * + * size :: handle to size object + * + * + * Error code. 0 means success + * + ************************************************************************/ + + LOCAL_DEF + T1_Error T1_Reset_Size_Hinter( T1_Size size ); + + +/************************************************************************ + * + * + * T1_New_Glyph_Hinter + * + * + * Allocates a new hinter structure for a given glyph slot + * + * + * glyph :: handle to target glyph slot + * + * + * Error code. 0 means success + * + ************************************************************************/ + + LOCAL_DEF + T1_Error T1_New_Glyph_Hinter( T1_GlyphSlot glyph ); + + +/************************************************************************ + * + * + * T1_Done_Glyph_Hinter + * + * + * Releases a given glyph slot's hinter structure + * + * + * glyph :: handle to glyph slot + * + ************************************************************************/ + + LOCAL_DEF + void T1_Done_Glyph_Hinter( T1_GlyphSlot glyph ); + + + + +/************************************************************************ + * + * + * T1_Hint_Points + * + * + * this function grid-fits several points in a given Type 1 builder + * at once. + * + * + * builder :: handle to target Type 1 builder + * + ************************************************************************/ + + LOCAL_DEF + void T1_Hint_Points( T1_Builder* builder ); + + +/************************************************************************ + * + * + * 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 :: handle to target builder + * + ************************************************************************/ + + LOCAL_DEF + void T1_Hint_Stems( T1_Builder* builder ); + +#ifdef __cplusplus + } +#endif + +#endif /* T1HINTER_H */ diff --git a/src/type1/t1load.c b/src/type1/t1load.c new file mode 100644 index 000000000..de5a347d0 --- /dev/null +++ b/src/type1/t1load.c @@ -0,0 +1,1458 @@ +#include + +#include +#include +#include +#include +#include + +#include + +#undef FT_COMPONENT +#define FT_COMPONENT trace_t1load + + typedef T1_Error (*T1_Parse_Func)( T1_Parser* parser ); + + +/*************************************************************************/ +/* */ +/* Init_T1_Parser */ +/* */ +/* */ +/* Initialise a given parser object to build a given T1_Face */ +/* */ +/* */ +/* parser :: handle to the newly built parser object */ +/* face :: handle to target T1 face object */ +/* */ + 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 = encoding_none; + parser->encoding_names = 0; + parser->encoding_offsets = 0; + parser->encoding_lengths = 0; + + parser->dump_tokens = 0; + face->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 :: handle to source parser */ +/* */ +/* */ +/* token :: the extracted token descriptor */ +/* */ +/* */ +/* Error code. 0 means success */ +/* */ + LOCAL_FUNC + T1_Error Next_T1_Token( T1_Parser* parser, + T1_Token* token ) + { + T1_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: + ; + } + + /* Dump the token when requested. This feature is only available */ + /* in the 'error' and 'trace' debug levels.. */ +#if defined( FT_DEBUG_LEVEL_ERROR ) || defined( FT_DEBUG_LEVEL_TRACE ) + if ( parser->dump_tokens ) + { + T1_String temp_string[128]; + T1_Int len; + + len = token->len; + if ( len > 127 ) len = 127; + strncpy( temp_string, + (T1_String*)tokzer->base + token->start, + len ); + temp_string[len] = '\0'; + FT_ERROR(( "%s\n", temp_string )); + } +#endif + + return T1_Err_Ok; + } + + + + static + T1_Error Expect_Keyword( T1_Parser* parser, + T1_TokenType keyword ) + { + T1_Token token; + T1_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(( "T1.Parse: keyword '%s' expected.\n", + t1_keywords[ keyword - key_first_ ] )); + } + + Exit: + return error; + } + + + + static + T1_Error Expect_Keyword2( T1_Parser* parser, + T1_TokenType keyword1, + T1_TokenType keyword2 ) + { + T1_Token token; + T1_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(( "T1.Parse: 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->encoding; + T1_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, T1_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 = encoding_expert; + default : parser->encoding_type = encoding_standard; break; + } + } + else + { + FT_ERROR(( "T1.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' when in the Font dictionary */ +/* Its purpose is to build the T1_Face attributes directly from */ +/* the stream.. */ +/* */ +/* */ +/* parser :: handle to current parser. */ +/* */ +/* */ +/* Error code. 0 means success */ +/* */ + static + T1_Error Do_Def_Font( T1_Parser* parser ) + { + T1_Token* top = parser->top; + T1_Face face = parser->face; + + 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; + T1_Error error; + T1_Int len = top[1].len; + + if ( ALLOC( face->font_name, len+1 ) ) + { + parser->error = error; + return error; + } + + MEM_Copy( face->font_name, + parser->tokenizer->base + top[1].start, + len ); + face->font_name[len] = '\0'; + } + else + face->font_name = CopyString( parser ); + break; + + case imm_Encoding: + Parse_Encoding( parser ); + break; + + case imm_PaintType: + face->paint_type = (T1_Byte)CopyInteger( parser ); + break; + + case imm_FontType: + face->font_type = (T1_Byte)CopyInteger( parser ); + break; + + case imm_FontMatrix: + CopyMatrix( parser, &face->font_matrix ); + break; + + case imm_FontBBox: + CopyBBox( parser, &face->font_bbox ); + break; + + case imm_UniqueID: + face->unique_id = CopyInteger( parser ); + break; + + case imm_StrokeWidth: + face->stroke_width = CopyInteger( parser ); + break; + + case imm_FontID: + face->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' when in the FontInfo dictionary */ +/* Its purpose is to build the T1_FontInfo structure directly from */ +/* the stream.. */ +/* */ +/* */ +/* parser :: handle to current parser. */ +/* */ +/* */ +/* Error code. 0 means success */ +/* */ + static + T1_Error Do_Def_FontInfo( T1_Parser* parser ) + { + T1_Token* top = parser->top; + T1_FontInfo* info = &parser->face->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 = (T1_Short)CopyInteger( parser ); + break; + + case imm_UnderlineThickness: + info->underline_thickness = (T1_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' when in the Private dictionary */ +/* Its purpose is to build the T1_Private structure directly from */ +/* the stream.. */ +/* */ +/* */ +/* parser :: handle to current parser. */ +/* */ +/* */ +/* Error code. 0 means success */ +/* */ + static + T1_Error Do_Def_Private( T1_Parser* parser ) + { + T1_Token* top = parser->top; + T1_Private* priv = &parser->face->private_dict; + + switch ( top[0].kind2 ) + { + case imm_RD: case imm_RD_alternate: /* Ignore the definitions */ + case imm_ND: case imm_ND_alternate: /* of RD, NP, ND and their */ + case imm_NP: case imm_NP_alternate: /* alternate forms ... */ + parser->error = T1_Err_Ok; + break; + + + case imm_BlueValues: + CopyArray( parser, &priv->num_blues, + 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, 0x10000 ); + 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, (T1_Short*)&priv->standard_width, 1 ); + break; + + + case imm_StdVW: + CopyArray( parser, 0, (T1_Short*)&priv->standard_height, 1 ); + break; + + + case imm_StemSnapH: + CopyArray( parser, &priv->num_snap_widths, + priv->stem_snap_widths, 12 ); + break; + + + case imm_StemSnapV: + CopyArray( parser, &priv->num_snap_heights, + priv->stem_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 */ +/* ued for the "def" keyword when in the "encoding", "subrs", */ +/* "othersubrs" and "charstrings" dictionary states.. */ +/* */ +/* */ +/* parser :: handle to current parser. */ +/* */ +/* */ +/* Error code. 0 means success */ +/* */ + static + T1_Error Do_Def_Error( T1_Parser* parser ) + { + FT_ERROR(( "T1.Load : 'def' keyword encountered in bad dictionary/array\n" )); + parser->error = T1_Err_Syntax_Error; + return parser->error; + } + + + static + T1_Error Do_Def_Ignore( T1_Parser* parser ) + { + (void)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' when 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 :: handle to current parser. */ +/* */ +/* */ +/* Error code. 0 means success */ +/* */ + static + T1_Error Do_Put_Encoding( T1_Parser* parser ) + { + T1_Error error = T1_Err_Ok; + T1_Face face = parser->face; + T1_Token* top = parser->top; + T1_Encoding* encode = &face->encoding; + T1_Int index; + + /* record and check the character code */ + if ( top[0].kind != tok_number ) + { + FT_TRACE4(( "T1.Parse.put: number expected\n" )); + goto Syntax_Error; + } + index = (T1_Int)CopyInteger( parser ); + if (parser->error) return parser->error; + + if ( index < 0 || index >= encode->num_chars ) + { + FT_TRACE4(( "T1.Parse.put: invalid character code\n" )); + goto Syntax_Error; + } + + /* record the immediate name */ + if ( top[1].kind != tok_immediate ) + { + FT_TRACE4(( "T1.Parse.put: 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 + { + T1_String temp_name[128]; + T1_Token* token = top+1; + T1_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, (T1_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(( "T1.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 a 'RD' when in the Subrs dictionary */ +/* It simply records the array of bytecodes/charstrings corresponding */ +/* to the sub-routine.. */ +/* */ +/* */ +/* parser :: handle to current parser. */ +/* */ +/* */ +/* Error code. 0 means success */ +/* */ + static + T1_Error Do_RD_Subrs( T1_Parser* parser ) + { + T1_Error error = T1_Err_Ok; + T1_Face face = parser->face; + T1_Token* top = parser->top; + T1_Tokenizer tokzer = parser->tokenizer; + T1_Int index, count; + + /* record and check the character code */ + if ( top[0].kind != tok_number || + top[1].kind != tok_number ) + { + FT_ERROR(( "T1.Parse.put: number expected\n" )); + goto Syntax_Error; + } + index = (T1_Int)CopyInteger( parser ); + error = parser->error; if (error) goto Exit; + + count = (T1_Int)CopyInteger( parser ); + error = parser->error; if (error) goto Exit; + + if ( index < 0 || index >= face->num_subrs ) + { + FT_ERROR(( "T1.Parse.put: invalid character code\n" )); + goto Syntax_Error; + } + + /* decrypt charstring and skip them */ + { + T1_Byte* base = tokzer->base + tokzer->cursor; + + t1_decrypt( base, count, 4330 ); + tokzer->cursor += count; + + base += face->private_dict.lenIV; + count -= face->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 a 'RD' when in the CharStrings dictionary */ +/* It simply records the array of bytecodes/charstrings corresponding */ +/* to the glyph program string. */ +/* */ +/* */ +/* parser :: handle to current parser. */ +/* */ +/* */ +/* Error code. 0 means success */ +/* */ + static + T1_Error Do_RD_Charstrings( T1_Parser* parser ) + { + T1_Error error = T1_Err_Ok; + T1_Face face = parser->face; + T1_Token* top = parser->top; + T1_Tokenizer tokzer = parser->tokenizer; + T1_Int index, count; + + /* check the character name argument */ + if ( top[0].kind != tok_immediate ) + { + FT_ERROR(( "T1.Parse.RD: immediate character name expected\n" )); + goto Syntax_Error; + } + + /* check the count argument */ + if ( top[1].kind != tok_number ) + { + FT_ERROR(( "T1.Parse.put: number expected\n" )); + goto Syntax_Error; + } + parser->args++; + count = (T1_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 + { + T1_String temp_name[128]; + T1_Token* token = top; + T1_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, (T1_Byte*)temp_name, len+1 ); + if (error) goto Exit; + } + + /* decrypt and record charstring, then skip them */ + { + T1_Byte* base = tokzer->base + tokzer->cursor; + + t1_decrypt( base, count, 4330 ); + tokzer->cursor += count; /* skip */ + + base += face->private_dict.lenIV; + count -= face->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 + T1_Error Expect_Dict_Arguments( T1_Parser* parser, + T1_Int num_args, + T1_TokenType immediate, + T1_DictState new_state, + T1_Int *count ) + { + /* check that we have enough arguments in the stack, including */ + /* the 'dict' keyword.. */ + if ( parser->top - parser->stack < num_args ) + { + FT_ERROR(( "T1.Parse.Dict : 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(( "T1.Parse.Dict : 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(( "T1.Parse.Dict : 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 + T1_Error Expect_Array_Arguments( T1_Parser* parser ) + { + T1_Token* top = parser->top; + T1_Error error = T1_Err_Ok; + T1_DictState new_state; + T1_Int count; + T1_Face face = parser->face; + FT_Memory memory = face->root.memory; + + /* Check arguments format */ + if ( top - parser->stack < 2 ) + { + FT_ERROR(( "T1.Parse.array: 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(( "T1.Parse.array: first argument must be an immediate name\n" )); + goto Syntax_Error; + } + + if ( top[1].kind != tok_number ) + { + FT_ERROR(( "T1.Parse.array: second argument must be a number\n" )); + goto Syntax_Error; + } + count = (T1_Int)CopyInteger( parser ); + + /* Is this an array we know about ?? */ + switch ( top[0].kind2 ) + { + case imm_Encoding: + { + T1_Encoding* encode = &face->encoding; + + new_state = dict_encoding; + + encode->code_first = count; + encode->code_last = 0; + encode->num_chars = count; + + /* allocate the table of character indexes. The table of */ + /* character names is allocated through init_t1_recorder */ + if ( ALLOC_ARRAY( encode->char_index, count, T1_Short ) ) + return error; + + error = T1_New_Table( &parser->table, count, memory ); + if (error) goto Exit; + + parser->encoding_type = encoding_array; + } + break; + + + case imm_Subrs: + { + new_state = dict_subrs; + face->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 + T1_Error Finalise_Parsing( T1_Parser* parser ) + { + T1_Face face = parser->face; + FT_Memory memory = face->root.memory; + T1_Table* strings = &parser->table; + T1_Int num_glyphs; + T1_Int n; + T1_Error error; + + num_glyphs = face->num_glyphs = parser->cur_name; + + /* allocate glyph names and charstrings arrays */ + if ( ALLOC_ARRAY( face->glyph_names , num_glyphs, T1_String* ) || + ALLOC_ARRAY( face->charstrings , num_glyphs, T1_Byte* ) || + ALLOC_ARRAY( face->charstrings_len, num_glyphs, T1_Int* ) ) + return error; + + /* copy glyph names and charstrings offsets and lengths */ + face->charstrings_block = strings->block; + for ( n = 0; n < num_glyphs; n++ ) + { + face->glyph_names[n] = (T1_String*)strings->elements[2*n]; + face->charstrings[n] = strings->elements[2*n+1]; + face->charstrings_len[n] = strings->lengths [2*n+1]; + } + + /* now free the old tables */ + FREE( strings->elements ); + FREE( strings->lengths ); + + /* Compute encoding if required. */ + if (parser->encoding_type == encoding_none) + { + FT_ERROR(( "T1.Parse.Finalise : no encoding specified in font file\n" )); + return T1_Err_Syntax_Error; + } + + { + T1_Int n; + T1_Encoding* encode = &face->encoding; + + encode->code_first = encode->num_chars-1; + encode->code_last = 0; + + for ( n = 0; n < encode->num_chars; n++ ) + { + T1_String** names; + T1_Int index; + T1_Int m; + + switch (parser->encoding_type) + { + case encoding_standard: + index = t1_standard_encoding[n]; + names = (T1_String**)t1_standard_strings; + break; + + case encoding_expert: + index = t1_expert_encoding[n]; + names = (T1_String**)t1_standard_strings; + break; + + default: + index = n; + names = (T1_String**)parser->encoding_offsets; + } + encode->char_index[n] = 0; + if (index) + { + T1_String* name = names[index]; + + if ( name ) + { + T1_Int len = strlen(name); + + /* lookup glyph index from name */ + for ( m = 0; m < num_glyphs; m++ ) + { + if ( strncmp( face->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 = encoding_none; + FREE( parser->encoding_names ); + FREE( parser->encoding_lengths ); + FREE( parser->encoding_offsets ); + } + + return T1_Err_Ok; + } + + + + + + LOCAL_FUNC + T1_Error Parse_T1_FontProgram( T1_Parser* parser ) + { + T1_Error error; + + for (;;) + { + T1_Token token; + T1_Token* top; + T1_DictState dict_state; + T1_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 was detected */ + case tok_keyword: + switch (token.kind2) + { + case key_dict: + + switch (dict_state) + { + case dict_none: + /* All right, we're beggining 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; + T1_Int count; + + error = Expect_Dict_Arguments( parser, 2, imm_CharStrings, + dict_charstrings, &count ); + if (error) goto Exit; + + face->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, (T1_Byte*)".notdef", 8 ); + parser->cur_name = 1; + /* XXXXX : DO SOMETHING HERE */ + } + break; + + default: + /* All other uses are invalid */ + FT_ERROR(( "T1.Parse: invalid use of the 'dict' keyword\n" )); + goto Syntax_Error; + } + break; + + + case key_array: + /* Are we in an array yet ? Is 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(( "T1.Parse.array: 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, finalise 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: + { + T1_Face face = parser->face; + + /* copy recorder sub-routines */ + T1_Done_Table( &parser->table ); + + parser->subrs = parser->table.block; + face->subrs = parser->table.elements; + face->subrs_len = parser->table.lengths; + + parser->state_index--; + } + break; + + case dict_charstrings: + case dict_othersubrs: + case dict_unknown_array: + FT_ERROR(( "T1.Parser.def: 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 some */ + /* stupid Postscript code. We simply ignore */ + /* an invalid 'def' by clearing the stack */ +#if 0 + FT_ERROR(( "T1.Parse.def: immediate expected\n" )); + goto Syntax_Error; +#else + parser->top = parser->stack; +#endif + } + } + else + { + FT_ERROR(( "T1.Parse.def: not enough arguments\n" )); + goto Stack_Underflow; + } + } + } + break; + + + + case key_index: + if ( top <= parser->stack ) + { + FT_ERROR(( "T1.Parse.index: 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(( "T1.Parse.put: 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(( "T1.Parse.put: invalid context\n" )); + goto Syntax_Error; +#else + /* invalid context, simply ignore the put and */ + /* clear the stack (stupid Postscript code..) */ + FT_TRACE4(( "T1.Parse.put: 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(( "T1.Parse.RD: 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(( "T1.Parse.RD: 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(( "T1.Parse.end: no dictionary defined\n" )); + goto Syntax_Error; + } + + switch (dict_state) + { + /* Jump to the private dictionary if we're closing the */ + /* /Font dictionary.. */ + case dict_font: + goto Open_Private; + + /* Exit the parser when closing the CharStrings dictionary */ + case dict_charstrings: + return Finalise_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--; + + error = Expect_Keyword2( parser, key_def, key_put ); + if (error) goto Exit; + } + break; + + + + case key_for: + /* check that we have four arguments, and simply */ + /* ignore them.. */ + if ( top - parser->stack < 4 ) + { + FT_ERROR(( "T1.Parse.for: 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(( "T1.Parser: invalid keyword in context\n" )); + error = T1_Err_Syntax_Error; + } + break; + + /* A number was detected */ + case tok_string: + case tok_program: + case tok_immediate: + 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 encountre 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; + } + diff --git a/src/type1/t1load.h b/src/type1/t1load.h new file mode 100644 index 000000000..9e0ee4736 --- /dev/null +++ b/src/type1/t1load.h @@ -0,0 +1,72 @@ +/******************************************************************* + * + * t1load.h 1.0 + * + * Type1 Loader. + * + * Copyright 1996-1998 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.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 +#include + +#ifdef __cplusplus + extern "C" { +#endif + + /*************************************************************************/ + /* */ + /* Init_T1_Parser */ + /* */ + /* */ + /* Initialise a given parser object to build a given T1_Face */ + /* */ + /* */ + /* parser :: handle to the newly built parser object */ + /* face :: handle to target T1 face object */ + /* */ + LOCAL_DEF + void Init_T1_Parser( T1_Parser* parser, + T1_Face face, + T1_Tokenizer tokenizer ); + + + /*************************************************************************/ + /* */ + /* Parse_T1_FontProgram */ + /* */ + /* */ + /* Parses a given Type 1 font file and builds its face object */ + /* */ + /* */ + /* parser :: handle to target parser object */ + /* */ + /* */ + /* Error code. 0 means success.. */ + /* */ + /* */ + /* The parser contains a handle to the target face object. */ + /* */ + LOCAL_DEF + T1_Error Parse_T1_FontProgram( T1_Parser* parser ); + + +#ifdef __cplusplus + } +#endif + +#endif /* T1LOAD_H */ + + +/* END */ diff --git a/src/type1/t1objs.c b/src/type1/t1objs.c new file mode 100644 index 000000000..88d77f50e --- /dev/null +++ b/src/type1/t1objs.c @@ -0,0 +1,414 @@ +/******************************************************************* + * + * t1objs.c 1.0 + * + * Type1 Objects manager. + * + * Copyright 1996-1998 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.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 + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER +#include +#endif + +/* Required by tracing mode */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_t1objs + +/******************************************************************* + * * + * SIZE FUNCTIONS * + * * + * * + *******************************************************************/ + +/******************************************************************* + * + * T1_Done_Size + * + * + * The TrueDoc instance object destructor. Used to discard + * a given instance object.. + * + * + * instance :: handle to the target instance object + * + * + * TrueDoc error code. 0 means success + * + ******************************************************************/ + + 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 instance object constructor + * + * + * instance : handle to new instance object + * face : pointer to parent face object + * + * + * TrueDoc error code. 0 means success. + * + ******************************************************************/ + + LOCAL_DEF + T1_Error T1_Init_Size( T1_Size size ) + { + T1_Error error; + + size->valid = 0; + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER + error = T1_New_Size_Hinter( size ); + return error; +#else + (void)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, + * As well as the stem snap tables for a given size.. + * + * + * instance the instance object to destroy + * + * + * Error code. + * + ******************************************************************/ + + LOCAL_FUNC + T1_Error T1_Reset_Size( T1_Size size ) + { +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER + return T1_Reset_Size_Hinter( size ); +#else + (void)size; + return 0; +#endif + } + + +/******************************************************************* + * * + * FACE FUNCTIONS * + * * + * * + *******************************************************************/ + +/******************************************************************* + * + * T1_Done_Face + * + * + * The face object destructor. + * + * + * face :: typeless pointer to the face object to destroy + * + * + * Error code. + * + ******************************************************************/ + + LOCAL_FUNC + void T1_Done_Face( T1_Face face ) + { + FT_Memory memory; + + if (face) + { + memory = face->root.memory; + /* XXXX : TO DO */ + } + } + +/******************************************************************* + * + * T1_Init_Face + * + * + * The face object constructor. + * + * + * face :: face record to build + * Input :: input stream where to load font data + * + * + * Error code. + * + ******************************************************************/ + + LOCAL_FUNC + T1_Error T1_Init_Face( FT_Stream stream, + FT_Int face_index, + T1_Face face ) + { + T1_Tokenizer tokenizer; + T1_Error error; + + (void)face_index; + (void)face; + + face->root.num_faces = 1; + + /* 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; + + root->num_glyphs = face->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; + + if ( face->font_info.is_fixed_pitch ) + root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; + + /* XXX : TO DO - add kerning with .afm support */ + + /* get style name - be careful, some broken fonts only */ + /* have a /FontName dictionary entry .. !! */ + root->family_name = face->font_info.family_name; + if (root->family_name) + { + char* full = face->font_info.full_name; + char* family = root->family_name; + + while ( *family && *full == *family ) + { + family++; + full++; + } + + root->style_name = ( *full == ' ' ? full+1 : "Regular" ); + } + else + { + /* do we have a /FontName ?? */ + if (face->font_name) + { + root->family_name = face->font_name; + root->style_name = "Regular"; + } + } + + /* no embedded bitmap support */ + root->num_fixed_sizes = 0; + root->available_sizes = 0; + + root->bbox = face->font_bbox; + root->units_per_EM = 1000; + root->ascender = (T1_Short)face->font_bbox.yMax; + root->descender = -(T1_Short)face->font_bbox.yMin; + root->height = ((root->ascender + root->descender)*12)/10; + + /* now compute the maximum advance width */ + + root->max_advance_width = face->private_dict.standard_width; + + /* compute max advance width for proportional fonts */ + if (!face->font_info.is_fixed_pitch) + { + T1_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 = face->font_info.underline_position; + root->underline_thickness = face->font_info.underline_thickness; + + root->max_points = 0; + root->max_contours = 0; + } + } + + Leave: + Done_Tokenizer( tokenizer ); + + Fail: + return error; + } + + +/******************************************************************* + * + * Function : Glyph_Destroy + * + * Description : The glyph object destructor. + * + * Input : _glyph typeless pointer to the glyph record to destroy + * + * Output : Error code. + * + ******************************************************************/ + + LOCAL_FUNC + void T1_Done_GlyphSlot( T1_GlyphSlot glyph ) + { + FT_Memory memory = glyph->root.face->memory; + FT_Library library = glyph->root.face->driver->library; + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER + T1_Done_Glyph_Hinter( glyph ); +#endif + /* the bitmaps are created on demand */ + FREE( glyph->root.bitmap.buffer ); + FT_Done_Outline( library, &glyph->root.outline ); + return; + } + + +/******************************************************************* + * + * Function : Glyph_Create + * + * Description : The glyph object constructor. + * + * Input : glyph glyph record to build. + * face the glyph's parent face. + * + * Output : Error code. + * + ******************************************************************/ + + LOCAL_FUNC + T1_Error T1_Init_GlyphSlot( T1_GlyphSlot glyph ) + { + FT_Library library = glyph->root.face->driver->library; + T1_Error error; + + glyph->max_points = 0; + glyph->max_contours = 0; + glyph->root.bitmap.buffer = 0; + + error = FT_New_Outline( library, 0, 0, &glyph->root.outline ); + if (error) return error; + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER + error = T1_New_Glyph_Hinter( glyph ); + if (error) + FT_Done_Outline( library, &glyph->root.outline ); +#endif + + return error; + } + + +/******************************************************************* + * + * T1_Init_Driver + * + * + * Initialise a given Type 1 driver object + * + * + * driver :: handle to target driver object + * + * + * Error code. + * + ******************************************************************/ + + LOCAL_FUNC + T1_Error T1_Init_Driver( T1_Driver driver ) + { + (void)driver; + return T1_Err_Ok; + } + + + +/******************************************************************* + * + * T1_Done_Driver + * + * + * finalise a given Type 1 driver + * + * + * driver :: handle to target Type 1 driver + * + ******************************************************************/ + + LOCAL_DEF + void T1_Done_Driver( T1_Driver driver ) + { + (void)driver; + } + + +/* END */ diff --git a/src/type1/t1objs.h b/src/type1/t1objs.h new file mode 100644 index 000000000..417ae5380 --- /dev/null +++ b/src/type1/t1objs.h @@ -0,0 +1,302 @@ +/******************************************************************* + * + * t1objs.h 1.0 + * + * Type1 objects definition. + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.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; + + + + /**************************************************************************/ + /* */ + /* NOW BEGINS THE TYPE1 SPECIFIC STUFF .............................. */ + /* */ + /**************************************************************************/ + + + /***************************************************/ + /* */ + /* T1_Size : */ + /* */ + /* Type 1 size record.. */ + /* */ + + typedef struct T1_SizeRec_ + { + FT_SizeRec root; + T1_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_GlyphSlot : */ + /* */ + /* TrueDoc glyph record.. */ + /* */ + + typedef struct T1_GlyphSlotRec_ + { + FT_GlyphSlotRec root; + + T1_Bool hint; + T1_Bool scaled; + + T1_Int max_points; + T1_Int max_contours; + + FT_Fixed x_scale; + FT_Fixed y_scale; + + T1_Glyph_Hints* hints; /* defined in the hinter */ + + } T1_GlyphSlotRec; + + +/******************************************************************* + * + * T1_Init_Face + * + * + * Initialise a given Type 1 face object + * + * + * face_index :: index of font face in resource + * resource :: source font resource + * face :: face record to build + * + * + * Error code. + * + ******************************************************************/ + + LOCAL_DEF + T1_Error T1_Init_Face( FT_Stream stream, + FT_Int face_index, + T1_Face face ); + + + +/******************************************************************* + * + * T1_Done_Face + * + * + * Finalise a given face object + * + * + * face :: handle to the face object to destroy + * + ******************************************************************/ + + LOCAL_DEF + void T1_Done_Face( T1_Face face ); + + + +/******************************************************************* + * + * T1_Init_Size + * + * + * Initialise a new Type 1 size object + * + * + * size :: handle to size object + * + * + * Type 1 error code. 0 means success. + * + ******************************************************************/ + + LOCAL_DEF + T1_Error T1_Init_Size( T1_Size size ); + + + +/******************************************************************* + * + * T1_Done_Size + * + * + * The Type 1 size object finaliser. + * + * + * size :: handle to the target size object. + * + ******************************************************************/ + + LOCAL_DEF + void T1_Done_Size( T1_Size size ); + + +/******************************************************************* + * + * T1_Reset_Size + * + * + * Reset a Type 1 size when resolutions and character dimensions + * have been changed.. + * + * + * size :: handle to the target size object. + * + ******************************************************************/ + + LOCAL_DEF + T1_Error T1_Reset_Size( T1_Size size ); + + + +/******************************************************************* + * + * T1_Init_GlyphSlot + * + * The TrueType glyph slot initialiser + * + * glyph :: glyph record to build. + * + * Error code. + * + ******************************************************************/ + + LOCAL_DEF + T1_Error T1_Init_GlyphSlot( T1_GlyphSlot slot ); + + + +/******************************************************************* + * + * T1_Done_GlyphSlot + * + * The Type 1 glyph slot finaliser + * + * glyph :: handle to glyph slot object + * + * Error code. + * + ******************************************************************/ + + LOCAL_DEF + void T1_Done_GlyphSlot( T1_GlyphSlot slot ); + + + +/******************************************************************* + * + * T1_Init_Driver + * + * + * Initialise a given Type 1 driver object + * + * + * driver :: handle to target driver object + * + * + * Error code. + * + ******************************************************************/ + + LOCAL_DEF + T1_Error T1_Init_Driver( T1_Driver driver ); + + + +/******************************************************************* + * + * T1_Done_Driver + * + * + * finalise a given Type 1 driver + * + * + * driver :: handle to target Type 1 driver + * + ******************************************************************/ + + LOCAL_DEF + void T1_Done_Driver( T1_Driver driver ); + +#ifdef __cplusplus + } +#endif + +#endif /* T1OBJS_H */ + + +/* END */ diff --git a/src/type1/t1parse.c b/src/type1/t1parse.c new file mode 100644 index 000000000..e3710b07f --- /dev/null +++ b/src/type1/t1parse.c @@ -0,0 +1,665 @@ +#include +#include +#include + +#include /* for sscanf */ + +/*************************************************************************/ +/* */ +/* T1_New_Table */ +/* */ +/* */ +/* Initialise a T1_Table. */ +/* */ +/* */ +/* table :: address of target table */ +/* count :: table size = maximum number of elements */ +/* memory :: memory object to use for all subsequent reallocations */ +/* */ +/* */ +/* Error code. 0 means success */ +/* */ + + LOCAL_FUNC + T1_Error T1_New_Table( T1_Table* table, + T1_Int count, + FT_Memory memory ) + { + T1_Error error; + + table->memory = memory; + if ( ALLOC_ARRAY( table->elements, count, T1_Byte* ) ) + return error; + + if ( ALLOC_ARRAY( table->lengths, count, T1_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; + } + + + +/*************************************************************************/ +/* */ +/* T1_Add_Table */ +/* */ +/* */ +/* Adds an object to a T1_Table, possibly growing its memory block */ +/* */ +/* */ +/* table :: target table */ +/* index :: index of object in table */ +/* object :: address of object to copy in memory */ +/* length :: length in bytes of source object */ +/* */ +/* */ +/* Error code. 0 means success. An error is returned when a */ +/* realloc failed.. */ +/* */ + + static + T1_Error reallocate_t1_table( T1_Table* table, + T1_Int new_size ) + { + FT_Memory memory = table->memory; + T1_Byte* old_base = table->block; + T1_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) + { + T1_Long delta = table->block - old_base; + T1_Byte** offset = table->elements; + T1_Byte** limit = offset + table->max_elems; + + if (delta) + for ( ; offset < limit; offset ++ ) + if (offset[0]) + offset[0] += delta; + } + + return T1_Err_Ok; + } + + + LOCAL_FUNC + T1_Error T1_Add_Table( T1_Table* table, + T1_Int index, + void* object, + T1_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 ) + { + T1_Error error; + T1_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 */ +/* */ +/* */ +/* Finalise a T1_Table. (realloc it to its current cursor). */ +/* */ +/* */ +/* table :: 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; + T1_Error error; + T1_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) + { + T1_Long delta = table->block - old_base; + T1_Byte** element = table->elements; + T1_Byte** limit = element + table->max_elems; + + for ( ; element < limit; element++ ) + if (element[0]) + element[0] += delta; + } + } + + + LOCAL_FUNC + T1_String* CopyString( T1_Parser* parser ) + { + T1_String* string = NULL; + T1_Token* token = parser->args++; + FT_Memory memory = parser->tokenizer->memory; + T1_Error error; + + if ( token->kind == tok_string ) + { + 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 + T1_Error parse_int( T1_Byte* base, + T1_Byte* limit, + T1_Long* result ) + { + T1_Bool sign = 0; + T1_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(( "T1.parse_integer : integer expected\n" )); + *result = 0; + return T1_Err_Syntax_Error; + } + + + + + static + T1_Error parse_float( T1_Byte* base, + T1_Byte* limit, + T1_Int scale, + T1_Long* result ) + { +#if 1 + /* XXX : We're simply much too lazy to code this function */ + /* properly for now.. We'll 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 = (T1_Long)(scale*value); + return 0; + +#else + T1_Byte* cur; + T1_Bool sign = 0; /* sign */ + T1_Long number_int = 0; /* integer part */ + T1_Long number_frac = 0; /* fractional part */ + T1_Long exponent = 0; /* exponent value */ + T1_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 ) + { + T1_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 ) + { + T1_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 */ + /* XXXXX : incomplete !!! */ +#endif + + Fail: + FT_ERROR(( "T1.parse_float : syntax error !\n" )); + return T1_Err_Syntax_Error; + } + + + + static + T1_Error parse_integer( T1_Byte* base, + T1_Byte* limit, + T1_Long* result ) + { + T1_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 ) + { + T1_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.. */ + { + T1_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 + T1_Long CopyInteger( T1_Parser* parser ) + { + T1_Long sum = 0; + T1_Token* token = parser->args++; + + if ( token->kind == tok_number ) + { + T1_Byte* base = parser->tokenizer->base + token->start; + T1_Byte* limit = base + token->len; + + /* now read the number's value */ + parser->error = parse_integer( base, limit, &sum ); + return sum; + } + + FT_ERROR(( "T1.CopyInteger : number expected\n" )); + parser->args--; + parser->error = T1_Err_Syntax_Error; + return 0; + } + + + + LOCAL_FUNC + T1_Bool CopyBoolean( T1_Parser* parser ) + { + T1_Error error = T1_Err_Ok; + T1_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(( "T1.CopyBoolean : syntax error, 'false' or 'true' expected\n" )); + error = T1_Err_Syntax_Error; + } + parser->error = error; + return result; + } + + + + + LOCAL_FUNC + T1_Long CopyFloat( T1_Parser* parser, + T1_Int scale ) + { + T1_Error error; + T1_Long sum = 0; + T1_Token* token = parser->args++; + + if ( token->kind == tok_number ) + { + T1_Byte* base = parser->tokenizer->base + token->start; + T1_Byte* limit = base + token->len; + + error = parser->error = parse_float( base, limit, scale, &sum ); + if (error) goto Fail; + + return sum; + } + + Fail: + FT_ERROR(( "T1.CopyFloat : syntax error !\n" )); + parser->error = T1_Err_Syntax_Error; + return 0; + } + + + + + + + LOCAL_FUNC + void CopyBBox( T1_Parser* parser, + T1_BBox* bbox ) + { + T1_Token* token = parser->args++; + T1_Int n; + T1_Error error; + + if ( token->kind == tok_program || + token->kind == tok_array ) + { + /* get rid of '['/']', or '{'/'}' */ + T1_Byte* base = parser->tokenizer->base + token->start + 1; + T1_Byte* limit = base + token->len - 1; + T1_Byte* cur; + T1_Byte* start; + + /* read each parameter independently */ + cur = base; + for ( n = 0; n < 4; n++ ) + { + T1_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(( "T1.CopyBBox : syntax error !\n" )); + parser->error = T1_Err_Syntax_Error; + } + + + + + LOCAL_FUNC + void CopyMatrix( T1_Parser* parser, + T1_Matrix* matrix ) + { + T1_Token* token = parser->args++; + T1_Error error; + + if ( token->kind == tok_array ) + { + /* get rid of '[' and ']' */ + T1_Byte* base = parser->tokenizer->base + token->start + 1; + T1_Byte* limit = base + token->len - 1; + T1_Byte* cur; + T1_Byte* start; + T1_Int n; + + /* read each parameter independently */ + cur = base; + for ( n = 0; n < 4; n++ ) + { + T1_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->xy; break; + case 2 : result = &matrix->yx; break; + default: result = &matrix->yy; + } + + error = parse_float( start, cur, 65536000, result ); + if (error) goto Fail; + } + parser->error = 0; + return; + } + + Fail: + FT_ERROR(( "T1.CopyMatrix : syntax error !\n" )); + parser->error = T1_Err_Syntax_Error; + } + + + + LOCAL_FUNC + void CopyArray( T1_Parser* parser, + T1_Byte* num_elements, + T1_Short* elements, + T1_Int max_elements ) + { + T1_Token* token = parser->args++; + T1_Error error; + + if ( token->kind == tok_array || + token->kind == tok_program ) /* in the case of MinFeature */ + { + /* get rid of '['/']', or '{'/'}' */ + T1_Byte* base = parser->tokenizer->base + token->start + 1; + T1_Byte* limit = base + token->len - 2; + T1_Byte* cur; + T1_Byte* start; + T1_Int n; + + /* read each parameter independently */ + cur = base; + for ( n = 0; n < max_elements; n++ ) + { + T1_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 ++ = (T1_Short)result; + } + + if (num_elements) + *num_elements = (T1_Byte)n; + + parser->error = 0; + return; + } + + Fail: + FT_ERROR(( "T1.CopyArray : syntax error !\n" )); + parser->error = T1_Err_Syntax_Error; + } + diff --git a/src/type1/t1parse.h b/src/type1/t1parse.h new file mode 100644 index 000000000..4bb718168 --- /dev/null +++ b/src/type1/t1parse.h @@ -0,0 +1,296 @@ +/******************************************************************* + * + * t1parse.h 1.0 + * + * Type1 parser. + * + * Copyright 1996-1998 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.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 +#include + +#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; + + + typedef enum T1_EncodingType_ + { + encoding_none = 0, + encoding_array, + encoding_standard, + encoding_expert + + } T1_EncodingType; +/************************************************************************* + * + * T1_Table + * + * + * A T1_Table is a simple object used to store an array of objects + * in a single memory block. + * + * + * block :: address in memory of the growheap's block. This + * can change between two object adds, due to the use + * of 'realloc'. + * + * cursor :: current top of the grow heap within its block + * + * capacity :: current size of the heap block. Increments by 1 Kb + * + * max_elems :: maximum number of elements in table + * num_elems :: current number of elements in table + * + * elements :: table of element addresses within the block + * lengths :: table of element sizes within the block + * + * system :: system object used for memory operations (alloc/realloc) + */ + + typedef struct T1_Table_ + { + T1_Byte* block; /* current memory block */ + T1_Int cursor; /* current cursor in memory block */ + T1_Int capacity; /* current size of memory block */ + + T1_Int max_elems; + T1_Int num_elems; + T1_Byte** elements; /* addresses of table elements */ + T1_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 :: */ +/* 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. */ +/* */ +/* stack :: */ +/* the current token stack. Note that we don't use intermediate */ +/* Postscript objects here ! */ +/* */ +/* top :: */ +/* current top of token stack */ +/* */ +/* limit :: */ +/* current upper bound of the token stack. Used for overflow */ +/* checks.. */ +/* */ +/* args :: */ +/* arguments of a given operator. used and increased by the */ +/* Copy.... functions.. */ +/* */ +/* state_index :: */ +/* index of top of the dictionary state stack */ +/* */ +/* state_stack :: */ +/* dictionary states stack */ +/* */ +/* table :: */ +/* a T1_Table object used to record various kinds of */ +/* dictionaries or arrays (like /Encoding, /Subrs, /CharStrings) */ +/* */ +/* */ + typedef struct T1_Parser_ + { + T1_Error error; + T1_Face face; + + T1_Tokenizer tokenizer; + T1_Bool dump_tokens; + + T1_Token stack[ T1_MAX_STACK_DEPTH ]; + T1_Token* top; + T1_Token* limit; + T1_Token* args; + + T1_Int state_index; + T1_DictState state_stack[ T1_MAX_DICT_DEPTH ]; + + T1_Table table; + + T1_Int cur_name; + + T1_EncodingType encoding_type; + T1_Byte* encoding_names; + T1_Int* encoding_lengths; + T1_Byte** encoding_offsets; + + T1_Byte* subrs; + T1_Byte* charstrings; + + } T1_Parser; + + + +/*************************************************************************/ +/* */ +/* T1_New_Table */ +/* */ +/* */ +/* Initialise a T1_Table. */ +/* */ +/* */ +/* table :: address of target table */ +/* count :: table size = maximum number of elements */ +/* system :: system object to use for all subsequent reallocations */ +/* */ +/* */ +/* Error code. 0 means success */ +/* */ + LOCAL_DEF + T1_Error T1_New_Table( T1_Table* table, + T1_Int count, + FT_Memory memory ); + + +/*************************************************************************/ +/* */ +/* T1_Add_Table */ +/* */ +/* */ +/* Adds an object to a T1_Table, possibly growing its memory block */ +/* */ +/* */ +/* table :: target table */ +/* index :: index of object in table */ +/* object :: address of object to copy in memory */ +/* length :: length in bytes of source object */ +/* */ +/* */ +/* Error code. 0 means success. An error is returned when a */ +/* realloc failed.. */ +/* */ + LOCAL_DEF + T1_Error T1_Add_Table( T1_Table* table, + T1_Int index, + void* object, + T1_Int length ); + + +/*************************************************************************/ +/* */ +/* T1_Done_Table */ +/* */ +/* */ +/* Finalise a T1_Table. (realloc it to its current cursor). */ +/* */ +/* */ +/* table :: 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_DEF + void T1_Done_Table( T1_Table* table ); + + + + + LOCAL_DEF + T1_String* CopyString( T1_Parser* parser ); + + + LOCAL_DEF + T1_Long CopyInteger( T1_Parser* parser ); + + + LOCAL_DEF + T1_Bool CopyBoolean( T1_Parser* parser ); + + + LOCAL_DEF + T1_Long CopyFloat( T1_Parser* parser, + T1_Int scale ); + + LOCAL_DEF + void CopyBBox( T1_Parser* parser, + T1_BBox* bbox ); + + LOCAL_DEF + void CopyMatrix( T1_Parser* parser, + T1_Matrix* matrix ); + + LOCAL_DEF + void CopyArray( T1_Parser* parser, + T1_Byte* num_elements, + T1_Short* elements, + T1_Int max_elements ); + +#ifdef __cplusplus + } +#endif + +#endif /* T1PARSE_H */ + + +/* END */ + diff --git a/src/type1/t1tokens.c b/src/type1/t1tokens.c new file mode 100644 index 000000000..7069d691d --- /dev/null +++ b/src/type1/t1tokens.c @@ -0,0 +1,994 @@ +/******************************************************************* + * + * t1tokens.c + * + * Type 1 tokenizer + * + * Copyright 1996 David Turner, Robert Wilhelm and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.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 extract 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 + +#include +#include + +#undef READ_BUFFER_INCREMENT +#define READ_BUFFER_INCREMENT 0x400 + +#undef FT_COMPONENT +#define FT_COMPONENT trace_t1load + + /* array of Type1 keywords supported by this engine. This table places */ + /* the keyword in lexicographical order. It should always correspond */ + /* to the enums key_XXXX !! */ + /* */ + 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", "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, perform binary search */ + static + int Find_Name( char* base, int length, + const char** table, int table_len ) + { + /* performs a binary search */ + + T1_Int left, right; + + left = 0; + right = table_len-1; + + while ( right-left > 1 ) + { + T1_Int middle = left + (( right-left ) >> 1); + T1_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 + T1_Error Read_PFB_Tag( FT_Stream stream, + T1_UShort* atag, + T1_ULong* asize ) + { + T1_UShort tag; + T1_ULong size; + T1_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 + T1_Error grow( T1_Tokenizer tokzer ) + { + T1_Error error; + T1_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 )); + + (void)stream; /* unused in non reentrant mode */ + + 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; + } + + + + + LOCAL_FUNC + void t1_decrypt( T1_Byte* buffer, + T1_Int length, + T1_UShort seed ) + { + while ( length > 0 ) + { + T1_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 :: input stream */ + /* */ + /* */ + /* tokenizer :: handle to new tokenizer object.. */ + /* */ + /* */ + /* Type1 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 + T1_Error New_Tokenizer( FT_Stream stream, + T1_Tokenizer* tokenizer ) + { + FT_Memory memory = stream->memory; + T1_Tokenizer tokzer; + T1_Error error; + T1_UShort tag; + T1_ULong size; + + T1_Byte* tok_base; + T1_ULong tok_limit; + T1_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's a memory-based resource, set up pointer */ + if ( !stream->read ) + { + tok_base = (T1_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 a '%!PS-AdobeFont-1' */ + /* or a '%!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 = T1_Err_Invalid_File_Format; + goto Fail; + } + } + return T1_Err_Ok; + + Fail: + 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 :: target tokenizer object */ + /* */ + /* */ + /* Type1 error code. 0 means success.. */ + /* */ + + LOCAL_FUNC + T1_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 :: target tokenizer object */ + /* lenIV :: value of the "lenIV" variable.. */ + /* */ + /* */ + /* Type1 error code. 0 means success.. */ + /* */ + + LOCAL_FUNC + T1_Error Open_PrivateDict( T1_Tokenizer tokenizer ) + { + T1_Tokenizer tokzer = tokenizer; + FT_Stream stream = tokzer->stream; + FT_Memory memory = tokzer->memory; + T1_Error error = 0; + + T1_UShort tag; + T1_ULong size; + + T1_Byte* private; + + /* 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.. */ + T1_Long start_pos = FILE_Pos(); + T1_ULong private_size = 0; + + do + { + error = Read_PFB_Tag( stream, &tag, &size ); + if (error || tag != 0x8002) break; + + private_size += size; + + if ( FILE_Skip(size) ) + goto Fail; + } + while (1); + + /* Check that we have a private dictionary there */ + /* and allocate private dictionary buffer */ + if ( private_size == 0 ) + { + FT_ERROR(( "T1.Open_Private: invalid private dictionary section\n" )); + error = T1_Err_Invalid_File_Format; + goto Fail; + } + + if ( ALLOC( private, private_size ) ) + goto Fail; + + /* read all sections into buffer */ + if ( FILE_Seek( start_pos ) ) + goto Fail_Private; + + private_size = 0; + do + { + error = Read_PFB_Tag( stream, &tag, &size ); + if (error || tag != 0x8002) { error = 0; break; } + + if ( FILE_Read( private + private_size, size ) ) + goto Fail_Private; + + private_size += size; + } + while (1); + + tokzer->base = private; + tokzer->cursor = 0; + tokzer->limit = private_size; + tokzer->max = private_size; + } + else + { + char* base; + + /* we're 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 wether 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's a memory-based resource, we need to allocate a new */ + /* storage buffer for the private dictionary, as it needs to */ + /* be decrypted later.. */ + if ( stream->base ) + { + size = stream->size - tokzer->cursor-1; /* remaining bytes */ + + if ( ALLOC( private, size ) ) /* allocate private dict buffer */ + goto Fail; + + /* copy eexec-encrypted bytes */ + MEM_Copy( private, tokzer->base + tokzer->cursor+1, size ); + + /* reset pointers - forget about file mapping */ + tokzer->base = private; + 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're 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.. */ + T1_Byte* write; + T1_Byte* cur; + T1_Byte* limit; + T1_Int count; + + /* Allocate a buffer, read each one byte at a time .. */ + count = ( stream->size - tokzer->cursor ); + size = count/2; + + if ( ALLOC( private, size ) ) /* allocate private dict buffer */ + goto Fail; + + write = private; + 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 hexa-decimal 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; + 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 ); + goto Fail; + } + + + /*************************************************************************/ + /* */ + /* Read_Token */ + /* */ + /* */ + /* Read 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 dictionnary.. */ + /* */ + /* */ + /* tokenizer :: target tokenizer object */ + /* */ + /* */ + /* Type1 error code. 0 means success.. */ + /* */ + /* */ + /* One should use the function Read_CharStrings to read the binary */ + /* charstrings from the private dict.. */ + /* */ + LOCAL_FUNC + T1_Error Read_Token( T1_Tokenizer tokenizer ) + { + T1_Tokenizer tok = tokenizer; + T1_Long cur, limit; + T1_Byte* base; + char c, starter, ender; + T1_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 ( (T1_Byte)c > 127 ) + { + 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 (;;) + { + T1_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; + } + + { + T1_Int nest_level = 1; + + starter = c; + for (;;) + { + T1_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 (;;) + { + T1_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 (;;) + { + T1_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 (;;) + { + T1_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 */ + T1_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 ? imm_first_ + index : 0 ); + 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 = key_first_ + index; + } + else + tok->token.kind2 = 0; + break; + + default: + tok->token.kind2 = 0; + } + } + return tokenizer->error; + } + + + /*************************************************************************/ + /* */ + /* Read_CharStrings */ + /* */ + /* */ + /* Read a charstrings 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 :: target tokenizer object */ + /* num_chars :: number of binary bytes to read */ + /* */ + /* */ + /* buffer :: target array of bytes. These are eexec-decrypted.. */ + /* */ + /* */ + /* Type1 error code. 0 means success.. */ + /* */ + /* */ + /* One should use the function Read_CharStrings to read the binary */ + /* charstrings from the private dict.. */ + /* */ + LOCAL_FUNC + T1_Error Read_CharStrings( T1_Tokenizer tokenizer, + T1_Int num_chars, + T1_Byte* buffer ) + { + for (;;) + { + T1_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; + } + } + diff --git a/src/type1/t1tokens.h b/src/type1/t1tokens.h new file mode 100644 index 000000000..d83148bd6 --- /dev/null +++ b/src/type1/t1tokens.h @@ -0,0 +1,352 @@ +/******************************************************************* + * + * t1tokens.h + * + * Type 1 tokenizer + * + * Copyright 1996 David Turner, Robert Wilhelm and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.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 extract 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.. + * + ******************************************************************/ + +#ifndef T1TOKENS_H +#define T1TOKENS_H + +#include + +/* 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_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 :: token type. Describes the token to the loader */ + /* kind2 :: detailed token type. */ + /* */ + /* start :: index of first character of token in input stream */ + /* */ + /* len :: length of token in characters. */ + /* */ + typedef struct T1_Token_ + { + T1_TokenType kind; /* simple type */ + T1_TokenType kind2; /* detailed type */ + T1_Int start; /* index of first token character */ + T1_Int len; /* length of token in chars */ + + } T1_Token; + + + + + typedef struct T1_TokenParser_ + { + FT_Memory memory; + FT_Stream stream; + + T1_Bool in_pfb; /* true if PFB file, PFA otherwise */ + T1_Bool in_private; /* true if in private dictionary */ + + T1_Byte* base; /* base address of current read buffer */ + T1_Long cursor; /* current position in read buffer */ + T1_Long limit; /* limit of current read buffer */ + T1_Long max; /* maximum size of read buffer */ + + T1_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; + + + /*************************************************************************/ + /* */ + /* 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 :: input stream */ + /* */ + /* */ + /* tokenizer :: handle to new tokenizer object.. */ + /* */ + /* */ + /* Type1 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_DEF + T1_Error New_Tokenizer( FT_Stream stream, + T1_Tokenizer* tokenizer ); + + + + /*************************************************************************/ + /* */ + /* Done_Tokenizer */ + /* */ + /* */ + /* Closes a given tokenizer. This function will also close the */ + /* stream embedded in the object.. */ + /* */ + /* */ + /* tokenizer :: target tokenizer object */ + /* */ + /* */ + /* Type1 error code. 0 means success.. */ + /* */ + LOCAL_DEF + T1_Error Done_Tokenizer( T1_Tokenizer tokenizer ); + + + + /*************************************************************************/ + /* */ + /* 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 :: target tokenizer object */ + /* lenIV :: value of the "lenIV" variable.. */ + /* */ + /* */ + /* Type1 error code. 0 means success.. */ + /* */ + LOCAL_DEF + T1_Error Open_PrivateDict( T1_Tokenizer tokenizer ); + + + + /*************************************************************************/ + /* */ + /* Read_Token */ + /* */ + /* */ + /* Read 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 dictionnary.. */ + /* */ + /* */ + /* tokenizer :: target tokenizer object */ + /* */ + /* */ + /* Type1 error code. 0 means success.. */ + /* */ + /* */ + /* One should use the function Read_CharStrings to read the binary */ + /* charstrings from the private dict.. */ + /* */ + LOCAL_DEF + T1_Error Read_Token( T1_Tokenizer tokenizer ); + + + + /*************************************************************************/ + /* */ + /* Read_CharStrings */ + /* */ + /* */ + /* Read a charstrings from the current input stream. These are */ + /* binary bytes that encode each individual glyph outline. */ + /* */ + /* */ + /* tokenizer :: target tokenizer object */ + /* num_chars :: number of binary bytes to read */ + /* */ + /* */ + /* buffer :: target array of bytes. These are eexec-decrypted.. */ + /* */ + /* */ + /* Type1 error code. 0 means success.. */ + /* */ + /* */ + /* One should use the function Read_CharStrings to read the binary */ + /* charstrings from the private dict.. */ + /* */ + LOCAL_DEF + T1_Error Read_CharStrings( T1_Tokenizer tokenizer, + T1_Int num_chars, + T1_Byte* buffer ); + + + /*************************************************************************/ + /* */ + /* t1_decrypt */ + /* */ + /* */ + /* Performs the Type 1 charstring decryption process.. */ + /* */ + /* */ + /* buffer :: base address of data to decrypt */ + /* length :: number of bytes to decrypt from base address */ + /* seed :: ecnryption seed (4330 for charstrings). */ + /* */ + LOCAL_DEF + void t1_decrypt( T1_Byte* buffer, + T1_Int length, + T1_UShort seed ); + +#endif /* T1TOKENS_H */ diff --git a/src/type1/type1.c b/src/type1/type1.c new file mode 100644 index 000000000..f7058d0b1 --- /dev/null +++ b/src/type1/type1.c @@ -0,0 +1,50 @@ +/***************************************************************************/ +/* */ +/* type1.c */ +/* */ +/* FreeType Type 1 driver component */ +/* */ +/* Copyright 1996-1998 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.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 compile the FreeType Type 1 font driver. */ +/* It relies on all components included in the "base" layer (see */ +/* the file "ftbase.c"). Source code is located in "freetype/ttlib" */ +/* and contains : */ +/* */ +/* - a driver interface */ +/* - an object manager */ +/* - a table loader */ +/* - a glyph loader */ +/* - a glyph hinter */ +/* */ +/***************************************************************************/ + + + +#if 0 +#define FT_MAKE_OPTION_SINGLE_OBJECT +#include /* driver interface */ +#include /* object manager */ +#include /* table loader */ +#include /* hinter */ +#include /* glyph loader */ +#endif + +#include +#include +#include /* table loader */ +#include + +#include +#include +#include +#include +