summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xtools/gslite/CenturySchL-Bold.ttfbin0 -> 95828 bytes
-rw-r--r--tools/gslite/Makefile81
-rw-r--r--tools/gslite/README208
-rw-r--r--tools/gslite/gslite-api.rtf349
-rw-r--r--tools/gslite/gslt.c1276
-rw-r--r--tools/gslite/gslt.h6
-rw-r--r--tools/gslite/gslt.mak56
-rw-r--r--tools/gslite/gslt_alloc.c18
-rw-r--r--tools/gslite/gslt_alloc.h2
-rw-r--r--tools/gslite/gslt_font.h138
-rw-r--r--tools/gslite/gslt_font_cache.c174
-rw-r--r--tools/gslite/gslt_font_cff.c967
-rw-r--r--tools/gslite/gslt_font_encoding.c183
-rw-r--r--tools/gslite/gslt_font_glyph.c325
-rw-r--r--tools/gslite/gslt_font_int.h107
-rw-r--r--tools/gslite/gslt_font_test.c296
-rw-r--r--tools/gslite/gslt_font_ttf.c196
-rw-r--r--tools/gslite/gslt_image.c2
-rw-r--r--tools/gslite/gslt_image.h2
-rw-r--r--tools/gslite/gslt_image_jpeg.c2
-rw-r--r--tools/gslite/gslt_image_png.c2
-rw-r--r--tools/gslite/gslt_image_test.c7
-rwxr-xr-xtools/gslite/gslt_image_threads_test.c219
-rw-r--r--tools/gslite/gslt_image_tiff.c2
-rw-r--r--tools/gslite/gslt_init.c14
-rwxr-xr-xtools/gslite/gslt_lib_gcc.mak140
-rwxr-xr-xtools/gslite/gslt_lib_msvc.mak145
-rw-r--r--tools/gslite/gslt_stubs.c44
-rw-r--r--tools/gslite/gslt_test.c9
-rw-r--r--tools/gslite/tiger.jpgbin0 -> 177310 bytes
30 files changed, 3481 insertions, 1489 deletions
diff --git a/tools/gslite/CenturySchL-Bold.ttf b/tools/gslite/CenturySchL-Bold.ttf
new file mode 100755
index 000000000..f100b5d58
--- /dev/null
+++ b/tools/gslite/CenturySchL-Bold.ttf
Binary files differ
diff --git a/tools/gslite/Makefile b/tools/gslite/Makefile
deleted file mode 100644
index c6df90742..000000000
--- a/tools/gslite/Makefile
+++ /dev/null
@@ -1,81 +0,0 @@
-GSDIR=./gs
-#GSDIR=../ghostscript-head
-
-CC = gcc
-#CFLAGS = -Wall -g -O2 -ggdb
-CFLAGS = -Wall -g -O0 -ggdb
-CPPFLAGS = $(GX_COLOR_INDEX_DEFINE) -DDEBUG -DGSLT_DEBUG_TIFF
-CPPFLAGS = $(GX_COLOR_INDEX_DEFINE) -DDEBUG
-INCLUDES = -I$(GSDIR)/src -I$(GSDIR)/soobj -I/opt/local/include
-LDFLAGS = -L$(GSDIR)/sobin -L/opt/local/lib
-LIBS = -lgs
-
-gslt_SRCS = gslt_alloc.c gslt_init.c \
- gslt_font_api.c \
- gslt_image.c \
- gslt_image_jpeg.c gslt_image_png.c gslt_image_tiff.c
-gslt_HDRS = gslite.h gslt_alloc.h gslt_font_api.h gslt_image.h
-gslt_OBJS = $(gslt_SRCS:.c=.o)
-
-MAIN = gslt_test gslt_image_test gslt_font_api_test
-
-.PHONY: depend clean
-
-all: $(MAIN)
-
-gslt_test: gslt_test.o $(gslt_OBJS)
- $(CC) $(CPPFLAGS) $(CFLAGS) $(INCLUDES) -o $@ $^ $(LDFLAGS) $(LIBS)
-
-gslt_image_test: gslt_image_test.o $(gslt_OBJS)
- $(CC) $(CPPFLAGS) $(CFLAGS) $(INCLUDES) -o $@ $^ $(LDFLAGS) $(LIBS)
-
-gslt_font_api_test: gslt_font_api_test.o $(gslt_OBJS)
- $(CC) $(CPPFLAGS) $(CFLAGS) $(INCLUDES) -o $@ $^ $(LDFLAGS) $(LIBS)
-
-
-.c.o:
- $(CC) $(CPPFLAGS) $(CFLAGS) $(INCLUDES) -c $<
-
-clean:
- $(RM) *.o *~ $(MAIN)
-
-check: $(MAIN)
- @failed=0; all=0; \
- for case in 1 2 3 4 5 6 7 8 9; do \
- all=`expr $$all + 1`; \
- if LD_LIBRARY_PATH=$(GSDIR)/sobin ./gslt_test x11 $$case; then \
- echo "PASS"; \
- else \
- failed=`expr $$failed + 1`; \
- echo "FAILED"; \
- fi; \
- done; \
- for file in *.png *.jpeg *.jpg *.tiff; do \
- all=`expr $$all + 1`; \
- if test -r $$file; then \
- if LD_LIBRARY_PATH=$(GSDIR)/sobin ./gslt_image_test $$file; then \
- echo "PASS"; \
- else \
- failed=`expr $$failed + 1`; \
- echo "FAILED"; \
- fi; \
- fi; \
- done; \
- all=`expr $$all + 1`; \
- if LD_LIBRARY_PATH=$(GSDIR)/sobin ./gslt_font_api_test; then \
- echo "PASS"; \
- else \
- failed=`expr $$failed + 1`; \
- echo "FAILED"; \
- fi; \
- if test "$$failed" -eq 0; then \
- echo "All $$all tests passed"; \
- else \
- echo "FAILED $$failed of $$all tests"; \
- fi
-
-depend: $(gslt_SRCS)
- makedepend $(INCLUDES) $^
-
-# DO NOT DELETE THIS LINE -- make depend needs it
-
diff --git a/tools/gslite/README b/tools/gslite/README
index 13d9abb25..67e9c7f5f 100644
--- a/tools/gslite/README
+++ b/tools/gslite/README
@@ -1,117 +1,93 @@
-gslt (gs lite)
-
-graphics library client, sans pdl's, based on Peter's gslib.c in gs/src/.
-
-simple APIs for image and font loading have been built on top of this
-stripped down Ghostscript build.
-
-File descriptions:
-
-gslt.h is a header that allows basic use of the Ghostscript graphics
-library without including the discipline of all the general headers.
-
-gslt_font_api.h declares the simplified OpenType font loading API.
-gslt_image.h declares the simplified image loading API.
-
-Currently only JPEG, PNG, and an appropriate subset of TIFF image
-formats are supported.
-
-There are three test and example clients for the three APIs that show
-how they can be used and verify that the implementation works.
-
-gslt_test.c - test general drawing routines. Invoke with an output
- device name and test number to run.
-gslt_font_api_test.c - OpenType font load and draw example. The
- test font name is hardcoded in the file.
-gslt_image_test.c - test image loading routines. Invoke with an
- image filename on the commandline.
-
-While these are intended to work on a stripped-down Ghostscript build,
-any recent version will work. Note that $(GLD)roplib.dev may need to
-be added to FEATURE_DEVS in the top-level Ghostscript makefile for
-gslt_test.c to link properly; this example used PCL-style Raster
-Operations in one test and these are not normally included in the main
-Ghostscript build.
-
-BUILD
------
-
-Build a shared library object of ghostscript.
-
-On *nix:
-
- cd gs # relative to the gslite directory.
-
- ln -s src/unix-gcc.mak Makefile
- or
- ./configure
-
- make sodebug # make so for a production build.
-
- cd .. # back to the gslite directory
- make depend
- make
- make check # verify implementation
-
-On MS Windows and other systems:
-
- build a libgs.dll as usual
- create a new project with:
- gslt.h
- gslt_init.c
- gslt_alloc.h
- gslt_alloc.c
- gslt_font_api.h
- gslt_font_api.c
- gslt_image.h
- gslt_image.c
- gslt_image_jpeg.c
- gslt_image_png.c
- gslt_image_tiff.c
- link this with libgs.dll to create a gslt library.
-
- compile each of the *_test.c examples, linking against
- gslt and libgs.dll to verify the implementation.
-
-RUN
----
-
-On Unix-like systems, the shared library can either be put in a well
-defined place or something like this will work if you run the client
-from the same directory each time:
-
-export LD_LIBRARY_PATH=./gs/sobin/
-
-Take care to avoid a common problem: use `ldd gslt' to verify the
-shared library (libgs.so.n) is the one you built above and not one
-installed say in /usr/lib/
-
-./gslt_test <device> <testnumber>
-
-example:
-
-./gslt_test x11 5
-
-The first argument is the device, see the ghostscript library makefile
-for supported devices.
-
-example 2:
-
-run all of the tests:
-
-for x in 1 2 3 4 5 6 7 8 9; do gslt_test x11 $x; done
-
-Likewise, to run the font_api test, edit the source file to set a valid
-path to a test font, recompile and run:
-
-./gslt_font_api_test
-
-To test the image loading library run for example:
-
-./gslt_image_test tiger.jpeg
-./gslt_image_test tiger.png
-./gslt_image_test tiger.tiff
-
-Each invokation will try to load the specified image file and save the
-output to 'out.pnm' which can be examined with an image editor.
+Tue Jan 2 14:04:44 MST 2007
+
+The gslite library temporarily requires a patch to gs/src. See
+"Patch for ghostscript" attached below.
+
+Build and test gslite library with Microsoft Visual Studio 8 with
+Microsoft Platform SDK for Windows Server 2003 R2.
+
+ # install the free visual C++ 2005 and SDK.
+ # modify vsvars32.bat so visual c can find the SDK (vsvars32.bat
+ # patch below) and open the Visual Studio 2005 command prompt.
+ # go to the gslite directory
+ cd tools\gslite
+ # build the library see DEBUG options in the makefile
+ make /f gslt_lib_msvc.mak DEVSTUDIO=
+ # build and run the the test files.
+ make /f gslt_lib_msvc.mak test
+
+build and test gslite library with Linux 2.6.12 and gcc version 3.4.4 20050721 (Red Hat 3.4.4-2)
+
+ # go to the glite directory and build the library.
+ make -f gslt_lib_gcc.mak
+ # test the library.
+ make test
+
+Note the linux makefile supports a threads test
+(gslt_image_threads_test), it is the same as gslt_image_test except it
+tests rendering 2 images in 2 concurrent threads of execution. To get
+this to run on windows wouuld require installing POSIX threads.
+
+
+vsvars32.bat patch
+------------------
+--- vsvars32.bat 2006-12-27 23:48:11.578125000 -0700
++++ vsvars32.bat.bak 2006-12-27 21:14:42.312500000 -0700
+@@ -14,8 +14,8 @@
+ @set DevEnvDir=C:\Program Files\Microsoft Visual Studio 8\Common7\IDE
+
+ @set PATH=C:\Program Files\Microsoft Visual Studio 8\Common7\IDE;C:\Program Files\Microsoft Visual Studio 8\VC\BIN;C:\Program Files\Microsoft Visual Studio 8\Common7\Tools;C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\bin;C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727;C:\Program Files\Microsoft Visual Studio 8\VC\VCPackages;%PATH%
+-@set INCLUDE=C:\Program Files\Microsoft Visual Studio 8\VC\INCLUDE;%INCLUDE%;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include
+-@set LIB=C:\Program Files\Microsoft Visual Studio 8\VC\LIB;C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\lib;%LIB%;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Lib
++@set INCLUDE=C:\Program Files\Microsoft Visual Studio 8\VC\INCLUDE;%INCLUDE%
++@set LIB=C:\Program Files\Microsoft Visual Studio 8\VC\LIB;C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\lib;%LIB%
+ @set LIBPATH=C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727
+
+ @goto end
+
+
+Patch for ghostscript
+---------------------
+
+svn diff
+Index: gs.mak
+===================================================================
+--- gs.mak (revision 7517)
++++ gs.mak (working copy)
+@@ -377,7 +377,7 @@
+ $(DEVICE_DEVS10) $(DEVICE_DEVS11) $(DEVICE_DEVS12) $(DEVICE_DEVS13) \
+ $(DEVICE_DEVS14) $(DEVICE_DEVS15) $(DEVICE_DEVS16) $(DEVICE_DEVS17) \
+ $(DEVICE_DEVS18) $(DEVICE_DEVS19) $(DEVICE_DEVS20) $(DEVICE_DEVS21) \
+- $(DEVICE_DEVS_EXTRA) $(PSD)romfs$(COMPILE_INITS).dev
++ $(DEVICE_DEVS_EXTRA)
+
+ devs_tr=$(GLGENDIR)$(D)devs.tr
+ $(devs_tr) : $(GS_MAK) $(TOP_MAKEFILES) $(ECHOGS_XE)
+@@ -407,7 +407,6 @@
+ $(EXP)$(ECHOGS_XE) -a $(devs_tr) -+ $(DEVICE_DEVS20)
+ $(EXP)$(ECHOGS_XE) -a $(devs_tr) -+ $(DEVICE_DEVS21)
+ $(EXP)$(ECHOGS_XE) -a $(devs_tr) -+ $(DEVICE_DEVS_EXTRA)
+- $(EXP)$(ECHOGS_XE) -a $(devs_tr) -+ $(PSD)romfs$(COMPILE_INITS).dev
+ $(EXP)$(ECHOGS_XE) -a $(devs_tr) - $(GLGENDIR)$(D)libcore
+
+ # GCONFIG_EXTRAS can be set on the command line.
+@@ -423,7 +422,7 @@
+
+ $(gconfig_h) : $(ld_tr)
+ $(NO_OP)
+-
++
+ # The line above is an empty command; don't delete.
+
+ # save our set of makefile variables that are defined in every build (paths, etc.)
+Index: sjpegc.c
+===================================================================
+--- sjpegc.c (revision 7517)
++++ sjpegc.c (working copy)
+@@ -34,7 +34,6 @@
+ unix-aux.mak, and written to gconfig_.h
+ */
+
+-#include "gconfig_.h"
+ #ifdef DONT_HAVE_JMEMSYS_H
diff --git a/tools/gslite/gslite-api.rtf b/tools/gslite/gslite-api.rtf
new file mode 100644
index 000000000..61ce0242d
--- /dev/null
+++ b/tools/gslite/gslite-api.rtf
@@ -0,0 +1,349 @@
+{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
+{\fonttbl\f0\fnil\fcharset77 Constantia;\f1\fnil\fcharset77 Constantia-Bold;}
+{\colortbl;\red255\green255\blue255;}
+\paperw11900\paperh16840\margl1440\margr1440\vieww11340\viewh12480\viewkind0
+\deftab720
+\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720\ql\qnatural
+
+\f0\fs24 \cf0 \
+\
+\
+\
+\
+\
+\
+\
+\
+\
+\
+\
+\
+\
+\
+\
+\
+\
+\
+\
+\
+\
+\
+\
+\
+\
+\
+\
+\
+\
+\
+The GSLite API\
+version 0.4\
+Artifex Software, Inc.\
+26 Oct 2006\
+\
+\page \pard\tx225\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720\ql\qnatural
+
+\f1\b \cf0 The GSLite API\
+\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720\ql\qnatural
+
+\f0\b0 \cf0 \
+GSLite is a simple, lightweight API for accessing some features of the Ghostscript graphics library, most importantly the font rendering and image decoding features. It is implemented as a thin wrapper over the significantly more complex and general Ghostscript graphics library interface, which is designed to support all imaging operations used in modern Page Description Languages.\
+\
+In this beta release, GSLite is provided as an additional layer on top of the full Ghostscript distribution. Production versions will contain a fairly small subset of the Ghostscript codebase, as needed to support the GSLite API. Clients should call GSLite functions exclusively, rather than directly into the Ghostscript graphics library, to allow maximum streamlining of the production GSLite implementation.\
+\
+\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720\ql\qnatural
+
+\f1\b \cf0 Initialization and library object lifecycle\
+\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720\ql\qnatural
+
+\f0\b0 \cf0 \
+Before using any other GSLite functions, the client must initialize the library, using the gslt_init_library() call. This function initializes a single static context; GSLite does not presently support multiple reentrant contexts. The client may also call gslt_free_library() at process termination to free up resources.\
+\
+In addition to the library context, font rendering operations require a graphics state (gs_state), which in turn requires a Ghostscript \'d2device\'d3 data structure (gx_device). In ordinary Ghostscript usage, this device represents a page buffer for imaging operations, but such a page buffer is not required for font rendering and image decoding, so GSLite clients will use the \'d2nullpage\'d3 device.\
+\
+The detailed calling instructions follow.\
+\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720\ql\qnatural
+
+\f1\b \cf0 \
+\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720\ql\qnatural
+
+\f0\b0 \cf0 To use GSLite, the first thing you need to do is to initialize the library:\
+\
+ gs_memory_t * gslt_init_library();\
+\
+This returns an allocator handle for internal use by the gslite routines and the underlying implementation in the graphics library. You need to pass this allocator to many functions. You do not have to use it yourself; it is perfectly safe to use malloc() and free() for your own code.\
+\
+The font rendering implementation in Ghostscript requires a device structure and a graphics state structure. The graphics state is used for font rendering internal operations. The graphics state is tied to a device structure, and contains a pointer to it.\
+\
+Create these two structures at program startup. Pass in "nullpage" as the device name.\
+\
+ gx_device * gslt_init_device(gs_memory_t *mem, char *name);\
+\
+ gs_state *gslt_init_state(gs_memory_t *mem, gx_device *dev);\
+\
+There are functions to clean up the Ghostscript library and the three global objects. Call these in the correct order before the program exits.\
+\
+ void gslt_free_state(gs_memory_t *mem, gs_state *pgs);\
+ void gslt_free_device(gs_memory_t *mem, gx_device *dev);\
+ void gslt_free_library(gs_memory_t *mem);\
+\
+Here is an example of how to use the gslite library:\
+\
+int main(int argc, char **argv)\
+\{\
+ gs_memory *mem = gslt_init_library();\
+ if (!mem)\
+ die("cannot create gslite allocator");\
+\
+ gx_device *dev = gslt_init_device(mem, "nullpage");\
+ if (!dev)\
+ die("cannot create gslite device");\
+\
+ gs_state *pgs = gslt_init_state(mem, dev);\
+ if (!pgs)\
+ die("cannot create gslite state");\
+\
+ /* do some work */\
+\
+ gslt_free_state(mem, pgs);\
+ gslt_free_device(mem, dev);\
+ gslt_free_library(mem, dev, pgs);\
+\}\
+\
+\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720\ql\qnatural
+
+\f1\b \cf0 The Image Codec API\
+\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720\ql\qnatural
+
+\f0\b0 \cf0 \
+There is no need to create the device and graphics state objects for the image codecs; they only require the allocator.\
+\
+There are three defined colorspaces for the image codec API: gray, RGB and CMYK. They come in two variants each: with and without an alpha channel. The variants are enumerated with the type gslt_image_colorspace:\
+\
+ typedef enum \{\
+ GSLT_GRAY,\
+ GSLT_GRAY_A,\
+ GSLT_RGB,\
+ GSLT_RGB_A,\
+ GSLT_CMYK, \
+ GSLT_CMYK_A\
+ \} gslt_image_colorspace;\
+\
+The function to decode an image takes three parameters: the allocator, a buffer with the encoded image data as loaded from disk, and the length of this buffer.\
+\
+ gslt_image_t *gslt_image_decode(gs_memory_t *mem,\
+ unsigned char *buf, int len);\
+\
+It returns an image object or NULL if it fails to decode the image.\
+\
+The image object is a struct:\
+\
+ struct gslt_image_s\
+ \{\
+ int width;\
+ int height;\
+ int stride; /* byte offset between image data rows */\
+ int components;\
+ int bits;\
+ int xres; /* horizontal resolution in pixels per meter */\
+ int yres; /* vertical resolution */\
+ char *samples; /* image data buffer */\
+ gslt_image_colorspace colorspace;\
+ \};\
+\
+The samples field points to the decoded image data. The data is in a format described by the other fields of the struct. Stride is the number of bytes separating each row of image data, and bits is the number of bits per component. The number of bits can be 1, 2, 4, 8 or 16. For 16 bits per component, treat the data as an array of shorts in native byte order. The number of components includes the alpha channel, so it is 3 for GSLT_RGB and 4 for GSLT_RGB_A.\
+\
+Release the image object and decoded data with:\
+\
+ void gslt_image_free(gs_memory_t *mem, gslt_image_t *image);\
+\
+The image decoder takes the entire image file and returns the decoded image data in single memory buffers. This design choice simplifies the API considerably, avoiding the need for complex stream operations.\
+\
+\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720\ql\qnatural
+
+\f1\b \cf0 The Font API\
+\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720\ql\qnatural
+
+\f0\b0 \cf0 \
+The GSLite API for font rendering is designed to support OpenType fonts. The underlying Ghostscript font rendering mechanism supports many other font types as needed for PostScript and PDF, including Type1, CID, and composite fonts, but these would involve considerable extra complexity and so are not supported by GSLite. OpenType is a font format that is based on TrueType; in practice it is a superset of TrueType. Most PostScript and PDF fonts can be transformed into OpenType without loss of fidelity.\
+\
+The primary functions supported by the API are:\
+\
+\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720\li360\fi-360\ri0\ql\qnatural
+\cf0 \'a5 Access to the font's encoding, mapping a character (usually expressed as a Unicode codepoint) to a glyph index.\
+\'a5 Determining the metrics for a glyph, specified by index.\
+\'a5 Rendering a glyph into a bitmap, given glyph index and transform.\
+\'a5 Obtaining an outline for the glyph.\
+\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720\ql\qnatural
+\cf0 \
+The functions in the font API that return an integer will return zero on success and a negative number on failure, unless otherwise specified.\
+\
+The GSLite font API has a caching mechanism for glyph bitmaps, significantly speeding up cases where the same glyph is requested repeatedly. The results of all glyph rendering operations are stored as bitmaps in the cache. The renderer may determine that the bitmap is too large to fit in the cache, in which case it returns an error code (-2), signalling the client that it should obtain an outline, and use its own vector path filling capabilities to render the glyph.\
+\
+At present, the functions for creating this cache choose reasonable defaults for cache size and rendering options, but more configuration options may be provided in the future. To create the cache, use these calls:\
+\
+ gs_font_dir * gslt_new_font_cache(gs_memory_t *mem);\
+\
+ void gslt_free_font_cache(gs_memory_t *mem, gs_font_dir *cache);\
+\
+Create the gslite font object from a memory buffer containing the file data. The font object keeps a pointer to this data, so do not free it until after you free the font object. You will also need to pass in the writing mode to be used with this font. Use zero for horizontal writing and 1 for vertical writing.\
+\
+ gslt_font_t * gslt_new_font(gs_memory_t *mem, gs_font_dir *cache,\
+ char *rbuf, int rlen, int wmode);\
+\
+ void gslt_free_font(gs_memory_t *mem, gslt_font_t *font);\
+\
+\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720\ql\qnatural
+
+\f1\b \cf0 Encodings\
+\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720\ql\qnatural
+
+\f0\b0 \cf0 \
+A TrueType font is a collection of tables. Some of these tables specify the metrics, others specify the outlines. One of the tables that are important for our purposes, is the table that specifies encodings. This table is called the "cmap" table. This table can hold many encodings.\
+\
+An encoding in this table is specified by two numbers. If the font has a Unicode encoding, it will have the identifier (3,1). The TrueType and OpenType specifications contain more details on allowed encodings.\
+\
+Some common encodings are:\
+\
+ 3,0 Microsoft Symbol\
+ 3,1 Microsoft Unicode (used for WGL4)\
+ 3,2 Microsoft SJIS\
+ 3,3 Microsoft GB2312\
+ 3,4 Microsoft Big5\
+ 3,5 Microsoft Wansung\
+ 3,6 Microsoft Johab\
+ 3,10 Microsoft UCS4\
+\
+ 1,0 Apple Roman\
+ 1,1 Apple Japanese\
+ 1,2 Apple Traditional Chinese\
+ 1,3 Apple Korean\
+\
+There is a function to count the number of encodings in the cmap table.\
+\
+ int gslt_count_font_encodings(gslt_font_t *font);\
+\
+Use the count to iterate over the encodings. The encoding identification function takes the index and returns the two numbers that identify the encoding. See the truetype specification for the meaning of these two numbers.\
+\
+ int gslt_identify_font_encoding(gslt_font_t *font, int idx,\
+ int *pid, int *eid);\
+\
+Finally, we can select one of these encodings for use later.\
+\
+ int gslt_select_font_encoding(gslt_font_t *font, int idx);\
+\
+In truetype fonts the glyphs are numbered from zero. Glyph zero has a special meaning as the glyph that represents undefined characters. Any character that cannot be encoded will be mapped to glyph zero.\
+\
+ int gslt_encode_font_char(gslt_font_t *font, int codepoint);\
+\
+The codepoint argument is an integer that represents a character code in the currently selected encoding. If you have selected encoding (3,0) then the codepoint is a unicode character. If you have selected encoding (1,0) then the codepoint is a mac roman encoded character.\
+\
+The function returns the glyph index of the encoded character. If the font does not provide the encoding you are using, you will have to use your own tables to map characters to a codepoint in an encoding the font does support before passing them to gslt_encode_font_char. [TODO microsoft is not clear on what to do when fonts don't have a 3,1 cmap; but they do state (SHOULD) that it is a possibility]\
+\
+You can also use the glyph indices directly, if you have some other means to know which glyph indices to use, such as the Indices attribute of the <Glyphs> element in XPS. When glyph indices are known, gslt_encode_font_char is not needed.\
+\
+For XPS fonts with an encoding table (3, 0) are treated specially. If the code point encodes to the undefined glyph, another attempt is made by first adding 0xf000 to the code point before looking it up again. This is handled by gslt whenever a cmap (3, 0) is selected. \
+\
+\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720\ql\qnatural
+
+\f1\b \cf0 Encoding XPS strings\
+\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720\ql\qnatural
+
+\f0\b0 \cf0 \
+XPS Glyph tags represent text on the page. The tag has two attributes that affect how we select the font glyphs to use when drawing the glyph element.\
+\
+The first one is UnicodeString. It contains the text that the tag represents in Unicode format. For trivial uses, this is enough information to select the glyphs. For each code point we can look it up in the font encoding and get the corresponding glyph.\
+\
+However, not all typeset text will be as straightforward. For instance, the "fi" ligature will map two unicode characters (f followed by i) to one glyph (fi). This transform can not be represented by the cmap table. These transforms are done by using smart font layout table features in OpenType. This is not done by the XPS renderer. The creator of the XPS file has to do this.\
+\
+In order to represent ligatures and more advanced typographical features, we need the second attribute in the <Glyph> element: Indices. Indices is used in parallel with UnicodeString to select glyphs that represent the Unicode characters.\
+\
+The Indices string contains cluster maps that map one-to-many and many-to-one; and also indices to glyphs that are not encoded by the cmap. The indices are the glyph indices for the font. You can use the indices directly; there is no need to encode them or pass them through gslt_encode_font_char.\
+\
+A ligature would be represented by a cluster map that says that the two characters 'f' and 'i' in the UnicodeString should map to the one (hypothetical) glyph index 1234. In this case you should ignore the 'f' and 'i' in the UnicodeString and use the glyph index specified by the cluster map instead.\
+\
+See the XPS specification for more details.\
+\
+\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720\ql\qnatural
+
+\f1\b \cf0 Glyph metrics\
+\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720\ql\qnatural
+
+\f0\b0 \cf0 \
+Once you have the list of glyphs, you will need to figure out their position on the page. Each glyph has the following metrics:\
+\
+ struct gslt_glyph_metrics_s\
+ \{\
+ float hadv, vadv, vorg;\
+ \};\
+\
+ int gslt_measure_font_glyph(gs_state *pgs, gslt_font_t *font,\
+ int gid, gslt_glyph_metrics_t *mtx);\
+\
+The metrics are untransformed, and will typically lie in the range 0..1.\
+\
+A glyph is drawn from its origin, which is at the bottom left of the glyph. This is used for horizontal writing; for vertical writing the origin should be at the middle top of the glyph.\
+\
+The origin offset is a vector that needs to be added to the pen position when drawing the glyph. The vorg field specifies the origin offset in the y direction, and the x origin offset is obtained by dividing hadv by two. This will adjust the horizontal writing origin to the vertical writing origin. This is only to be used for vertical (IsSideways) written text.\
+\
+The hadv and vadv field specifies the advance width, or escapement, for horizontal and vertical writing. This is the distance the pen should be moved to position the following glyph. Use the appropriate field depending on the IsSideways attribute.\
+\
+\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720\ql\qnatural
+
+\f1\b \cf0 Rendering bitmaps\
+\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720\ql\qnatural
+
+\f0\b0 \cf0 \
+With the list of glyph indices and their positions on the page in hand, it will be time to draw them.\
+\
+ struct gslt_glyph_bitmap_s\
+ \{\
+ int w, h, stride;\
+ int lsb, top;\
+ unsigned char *data;\
+ \};\
+\
+ int gslt_render_font_glyph(gs_state *pgs, gslt_font_t *font,\
+ gs_matrix *tm, int gid,\
+ gslt_glyph_bitmap_t *slot);\
+\
+ void gslt_retain_font_glyph(gs_memory_t *mem, gslt_glyph_bitmap_t *slot);\
+ void gslt_release_font_glyph(gs_memory_t *mem, gslt_glyph_bitmap_t *slot);\
+\
+\
+This function will attempt to find a rendered bitmap with the same font, matrix and glyph index in the cache (the same cache as was used to create the font object). If it fails, it will try to render the bitmap and store it in the cache, then return that bitmap.\
+\
+The bitmap data returned is a pointer to the cache. Therefore, you must not overwrite the data, or it may give provide incorrect results to future calls. Similarly, subsequent rendering calls may evict the data from the cache, so validity is only guaranteed until the next rendering call or library free call. If a more persistent lifetime is desired, copy the data.\
+\
+The lsb and top fields specify the position of the bitmap relative to the pen position for the horizontal origin.\
+\
+The cache has a limited amount of space to work with. If you try to render a bitmap that is too large, the rendering function will return -2. In that case, you will have to fall back to your own path rendering functions, using the outline data.\
+\
+The bitmap data points to an internal slot in the cache. These slots have a reference count, which is the number of client pointers that use it. When the reference count is zero, the slot can be reused. Each time gslt_render_font_glyph returns a bitmap, the corresponding slot has its reference count incremented. Therefore it is very important that you call gslt_release_font_glyph as soon as you do not need the bitmap anymore. If your code needs to pass around or hold multiple pointers to a glyph bitmap, then you may use the gslt_retain_font_glyph function to increment the reference count.\
+\
+If you do not released the bitmaps immediately after using them, the next call to gslt_render_font_glyph may also fail because the glyph cache has filled up. This can happen because it cannot evict old bitmaps that you still hold references to.\
+\
+\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720\ql\qnatural
+
+\f1\b \cf0 Walking the outline\
+\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720\ql\qnatural
+
+\f0\b0 \cf0 \
+Extract the outline data with a struct full of function pointers. The function will pass unhinted, untransformed coordinates scaled by 1000.\
+\
+ struct gslt_outline_walker_s\
+ \{\
+ void *user;\
+ int (*moveto)(void *user, float x, float y);\
+ int (*lineto)(void *user, float x, float y);\
+ int (*curveto)(void *user, float x0, float y0,\
+ float x1, float y1,\
+ float x2, float y2);\
+ int (*closepath)(void *user);\
+ \};\
+\
+ int gslt_outline_font_glyph(gs_state *pgs, gslt_font_t *font, int gid,\
+ gslt_outline_walker_t *walker);\
+\
+As usual, this function returns -1 if it fails. Return -1 from the callbacks to abort the outline extraction.\
+} \ No newline at end of file
diff --git a/tools/gslite/gslt.c b/tools/gslite/gslt.c
deleted file mode 100644
index 11e8122c0..000000000
--- a/tools/gslite/gslt.c
+++ /dev/null
@@ -1,1276 +0,0 @@
-/* Copyright (C) 1995, 2000 Aladdin Enterprises. All rights reserved.
-
- This software is provided AS-IS with no warranty, either express or
- implied.
-
- This software is distributed under license and may not be copied,
- modified or distributed except as expressly authorized under the terms
- of the license contained in the file LICENSE in this distribution.
-
- For more information about licensing, please refer to
- http://www.ghostscript.com/licensing/. For information on
- commercial licensing, go to http://www.artifex.com/licensing/ or
- contact Artifex Software, Inc., 101 Lucas Valley Road #110,
- San Rafael, CA 94903, U.S.A., +1(415)492-9861.
-*/
-
-/* $Id$ */
-/* Test program for Ghostscript library */
-/* Capture stdin/out/err before gsio.h redefines them. */
-#include "stdio_.h"
-#include "math_.h"
-#include "string_.h"
-#include "gx.h"
-#include "gp.h"
-#include "gslt_alloc.h"
-#include "gscdefs.h"
-#include "gserrors.h"
-#include "gslib.h"
-#include "gsmatrix.h"
-#include "gsstate.h"
-#include "gscspace.h"
-#include "gscolor2.h"
-#include "gscoord.h"
-#include "gscie.h"
-#include "gscrd.h"
-#include "gsiparm3.h"
-#include "gsiparm4.h"
-#include "gsparam.h"
-#include "gspaint.h"
-#include "gspath.h"
-#include "gspath2.h"
-#include "gsrop.h"
-#include "gsstruct.h"
-#include "gsutil.h"
-#include "gxalloc.h"
-#include "gxdcolor.h" /* for gx_device_white/black */
-#include "gxdevice.h"
-#include "gxht.h" /* for gs_halftone */
-// #include "gdevcmap.h"
-#include "gshtx.h"
-#include "gxpath.h"
-/* Define whether we are processing captured data. */
-/*#define CAPTURE */
-
-/* Test programs */
-private int test1(gs_state *, gs_memory_t *); /* kaleidoscope */
-private int test2(gs_state *, gs_memory_t *); /* pattern fill */
-private int test3(gs_state *, gs_memory_t *); /* RasterOp */
-private int test4(gs_state *, gs_memory_t *); /* set resolution */
-private int test5(gs_state *, gs_memory_t *); /* images */
-private int test6(gs_state *, gs_memory_t *); /* CIE API, snapping */
-private int test7(gs_state *, gs_memory_t *); /* non-monot HT */
-private int test8(gs_state *, gs_memory_t *); /* transp patterns */
-private int test9(gs_state *, gs_memory_t *); /* type 42 font */
-
-private int (*tests[]) (gs_state *, gs_memory_t *) =
-{
- test1, test2, test3, test4, test5,
- test6,
-#ifdef HALFTONE_FIX
- test7,
-#else
- 0,
-#endif
- test8, test9,
-#ifdef CAPTURE
- test10
-#endif
-};
-
-/* Include the extern for the device list. */
-extern_gs_lib_device_list();
-
-/* Forward references */
-private float odsf(floatp, floatp);
-
-
-/* return index in gs device list -1 if not found */
-private inline int
-get_device_index(const gs_memory_t *mem, const char *value)
-{
- const gx_device *const *dev_list;
- int num_devs = gs_lib_device_list(&dev_list, NULL);
- int di;
-
- for ( di = 0; di < num_devs; ++di )
- if ( !strcmp(gs_devicename(dev_list[di]), value) )
- break;
- if ( di == num_devs ) {
- lprintf1("Unknown device name %s.\n", value);
- return -1;
- }
- return di;
-}
-
-int
-main(int argc, const char *argv[])
-{
- char achar;
- gs_memory_t *mem;
- /* memory braindamage */
-#define gs_stdin mem->gs_lib_ctx->fstdin
- gs_state *pgs;
- const gx_device *const *list;
- gx_device *dev;
- int code;
-
- /* a simple allocator to avoid the complications of the full
- featured memory allocator */
- mem = gslt_alloc_init();
- gp_init();
- gs_lib_init1(mem);
- if (argc < 3 || (achar = argv[2][0]) < '1' ||
- achar > '0' + countof(tests)
- ) {
- lprintf1("Usage: gslt [device] 1..%c\n", '0' + (char)countof(tests));
- exit(1);
- }
- memset(gs_debug, 0, 128);
- gs_debug['@'] = 1;
- gs_debug['?'] = 1;
-/*gs_debug['B'] = 1; *//****** PATCH ******/
-/*gs_debug['L'] = 1; *//****** PATCH ******/
- gs_log_errors = 0;
- /*
- * gs_iodev_init must be called after the rest of the inits, for
- * obscure reasons that really should be documented!
- */
- gs_iodev_init(mem);
- {
- int devindex = get_device_index(mem, argv[1]);
- if (devindex < 0) {
- lprintf1("device %s not found\n", argv[1]);
- exit(1);
- }
- gs_lib_device_list(&list, NULL);
- gs_copydevice(&dev, list[devindex], mem);
- }
- // stefan foo: pulled for linking to gs 8.13
- //check_device_separable(dev);
- gx_device_fill_in_procs(dev);
- /* Print out the device name just to test the gsparam.c API. */
- {
- gs_c_param_list list;
- gs_param_string nstr;
-
- gs_c_param_list_write(&list, mem);
- code = gs_getdeviceparams(dev, (gs_param_list *) & list);
- if (code < 0) {
- lprintf1("getdeviceparams failed! code = %d\n", code);
- exit(1);
- }
- gs_c_param_list_read(&list);
- code = param_read_string((gs_param_list *) & list, "Name", &nstr);
- if (code < 0) {
- lprintf1("reading Name failed! code = %d\n", code);
- exit(1);
- }
- dputs("Device name = ");
- debug_print_string(nstr.data, nstr.size);
- dputs("\n");
- gs_c_param_list_release(&list);
- }
- /*
- * If this is a device that takes an OutputFile, set the OutputFile
- * to "-" in the copy.
- */
- {
- gs_c_param_list list;
- gs_param_string nstr;
-
- gs_c_param_list_write(&list, mem);
- param_string_from_string(nstr, "-");
- code = param_write_string((gs_param_list *)&list, "OutputFile", &nstr);
- if (code < 0) {
- lprintf1("writing OutputFile failed! code = %d\n", code);
- exit(1);
- }
- gs_c_param_list_read(&list);
- code = gs_putdeviceparams(dev, (gs_param_list *)&list);
- gs_c_param_list_release(&list);
- if (code < 0 && code != gs_error_undefined) {
- lprintf1("putdeviceparams failed! code = %d\n", code);
- exit(1);
- }
- }
- pgs = gs_state_alloc(mem);
- gs_setdevice_no_erase(pgs, dev); /* can't erase yet */
- {
- gs_point dpi;
- gs_screen_halftone ht;
-
- gs_dtransform(pgs, 72.0, 72.0, &dpi);
- ht.frequency = min(fabs(dpi.x), fabs(dpi.y)) / 16.001;
- ht.angle = 0;
- ht.spot_function = odsf;
- gs_setscreen(pgs, &ht);
- }
- /* gsave and grestore (among other places) assume that */
- /* there are at least 2 gstates on the graphics stack. */
- /* Ensure that now. */
- gs_gsave(pgs);
- gs_erasepage(pgs);
-
- if (tests[achar - '1']) {
- code = (*tests[achar - '1']) (pgs, mem);
- gs_output_page(pgs, 1, 1);
- if (code)
- dprintf1("**** Test returned code = %d.\n", code);
- dputs("Done. Press <enter> to exit.");
- fgetc(gs_stdin);
- } else {
- dputs("test not defined\n");
- }
- gs_lib_finit(0, 0, mem);
- return 0;
-
-#undef mem
-}
-/* Ordered dither spot function */
-private float
-odsf(floatp x, floatp y)
-{
- static const byte dither[256] =
- {
- 0x0E, 0x8E, 0x2E, 0xAE, 0x06, 0x86, 0x26, 0xA6, 0x0C, 0x8C, 0x2C, 0xAC, 0x04, 0x84, 0x24, 0xA4,
- 0xCE, 0x4E, 0xEE, 0x6E, 0xC6, 0x46, 0xE6, 0x66, 0xCC, 0x4C, 0xEC, 0x6C, 0xC4, 0x44, 0xE4, 0x64,
- 0x3E, 0xBE, 0x1E, 0x9E, 0x36, 0xB6, 0x16, 0x96, 0x3C, 0xBC, 0x1C, 0x9C, 0x34, 0xB4, 0x14, 0x94,
- 0xFE, 0x7E, 0xDE, 0x5E, 0xF6, 0x76, 0xD6, 0x56, 0xFC, 0x7C, 0xDC, 0x5C, 0xF4, 0x74, 0xD4, 0x54,
- 0x01, 0x81, 0x21, 0xA1, 0x09, 0x89, 0x29, 0xA9, 0x03, 0x83, 0x23, 0xA3, 0x0B, 0x8B, 0x2B, 0xAB,
- 0xC1, 0x41, 0xE1, 0x61, 0xC9, 0x49, 0xE9, 0x69, 0xC3, 0x43, 0xE3, 0x63, 0xCB, 0x4B, 0xEB, 0x6B,
- 0x31, 0xB1, 0x11, 0x91, 0x39, 0xB9, 0x19, 0x99, 0x33, 0xB3, 0x13, 0x93, 0x3B, 0xBB, 0x1B, 0x9B,
- 0xF1, 0x71, 0xD1, 0x51, 0xF9, 0x79, 0xD9, 0x59, 0xF3, 0x73, 0xD3, 0x53, 0xFB, 0x7B, 0xDB, 0x5B,
- 0x0D, 0x8D, 0x2D, 0xAD, 0x05, 0x85, 0x25, 0xA5, 0x0F, 0x8F, 0x2F, 0xAF, 0x07, 0x87, 0x27, 0xA7,
- 0xCD, 0x4D, 0xED, 0x6D, 0xC5, 0x45, 0xE5, 0x65, 0xCF, 0x4F, 0xEF, 0x6F, 0xC7, 0x47, 0xE7, 0x67,
- 0x3D, 0xBD, 0x1D, 0x9D, 0x35, 0xB5, 0x15, 0x95, 0x3F, 0xBF, 0x1F, 0x9F, 0x37, 0xB7, 0x17, 0x97,
- 0xFD, 0x7D, 0xDD, 0x5D, 0xF5, 0x75, 0xD5, 0x55, 0xFF, 0x7F, 0xDF, 0x5F, 0xF7, 0x77, 0xD7, 0x57,
- 0x02, 0x82, 0x22, 0xA2, 0x0A, 0x8A, 0x2A, 0xAA, 0x00, 0x80, 0x20, 0xA0, 0x08, 0x88, 0x28, 0xA8,
- 0xC2, 0x42, 0xE2, 0x62, 0xCA, 0x4A, 0xEA, 0x6A, 0xC0, 0x40, 0xE0, 0x60, 0xC8, 0x48, 0xE8, 0x68,
- 0x32, 0xB2, 0x12, 0x92, 0x3A, 0xBA, 0x1A, 0x9A, 0x30, 0xB0, 0x10, 0x90, 0x38, 0xB8, 0x18, 0x98,
- 0xF2, 0x72, 0xD2, 0x52, 0xFA, 0x7A, 0xDA, 0x5A, 0xF0, 0x70, 0xD0, 0x50, 0xF8, 0x78, 0xD8, 0x58
- };
- int i = (int)((x + 1) * 7.9999);
- int j = (int)((y + 1) * 7.9999);
-
- return dither[16 * i + j] / 256.0;
-}
-
-/* Fill a rectangle. */
-private int
-fill_rect1(gs_state * pgs, floatp x, floatp y, floatp w, floatp h)
-{
- gs_rect r;
-
- r.q.x = (r.p.x = x) + w;
- r.q.y = (r.p.y = y) + h;
- return gs_rectfill(pgs, &r, 1);
-}
-
-/* Stubs for GC */
-const gs_ptr_procs_t ptr_struct_procs =
-{NULL, NULL, NULL};
-const gs_ptr_procs_t ptr_string_procs =
-{NULL, NULL, NULL};
-const gs_ptr_procs_t ptr_const_string_procs =
-{NULL, NULL, NULL};
-void * /* obj_header_t * */
-gs_reloc_struct_ptr(const void * /* obj_header_t * */ obj, gc_state_t * gcst)
-{
- return (void *)obj;
-}
-void
-gs_reloc_string(gs_string * sptr, gc_state_t * gcst)
-{
-}
-void
-gs_reloc_const_string(gs_const_string * sptr, gc_state_t * gcst)
-{
-}
-
-/* Other stubs */
-void
-gs_to_exit(const gs_memory_t *mem, int exit_status)
-{
- gs_lib_finit(exit_status, 0, mem);
-}
-
-void
-gs_abort(const gs_memory_t *mem)
-{
- gs_to_exit(mem, 1); /* cleanup */
- gp_do_exit(1); /* system independent exit() */
-}
-
-
-/* Return the number with the magnitude of x and the sign of y. */
-/* This is a BSD addition to libm; not all compilers have it. */
-private double
-gs_copysign(floatp x, floatp y)
-{
- return ( y >= 0 ? fabs(x) : -fabs(x) );
-}
-
-
-/* ---------------- Test program 1 ---------------- */
-/* Draw a colored kaleidoscope. */
-
-/* Random number generator */
-private long rand_state = 1;
-private long
-rand(void)
-{
-#define A 16807
-#define M 0x7fffffff
-#define Q 127773 /* M / A */
-#define R 2836 /* M % A */
- rand_state = A * (rand_state % Q) - R * (rand_state / Q);
- /* Note that rand_state cannot be 0 here. */
- if (rand_state <= 0)
- rand_state += M;
-#undef A
-#undef M
-#undef Q
-#undef R
- return rand_state;
-}
-private int
-test1(gs_state * pgs, gs_memory_t * mem)
-{
- int n;
-
- gs_scale(pgs, 72.0, 72.0);
- gs_translate(pgs, 4.25, 5.5);
- gs_scale(pgs, 4.0, 4.0);
- gs_newpath(pgs);
- for (n = 200; --n >= 0;) {
- int j;
-
-#define rf() (rand() / (1.0 * 0x10000 * 0x8000))
- double r = rf(), g = rf(), b = rf();
- double x0 = rf(), y0 = rf(), x1 = rf(), y1 = rf(), x2 = rf(), y2 = rf();
-
- gs_setrgbcolor(pgs, r, g, b);
- for (j = 0; j < 6; j++) {
- gs_gsave(pgs);
- gs_rotate(pgs, 60.0 * j);
- gs_moveto(pgs, x0, y0);
- gs_lineto(pgs, x1, y1);
- gs_lineto(pgs, x2, y2);
- gs_fill(pgs);
- gs_grestore(pgs);
- }
- }
-#undef mem
- return 0;
-}
-
-/* ---------------- Test program 2 ---------------- */
-/* Fill an area with a pattern. */
-
-private int
-test2(gs_state * pgs, gs_memory_t * mem)
-{
- gs_client_color cc;
- gx_tile_bitmap tile;
- /*const */ byte tpdata[] =
- {
- /* Define a pattern that looks like this:
- ..xxxx
- .....x
- .....x
- ..xxxx
- .x....
- x.....
- */
- 0x3c, 0, 0, 0, 0x04, 0, 0, 0, 0x04, 0, 0, 0, 0x3c, 0, 0, 0,
- 0x40, 0, 0, 0, 0x80, 0, 0, 0
- };
-
- gs_newpath(pgs);
- gs_moveto(pgs, 100.0, 300.0);
- gs_lineto(pgs, 500.0, 500.0);
- gs_lineto(pgs, 200.0, 100.0);
- gs_lineto(pgs, 300.0, 500.0);
- gs_lineto(pgs, 500.0, 200.0);
- gs_closepath(pgs);
- gs_setrgbcolor(pgs, 0.0, 0.0, 0.0);
- gs_gsave(pgs);
- gs_fill(pgs);
- gs_grestore(pgs);
- tile.data = tpdata;
- tile.raster = 4;
- tile.size.x = tile.rep_width = 6;
- tile.size.y = tile.rep_height = 6;
- tile.id = gx_no_bitmap_id;
- gs_makebitmappattern(&cc, &tile, true, pgs, NULL);
- /* Note: color space is DeviceRGB */
- cc.paint.values[0] = 0.0;
- cc.paint.values[1] = 1.0;
- cc.paint.values[2] = 1.0;
- gs_setpattern(pgs, &cc);
- gs_eofill(pgs);
- gs_makebitmappattern(&cc, &tile, false, pgs, NULL);
- gs_setcolor(pgs, &cc);
- gs_moveto(pgs, 50.0, 50.0);
- gs_lineto(pgs, 300.0, 50.0);
- gs_lineto(pgs, 50.0, 300.0);
- gs_closepath(pgs);
- gs_setrgbcolor(pgs, 1.0, 0.0, 0.0);
- gs_gsave(pgs);
- gs_fill(pgs);
- gs_grestore(pgs);
- gs_setpattern(pgs, &cc);
- gs_eofill(pgs);
- return 0;
-}
-
-/* ---------------- Test program 3 ---------------- */
-/* Exercise RasterOp a little. */
-/* Currently, this only works with monobit devices. */
-
-private int
-test3(gs_state * pgs, gs_memory_t * mem)
-{
- gx_device *dev = gs_currentdevice(pgs);
- gx_color_index black = gx_device_black(dev);
- gx_color_index white = gx_device_white(dev);
- gx_color_index black2[2];
- gx_color_index black_white[2];
- gx_color_index white_black[2];
- long pattern[max(align_bitmap_mod / sizeof(long), 1) * 4];
-
-#define pbytes ((byte *)pattern)
- gx_tile_bitmap tile;
-
- black2[0] = black2[1] = black;
- black_white[0] = white_black[1] = black;
- black_white[1] = white_black[0] = white;
- pbytes[0] = 0xf0;
- pbytes[align_bitmap_mod] = 0x90;
- pbytes[align_bitmap_mod * 2] = 0x90;
- pbytes[align_bitmap_mod * 3] = 0xf0;
- tile.data = pbytes;
- tile.raster = align_bitmap_mod;
- tile.size.x = tile.size.y = 4;
- tile.id = gs_next_ids(mem, 1);
- tile.rep_width = tile.rep_height = 4;
- (*dev_proc(dev, copy_rop))
- (dev, NULL, 0, 0, gx_no_bitmap_id, black2,
- &tile, white_black, 100, 100, 150, 150, 0, 0, rop3_T);
- (*dev_proc(dev, copy_rop))
- (dev, NULL, 0, 0, gx_no_bitmap_id, black2,
- NULL, NULL, 120, 120, 110, 110, 0, 0, ~rop3_S & rop3_1);
- (*dev_proc(dev, copy_rop))
- (dev, NULL, 0, 0, gx_no_bitmap_id, black2,
- &tile, white_black, 110, 110, 130, 130, 0, 0, rop3_T ^ rop3_D);
-#undef pbytes
- return 0;
-}
-
-/* ---------------- Test program 4 ---------------- */
-/* Set the resolution dynamically. */
-
-private int
-test4(gs_state * pgs, gs_memory_t * mem)
-{
- gs_c_param_list list;
- float resv[2];
- gs_param_float_array ares;
- int code;
- gx_device *dev = gs_currentdevice(pgs);
-
- gs_c_param_list_write(&list, mem);
- resv[0] = resv[1] = 100;
- ares.data = resv;
- ares.size = 2;
- ares.persistent = true;
- code = param_write_float_array((gs_param_list *) & list,
- "HWResolution", &ares);
- if (code < 0) {
- lprintf1("Writing HWResolution failed: %d\n", code);
- exit(1);
- }
- gs_c_param_list_read(&list);
- code = gs_putdeviceparams(dev, (gs_param_list *) & list);
- gs_c_param_list_release(&list);
- if (code < 0) {
- lprintf1("Setting HWResolution failed: %d\n", code);
- exit(1);
- }
- gs_initmatrix(pgs);
- gs_initclip(pgs);
- if (code == 1) {
- code = (*dev_proc(dev, open_device)) (dev);
- if (code < 0) {
- lprintf1("Reopening device failed: %d\n", code);
- exit(1);
- }
- }
- gs_moveto(pgs, 0.0, 72.0);
- gs_rlineto(pgs, 72.0, 0.0);
- gs_rlineto(pgs, 0.0, 72.0);
- gs_closepath(pgs);
- gs_stroke(pgs);
- return 0;
-}
-
-/* ---------------- Test program 5 ---------------- */
-/* Test masked (and non-masked) images. */
-
-private int
-test5(gs_state * pgs, gs_memory_t * mem)
-{
- gx_device *dev = gs_currentdevice(pgs);
- gx_image_enum_common_t *info;
- gx_image_plane_t planes[5];
- gx_drawing_color dcolor;
- int code;
- static const byte data3[] =
- {
- 0x00, 0x44, 0x88, 0xcc,
- 0x44, 0x88, 0xcc, 0x00,
- 0x88, 0xcc, 0x00, 0x44,
- 0xcc, 0x00, 0x44, 0x88
- };
- gs_color_space gray_cs;
-
- gs_cspace_init_DeviceGray(mem, &gray_cs);
-
- /*
- * Neither ImageType 3 nor 4 needs a current color,
- * but some intermediate code assumes it's valid.
- */
- set_nonclient_dev_color(&dcolor, 0);
-
- /* Scale everything up, and fill the background. */
- {
- gs_matrix mat;
-
- gs_currentmatrix(pgs, &mat);
- mat.xx = gs_copysign(98.6, mat.xx);
- mat.yy = gs_copysign(98.6, mat.yy);
- mat.tx = floor(mat.tx) + 0.499;
- mat.ty = floor(mat.ty) + 0.499;
- gs_setmatrix(pgs, &mat);
- }
- gs_setrgbcolor(pgs, 1.0, 0.9, 0.9);
- fill_rect1(pgs, 0.25, 0.25, 4.0, 6.0);
- gs_setrgbcolor(pgs, 0.5, 1.0, 0.5);
-
-#if 0
- /* Make things a little more interesting.... */
- gs_translate(pgs, 1.0, 1.0);
- gs_rotate(pgs, 10.0);
- gs_scale(pgs, 1.3, 0.9);
-#endif
-
-#define do_image(image, idata)\
- BEGIN\
- code = gx_device_begin_typed_image(dev, (gs_imager_state *)pgs, NULL,\
- (gs_image_common_t *)&image, NULL, &dcolor, NULL, mem, &info);\
- /****** TEST code >= 0 ******/\
- planes[0].data = idata;\
- planes[0].data_x = 0;\
- planes[0].raster = (image.Height * image.BitsPerComponent + 7) >> 3;\
- code = gx_image_plane_data(info, planes, image.Height);\
- /****** TEST code == 1 ******/\
- code = gx_image_end(info, true);\
- /****** TEST code >= 0 ******/\
- END
-
-#define W 4
-#define H 4
-
- /* Test an unmasked image. */
- gs_gsave(pgs);
- {
- gs_image1_t image1;
- void *info1;
- gs_color_space cs;
-
- gs_cspace_init_DeviceGray(mem, &cs);
- gs_image_t_init(&image1, &cs);
- /* image */
- image1.ImageMatrix.xx = W;
- image1.ImageMatrix.yy = -H;
- image1.ImageMatrix.ty = H;
- /* data_image */
- image1.Width = W;
- image1.Height = H;
- image1.BitsPerComponent = 8;
-
- gs_translate(pgs, 0.5, 4.0);
- code = (*dev_proc(dev, begin_image))
- (dev, (const gs_imager_state *)pgs, &image1,
- gs_image_format_chunky, (const gs_int_rect *)0,
- &dcolor, NULL, mem, &info1);
-/****** TEST code >= 0 ******/
- planes[0].data = data3;
- planes[0].data_x = 0;
- planes[0].raster =
- (image1.Height * image1.BitsPerComponent + 7) >> 3;
- /* Use the old image_data API. */
- code = (*dev_proc(dev, image_data))
- (dev, info1, &planes[0].data, 0,
- planes[0].raster, image1.Height);
-/****** TEST code == 1 ******/
- code = (*dev_proc(dev, end_image))(dev, info1, true);
-/****** TEST code >= 0 ******/
- }
- gs_grestore(pgs);
-
- /* Test an explicitly masked image. */
- gs_gsave(pgs);
- {
- gs_image3_t image3;
- static const byte data3mask[] =
- {
- 0x60,
- 0x90,
- 0x90,
- 0x60
- };
- static const byte data3x2mask[] =
- {
- 0x66,
- 0x99,
- 0x99,
- 0x66,
- 0x66,
- 0x99,
- 0x99,
- 0x66
- };
-
- gs_image3_t_init(&image3, &gray_cs, interleave_scan_lines);
- /* image */
- image3.ImageMatrix.xx = W;
- image3.ImageMatrix.yy = -H;
- image3.ImageMatrix.ty = H;
- /* data_image */
- image3.Width = W;
- image3.Height = H;
- image3.BitsPerComponent = 8;
- /* MaskDict */
- image3.MaskDict.ImageMatrix = image3.ImageMatrix;
- image3.MaskDict.Width = image3.Width;
- image3.MaskDict.Height = image3.Height;
-
- /* Display with 1-for-1 mask and image. */
- gs_translate(pgs, 0.5, 2.0);
- code = gx_device_begin_typed_image(dev, (gs_imager_state *) pgs,
- NULL, (gs_image_common_t *) & image3,
- NULL, &dcolor, NULL, mem, &info);
-/****** TEST code >= 0 ******/
- planes[0].data = data3mask;
- planes[0].data_x = 0;
- planes[0].raster = (image3.MaskDict.Height + 7) >> 3;
- planes[1].data = data3;
- planes[1].data_x = 0;
- planes[1].raster =
- (image3.Height * image3.BitsPerComponent + 7) >> 3;
- code = gx_image_plane_data(info, planes, image3.Height);
-/****** TEST code == 1 ******/
- code = gx_image_end(info, true);
-/****** TEST code >= 0 ******/
-
- /* Display with 2-for-1 mask and image. */
- image3.MaskDict.ImageMatrix.xx *= 2;
- image3.MaskDict.ImageMatrix.yy *= 2;
- image3.MaskDict.ImageMatrix.ty *= 2;
- image3.MaskDict.Width *= 2;
- image3.MaskDict.Height *= 2;
- gs_translate(pgs, 1.5, 0.0);
- code = gx_device_begin_typed_image(dev, (gs_imager_state *) pgs,
- NULL, (gs_image_common_t *) & image3,
- NULL, &dcolor, NULL, mem, &info);
-/****** TEST code >= 0 ******/
- planes[0].data = data3x2mask;
- planes[0].raster = (image3.MaskDict.Width + 7) >> 3;
- {
- int i;
-
- for (i = 0; i < H; ++i) {
- planes[1].data = 0;
- code = gx_image_plane_data(info, planes, 1);
- planes[0].data += planes[0].raster;
-/****** TEST code == 0 ******/
- planes[1].data = data3 + i * planes[1].raster;
- code = gx_image_plane_data(info, planes, 1);
- planes[0].data += planes[0].raster;
-/****** TEST code >= 0 ******/
- }
- }
-/****** TEST code == 1 ******/
- code = gx_image_end(info, true);
-/****** TEST code >= 0 ******/
- }
- gs_grestore(pgs);
-
- /* Test a chroma-keyed masked image. */
- gs_gsave(pgs);
- {
- gs_image4_t image4;
- const byte *data4 = data3;
-
- gs_image4_t_init(&image4, &gray_cs);
- /* image */
- image4.ImageMatrix.xx = W;
- image4.ImageMatrix.yy = -H;
- image4.ImageMatrix.ty = H;
- /* data_image */
- image4.Width = W;
- image4.Height = H;
- image4.BitsPerComponent = 8;
-
- /* Display with a single mask color. */
- gs_translate(pgs, 0.5, 0.5);
- image4.MaskColor_is_range = false;
- image4.MaskColor[0] = 0xcc;
- do_image(image4, data4);
-
- /* Display a second time with a color range. */
- gs_translate(pgs, 1.5, 0.0);
- image4.MaskColor_is_range = true;
- image4.MaskColor[0] = 0x40;
- image4.MaskColor[1] = 0x90;
- do_image(image4, data4);
- }
- gs_grestore(pgs);
-
-#undef W
-#undef H
-#undef do_image
- return 0;
-}
-
-/* ---------------- Test program 6 ---------------- */
-/* Test the C API for CIE CRDs, and color snapping. */
-
-private void
-spectrum(gs_state * pgs, int n)
-{
- float den = n;
- float den1 = n - 1;
- float den2 = (n * 2 - 1) * n;
- int a, b, c;
-
- for (a = 0; a < n; ++a)
- for (b = 0; b < n; ++b)
- for (c = 0; c < n; ++c) {
- double size = (n * 2 - c * 2 - 1) / den2;
- gs_client_color cc;
-
- cc.paint.values[0] = a / den1;
- cc.paint.values[1] = b / den1;
- cc.paint.values[2] = c / den1;
- gs_setcolor(pgs, &cc);
- fill_rect1(pgs,
- a / den + c / den2, b / den + c / den2,
- size, size);
- }
-}
-private float
-render_abc(floatp v, const gs_cie_render * ignore_crd)
-{
- return v / 2;
-}
-
-private int
-test6(gs_state * pgs, gs_memory_t * mem)
-{
- gs_color_space *pcs;
- gs_cie_abc *pabc;
- gs_cie_render *pcrd;
- static const gs_vector3 white_point =
- {1, 1, 1};
- static const gs_cie_render_proc3 encode_abc =
- {
- {render_abc, render_abc, render_abc}
- };
-#ifdef COLOR_MAP_DEVICE
- gx_device_cmap *cmdev;
-#endif /* COLOR_MAP_DEVICE */
- int code;
- gs_color_space rgb_cs;
-
- gs_cspace_init_DeviceRGB(mem, &rgb_cs);
-
- gs_scale(pgs, 150.0, 150.0);
- gs_translate(pgs, 0.5, 0.5);
- gs_setcolorspace(pgs, &rgb_cs);
- spectrum(pgs, 5);
- gs_translate(pgs, 1.2, 0.0);
- /* We must set the CRD before the color space. */
- code = gs_cie_render1_build(&pcrd, mem, "test6");
- if (code < 0)
- return code;
- gs_cie_render1_initialize(mem, pcrd, NULL, &white_point, NULL,
- NULL, NULL, NULL,
- NULL, NULL, NULL,
- NULL, &encode_abc, NULL,
- NULL);
- gs_setcolorrendering(pgs, pcrd);
- gs_cspace_build_CIEABC(&pcs, NULL, mem);
- /* There should be an API for initializing CIE color spaces too.... */
- pabc = pcs->params.abc;
- pabc->common.points.WhitePoint = white_point;
- gs_cie_abc_complete(pabc);
- /* End of initializing the color space. */
- gs_setcolorspace(pgs, pcs);
- spectrum(pgs, 5);
-#ifdef COLOR_MAP_DEVICE
- /* Now test color snapping. */
- cmdev =
- gs_alloc_struct_immovable(mem, gx_device_cmap, &st_device_cmap,
- "cmap device");
- gdev_cmap_init(cmdev, gs_currentdevice(pgs),
- device_cmap_snap_to_primaries);
- gs_setdevice_no_init(pgs, (gx_device *) cmdev);
-#endif /* COLOR_MAP_DEVICE */
- gs_setrgbcolor(pgs, 0.0, 0.0, 0.0); /* back to DeviceRGB space */
- gs_translate(pgs, -1.2, 1.2);
- spectrum(pgs, 5);
- gs_translate(pgs, 1.2, 0.0);
-#ifdef COLOR_MAP_DEVICE
- set_cmap_method(cmdev, device_cmap_monochrome, pgs, mem);
-#endif /* COLOR_MAP_DEVICE */
- spectrum(pgs, 5);
- gs_translate(pgs, -1.2, 1.2);
-#ifdef COLOR_MAP_DEVICE
- set_cmap_method(cmdev, device_cmap_color_to_black_over_white, pgs, mem);
-#endif /* COLOR_MAP_DEVICE */
- spectrum(pgs, 5);
- return 0;
-}
-
-/* ---------------- Test program 7 ---------------- */
-/* Test the C API for non-monotonic halftones. */
-
-#ifdef HALFTONE_FIX
-private int
-test7(gs_state * pgs, gs_memory_t * mem)
-{
- /* Define a non-monotonic 4 x 4 halftone with 4 gray levels. */
- static const byte masks[1 * 4 * 4] =
- {
- /* 0% */
- 0x00, 0x00, 0x00, 0x00,
- /* 25% */
- 0x80, 0x40, 0x20, 0x10,
- /* 50% */
- 0xa0, 0xa0, 0x50, 0x50,
- /* 75% */
- 0xd0, 0xe0, 0x70, 0xb0
- };
- gs_ht *pht;
- int code;
- int i;
-
- /* Fabricate a Type 5 halftone. */
- code = gs_ht_build(&pht, 1, mem);
- dprintf1("ht build code = %d\n", code);
- code = gs_ht_set_mask_comp(pht, 0,
- 4, 4, 4, masks, NULL, NULL);
- dprintf1("set mask code = %d\n", code);
- code = gs_sethalftone(pgs, pht);
- dprintf1("sethalftone code = %d\n", code);
- for (i = 0; i <= 4; ++i) {
- gs_setgray(pgs, i / 4.0);
- fill_rect1(pgs, 100 + i * 100, 100, 50, 50);
- }
- return 0;
-}
-#endif
-
-/* ---------------- Test program 8 ---------------- */
-/* Test partially transparent patterns */
-
-private int
-test8(gs_state * pgs, gs_memory_t * mem)
-{
- /*
- * Define a 16 x 16 pattern using a 4-entry palette
- * (white, red, green, black).
- */
- static const byte pdata[] =
- {
- 0x7f, 0xff, 0x00, 0x03,
- 0x7f, 0xff, 0x00, 0x0c,
- 0x50, 0x00, 0x00, 0x30,
- 0x50, 0x00, 0x00, 0xc0,
- 0x50, 0x00, 0x03, 0x00,
- 0x50, 0x00, 0x0c, 0x00,
- 0x50, 0x00, 0x30, 0x00,
- 0x50, 0x00, 0xc0, 0x00,
- 0xf0, 0x00, 0xc0, 0x00,
- 0xf0, 0x00, 0x30, 0x00,
- 0xf0, 0x00, 0x0c, 0x00,
- 0xf0, 0x00, 0x03, 0x00,
- 0xf0, 0x00, 0x00, 0xc0,
- 0xf0, 0x00, 0x00, 0x30,
- 0xea, 0x55, 0xaa, 0x5c,
- 0xea, 0x55, 0xaa, 0x57,
- };
- gs_depth_bitmap ptile;
- gs_const_string table;
- gs_color_space *pcs;
- gs_client_color ccolor;
- gs_color_space rgb_cs;
-
- gs_cspace_init_DeviceRGB(mem, &rgb_cs);
-
- table.data =
- (const byte *)"\377\377\377\377\000\000\000\377\000\000\000\000";
- table.size = 12;
- gs_cspace_build_Indexed(&pcs, &rgb_cs, 4, &table, mem);
- ptile.data = pdata;
- ptile.raster = 4;
- ptile.size.x = ptile.size.y = 16;
- ptile.id = gs_no_bitmap_id;
- ptile.pix_depth = 2;
- ptile.num_comps = 1;
- gs_makepixmappattern(&ccolor, &ptile, false /*mask */ , NULL /*pmat */ ,
- gs_no_id, pcs, 0 /*white_index */ , pgs, mem);
- {
- gs_rect r;
-
- r.p.x = 100;
- r.p.y = 100;
- r.q.x = 200;
- r.q.y = 200;
- gs_setrgbcolor(pgs, 1.0, 1.0, 0.0);
- gs_rectfill(pgs, &r, 1);
- gs_setpattern(pgs, &ccolor);
- gs_settexturetransparent(pgs, true);
- gs_rectfill(pgs, &r, 1);
- r.p.x += 150;
- r.q.x += 150;
- gs_setrgbcolor(pgs, 1.0, 1.0, 0.0);
- gs_rectfill(pgs, &r, 1);
- gs_setpattern(pgs, &ccolor);
- gs_settexturetransparent(pgs, false);
- gs_rectfill(pgs, &r, 1);
- }
- return 0;
-}
-
-/* type42 test. Lots of setup stuff here since the graphics library
- leaves most font parsing to the client. */
-#include "gxfont.h"
-#include "gxchar.h"
-#include "gsgdata.h"
-#include "gxfont42.h"
-#include "gxfcache.h"
-
-/* big endian accessors */
-#define get_uint16(bptr)\
- (((bptr)[0] << 8) | (bptr)[1])
-#define get_int16(bptr)\
- (((int)get_uint16(bptr) ^ 0x8000) - 0x8000)
-
-private int
-test9_get_int16(const byte *bptr)
-{
- return get_int16(bptr);
-}
-
-private uint
-test9_get_uint16(const byte *bptr)
-{
- return get_uint16(bptr);
-}
-
-private long
-test9_get_int32(const byte *bptr)
-{
- return ((long)get_int16(bptr) << 16) | get_uint16(bptr + 2);
-}
-
-private ulong
-test9_get_uint32(const byte *bptr)
-{
- return ((ulong)get_uint16(bptr) << 16) | get_uint16(bptr + 2);
-}
-
-/* ACCESS is braindamage from gstype42.c - */
-/* Set up a pointer to a substring of the font data. */
-/* Free variables: pfont, string_proc. */
-#define ACCESS(mem, base, length, vptr)\
- BEGIN\
- code = (*string_proc)(pfont, (ulong)(base), length, &vptr);\
- if ( code < 0 ) return code;\
- if ( code > 0 ) return_error(gs_error_invalidfont);\
- END
-
-/* find a tt table by name derived from plchar.c */
-ulong
-test9_tt_find_table(gs_font_type42 *pfont, const char *tname, uint *plen)
-{
- const byte *OffsetTable;
- int code;
- uint numTables;
- const byte *TableDirectory;
- uint i;
- ulong table_dir_offset = 0;
- int (*string_proc)(gs_font_type42 *, ulong, uint, const byte **) =
- pfont->data.string_proc;
-
- /* nb check return values */
- ACCESS(pfont->memory, 0, 12, OffsetTable);
- ACCESS(pfont->memory, table_dir_offset, 12, OffsetTable);
- numTables = test9_get_uint16(OffsetTable + 4);
- ACCESS(pfont->memory, table_dir_offset + 12, numTables * 16, TableDirectory);
- for ( i = 0; i < numTables; ++i ) {
- const byte *tab = TableDirectory + i * 16;
- if ( !memcmp(tab, tname, 4) ) {
- if ( plen )
- *plen = test9_get_uint32(tab + 12);
- return test9_get_uint32(tab + 8);
- }
- }
- return 0;
-}
-
-/* encode, derived from plchar.c */
-private gs_glyph
-test9_tt_encode_char(gs_font *p42, gs_char chr, gs_glyph not_used)
-{
- /* NB encode me */
- return chr - 29;
-}
-
-private gs_char
-test9_tt_decode_glyph(gs_font *p42, gs_glyph glyph)
-{
- return GS_NO_CHAR;
-}
-
-private int
-test9_tt_glyph_name(gs_font *pf, gs_glyph glyph, gs_const_string *pstr)
-{
- return 0;
-}
-
-private int
-test9_tt_string_proc(gs_font *p42, ulong offset, uint length, const byte **pdata)
-{
-
- /* NB bounds check offset + length - use gs_object_size for memory
- buffers - if file read should fail */
- *pdata = p42->client_data + offset;
- return 0;
-}
-
-/* derived from plchar.c */
-private int
-test9_tt_build_char(gs_show_enum *penum, gs_state *pgs, gs_font *pfont, gs_char chr, gs_glyph glyph)
-{
- int code;
- float sbw[4], w2[6];
-
- code = gs_type42_get_metrics((gs_font_type42 *)pfont, glyph, sbw);
- if (code < 0)
- return code;
- w2[0] = sbw[2], w2[1] = sbw[3];
- /* don't ask me about the following, I just work here. */
- {
-#define pbfont ((gs_font_base *)pfont)
-
- const gs_rect *pbbox = &pbfont->FontBBox;
-#undef pbfont
-
- w2[2] = pbbox->p.x, w2[3] = pbbox->p.y;
- w2[4] = pbbox->q.x, w2[5] = pbbox->q.y;
- if ( pfont->PaintType ) {
- double expand = max(1.415, gs_currentmiterlimit(pgs)) *
- gs_currentlinewidth(pgs) / 2;
-
- w2[2] -= expand, w2[3] -= expand;
- w2[4] += expand, w2[5] += expand;
- }
- }
-
- if ( (code = gs_moveto(pgs, 0.0, 0.0)) < 0 )
- return code;
-
- if ( (code = gs_setcachedevice(penum, pgs, w2)) < 0 )
- return code;
-
- code = gs_type42_append(glyph,
- (gs_imager_state *)pgs,
- gx_current_path(pgs),
- &penum->log2_scale,
- gs_show_in_charpath(penum) != cpm_show,
- pfont->PaintType,
- (gs_font_type42 *)pfont);
- if ( code >= 0 )
- code = (pfont->PaintType ? gs_stroke(pgs) : gs_fill(pgs));
- return code;
-}
-
-byte *
-test9_load_font_data(const char *filename, gs_memory_t * mem)
-{
- FILE *in = fopen(filename, gp_fmode_rb);
- byte *data;
- ulong size;
- if (in == NULL)
- return NULL;
- size = (fseek(in, 0L, SEEK_END), ftell(in));
- rewind(in);
- data = gs_alloc_bytes(mem, size, "test9_load_font data");
- if ( data == 0 ) {
- fclose(in);
- return NULL;
- }
-
- /* NB check size */
- fread(data, 1, size, in);
- fclose(in);
- return data;
-}
-
-/* windows tt file name */
-
-#define TTF_FILENAME "/windows/fonts/A028-Ext.ttf"
-
-/* TEST9 NB:
-
- 1) assumes character successfully renders to cache. There should
- be a charpath fallback if looking up the character in the cache
- returns NULL.
-
- 2) Cache memory management needs investigation
-
- 3) This implementation is one character at a time.
-
- 4) needs encoding - fill in test9_tt_encode_char().
-
-*/
-
-private int
-test9(gs_state * pgs, gs_memory_t * mem)
-{
-
- gs_font_type42 *p42 = gs_alloc_struct(mem, gs_font_type42,
- &st_gs_font_type42,
- "new p42");
- gs_font_dir *pfont_dir = gs_font_dir_alloc(mem);
-
- byte *pfont_data = test9_load_font_data(TTF_FILENAME, mem);
-
- if (!pfont_data || !pfont_dir || !p42)
- return -1;
-
- /* no shortage of things to initialize */
- p42->next = p42->prev = 0;
- p42->memory = mem;
- p42->dir = pfont_dir;
- p42->is_resource = false;
- gs_notify_init(&p42->notify_list, gs_memory_stable(mem));
- p42->base = p42;
- p42->client_data = pfont_data;
- p42->WMode = 0;
- p42->PaintType = 0;
- p42->StrokeWidth = 0;
- p42->procs.init_fstack = gs_default_init_fstack;
- p42->procs.next_char_glyph = gs_default_next_char_glyph;
- p42->font_name.size = 0;
- p42->key_name.size = 0;
- p42->procs.glyph_name = test9_tt_glyph_name;
- p42->procs.decode_glyph = test9_tt_decode_glyph;
- p42->procs.define_font = gs_no_define_font;
- p42->procs.make_font = gs_no_make_font;
- p42->procs.font_info = gs_default_font_info;
- p42->procs.glyph_info = gs_default_glyph_info;
- p42->procs.glyph_outline = gs_no_glyph_outline;
- p42->procs.encode_char = test9_tt_encode_char;
- p42->procs.build_char = test9_tt_build_char;
- p42->id = gs_next_ids(mem, 1);
- gs_make_identity(&p42->FontMatrix);
- p42->FontType = ft_TrueType;
- p42->BitmapWidths = true;
- p42->ExactSize = fbit_use_outlines;
- p42->InBetweenSize = fbit_use_outlines;
- p42->TransformedChar = fbit_use_outlines;
- p42->FontBBox.p.x = p42->FontBBox.p.y =
- p42->FontBBox.q.x = p42->FontBBox.q.y = 0;
- uid_set_UniqueID(&p42->UID, p42->id);
- p42->encoding_index = ENCODING_INDEX_UNKNOWN;
- p42->nearest_encoding_index = ENCODING_INDEX_UNKNOWN;
- /* Initialize Type 42 specific data. */
- p42->data.string_proc = test9_tt_string_proc;
- gs_type42_font_init(p42);
-
- gs_definefont(pfont_dir, (gs_font *)p42);
- gs_setfont(pgs, (gs_font *)p42);
- {
- gs_text_params_t text_params;
- gs_text_enum_t *penum;
- byte *mystr = "The quick brown fox";
- floatp FontRenderingEmSize = 20; /* XPS terminology */
- gs_matrix fmat; /* font matrix */
- int code;
- {
- int i;
- if (gs_moveto(pgs, 72.0, 72.0) != 0)
- return -1;
-
- for (i = 0; i < strlen(mystr); i++) {
- dprintf1("%d\n", i);
- text_params.operation = (TEXT_FROM_STRING | TEXT_DO_DRAW | TEXT_RETURN_WIDTH);
- text_params.data.bytes = mystr + i;
- text_params.size = 1;
-
-
- gs_make_identity(&fmat);
- if ((gs_matrix_scale(&fmat, FontRenderingEmSize, FontRenderingEmSize, &fmat) != 0) ||
- (gs_setcharmatrix(pgs, &fmat) != 0) ||
- (gs_text_begin(pgs, &text_params, mem, &penum) != 0) ||
- (gs_text_process(penum) != 0)) {
- dprintf("text_failed\n");
- return -1;
- }
- {
- gs_show_enum *psenum = (gs_show_enum *)penum;
- cached_fm_pair *ppair;
- gs_fixed_point sub_pix_or = {0, 0};
- cached_char *cc;
- gs_matrix cmat;
- gs_currentcharmatrix(pgs, &cmat, true);
- code = gx_lookup_fm_pair(penum->current_font,
- &cmat,
- &penum->log2_scale,
- /* NB design grid */
- false,
- &ppair);
-
- cc = gx_lookup_cached_char(penum->current_font,
- ppair,
- penum->returned.current_glyph,
- /* nb next three assume
- no veritcal writing
- '0', bitdepth '1'
- and no sub pixel
- stuff */
- 0,
- 1,
- &sub_pix_or);
-
- debug_dump_bitmap(cc_bits(cc),
- cc_raster(cc),
- cc->height, "");
- /* update point (device space) */
- gx_path_add_relative_point(gx_current_path(pgs),
- cc->wxy.x,
- cc->wxy.y);
- gs_text_release(penum, "test_9");
-
- }
- }
- }
- }
- return 0;
-}
diff --git a/tools/gslite/gslt.h b/tools/gslite/gslt.h
index 6344023f1..cd309e931 100644
--- a/tools/gslite/gslt.h
+++ b/tools/gslite/gslt.h
@@ -11,7 +11,7 @@
San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
*/
-/* $Id: gslt.h 2461 2006-07-14 18:54:03Z giles $ */
+/* $Id$ */
/* gslt "Ghostscript Lite" convenience header */
/*
@@ -55,7 +55,9 @@ gs_memory_t *gslt_alloc_init(void);
gs_memory_t * gslt_init_library();
gx_device * gslt_init_device(gs_memory_t *mem, char *name);
gs_state *gslt_init_state(gs_memory_t *mem, gx_device *dev);
-void gslt_free_library(gs_memory_t *mem, gx_device *dev, gs_state *pgs);
+void gslt_free_state(gs_memory_t *mem, gs_state *pgs);
+void gslt_free_device(gs_memory_t *mem, gx_device *dev);
+void gslt_free_library(gs_memory_t *mem);
void gslt_get_device_param(gs_memory_t *mem, gx_device *dev, char *key);
void gslt_set_device_param(gs_memory_t *mem, gx_device *dev, char *key, char *val);
diff --git a/tools/gslite/gslt.mak b/tools/gslite/gslt.mak
new file mode 100644
index 000000000..21f494d16
--- /dev/null
+++ b/tools/gslite/gslt.mak
@@ -0,0 +1,56 @@
+GSLT_CC=$(CC_) $(I_)$(GSLTSRCDIR)$(_I) $(I_)$(GLSRCDIR)$(_I)\
+ $(I_)$(GLGENDIR)$(_I) $(I_)$(PSRCDIR)$(_I)\
+ $(I_)$(ZSRCDIR)$(_I)
+GSLTO_=$(O_)$(GSLTOBJ)
+GSLTOBJ=$(GLOBJDIR)$(D)
+GSLTSRC=$(GSLTSRCDIR)$(D)
+
+GSLT_OBJS = \
+ $(GSLTOBJ)gslt_alloc.$(OBJ) \
+ $(GSLTOBJ)gslt_init.$(OBJ) \
+ $(GSLTOBJ)gslt_image.$(OBJ) \
+ $(GSLTOBJ)gslt_image_jpeg.$(OBJ) \
+ $(GSLTOBJ)gslt_image_png.$(OBJ) \
+ $(GSLTOBJ)gslt_image_tiff.$(OBJ) \
+ $(GSLTOBJ)gslt_font_cache.$(OBJ) \
+ $(GSLTOBJ)gslt_font_encoding.$(OBJ) \
+ $(GSLTOBJ)gslt_font_glyph.$(OBJ) \
+ $(GSLTOBJ)gslt_font_ttf.$(OBJ) \
+ $(GSLTOBJ)gslt_font_cff.$(OBJ) \
+ $(GSLTOBJ)gslt_stubs.$(OBJ) \
+
+$(GSLTOBJ)gslt_alloc.$(OBJ) : $(GSLTSRC)gslt_alloc.c
+ $(GSLT_CC) $(GSLTO_)gslt_alloc.$(OBJ) $(C_) $(GSLTSRC)gslt_alloc.c
+
+$(GSLTOBJ)gslt_init.$(OBJ) : $(GSLTSRC)gslt_init.c
+ $(GSLT_CC) $(GSLTO_)gslt_init.$(OBJ) $(C_) $(GSLTSRC)gslt_init.c
+
+$(GSLTOBJ)gslt_image.$(OBJ) : $(GSLTSRC)gslt_image.c
+ $(GSLT_CC) $(GSLTO_)gslt_image.$(OBJ) $(C_) $(GSLTSRC)gslt_image.c
+
+$(GSLTOBJ)gslt_image_png.$(OBJ) : $(GSLTSRC)gslt_image_png.c
+ $(GSLT_CC) $(GSLTO_)gslt_image_png.$(OBJ) $(C_) $(GSLTSRC)gslt_image_png.c
+
+$(GSLTOBJ)gslt_image_jpeg.$(OBJ) : $(GSLTSRC)gslt_image_jpeg.c
+ $(GSLT_CC) $(GSLTO_)gslt_image_jpeg.$(OBJ) $(C_) $(GSLTSRC)gslt_image_jpeg.c
+
+$(GSLTOBJ)gslt_image_tiff.$(OBJ) : $(GSLTSRC)gslt_image_tiff.c
+ $(GSLT_CC) $(GSLTO_)gslt_image_tiff.$(OBJ) $(C_) $(GSLTSRC)gslt_image_tiff.c
+
+$(GSLTOBJ)gslt_font_cache.$(OBJ) : $(GSLTSRC)gslt_font_cache.c
+ $(GSLT_CC) $(GSLTO_)gslt_font_cache.$(OBJ) $(C_) $(GSLTSRC)gslt_font_cache.c
+
+$(GSLTOBJ)gslt_font_encoding.$(OBJ) : $(GSLTSRC)gslt_font_encoding.c
+ $(GSLT_CC) $(GSLTO_)gslt_font_encoding.$(OBJ) $(C_) $(GSLTSRC)gslt_font_encoding.c
+
+$(GSLTOBJ)gslt_font_glyph.$(OBJ) : $(GSLTSRC)gslt_font_glyph.c
+ $(GSLT_CC) $(GSLTO_)gslt_font_glyph.$(OBJ) $(C_) $(GSLTSRC)gslt_font_glyph.c
+
+$(GSLTOBJ)gslt_font_ttf.$(OBJ) : $(GSLTSRC)gslt_font_ttf.c
+ $(GSLT_CC) $(GSLTO_)gslt_font_ttf.$(OBJ) $(C_) $(GSLTSRC)gslt_font_ttf.c
+
+$(GSLTOBJ)gslt_font_cff.$(OBJ) : $(GSLTSRC)gslt_font_cff.c
+ $(GSLT_CC) $(GSLTO_)gslt_font_cff.$(OBJ) $(C_) $(GSLTSRC)gslt_font_cff.c
+
+$(GSLTOBJ)gslt_stubs.$(OBJ) : $(GSLTSRC)gslt_stubs.c
+ $(GSLT_CC) $(GSLTO_)gslt_stubs.$(OBJ) $(C_) $(GSLTSRC)gslt_stubs.c
diff --git a/tools/gslite/gslt_alloc.c b/tools/gslite/gslt_alloc.c
index d0ae9685d..f57ebf4ae 100644
--- a/tools/gslite/gslt_alloc.c
+++ b/tools/gslite/gslt_alloc.c
@@ -8,6 +8,10 @@
#include "gsstype.h"
#include "gslt_alloc.h"
+static int num_alloc_called = 0;
+static int num_resize_called = 0;
+static int num_free_called = 0;
+
/* a screwed up mess, we try to make it manageable here */
extern const gs_memory_struct_type_t st_bytes;
@@ -84,6 +88,7 @@ gslt_alloc(gs_memory_t *mem, uint size, gs_memory_type_ptr_t type, client_name_t
byte *ptr = (byte *)malloc(newsize);
if ( !ptr )
return NULL;
+ num_alloc_called ++;
#ifdef DEBUG
if_debug2('A', "[da]:malloc:%p:%s\n", &ptr[minsize * 2], cname );
#endif
@@ -171,6 +176,8 @@ gslt_resize_object(gs_memory_t * mem, void *obj, uint new_num_elements, client_n
if ( !ptr )
return NULL;
+ num_resize_called ++;
+
/* da for debug allocator - so scripts can parse the trace */
if_debug2('A', "[da]:realloc:%p:%s\n", ptr, cname );
/* we reset size and type - the type in case realloc moved us */
@@ -191,6 +198,8 @@ gslt_free_object(gs_memory_t * mem, void *ptr, client_name_t cname)
memset(bptr-header_size, 0xee, header_size + get_size(ptr));
#endif
free(bptr-header_size);
+
+ num_free_called ++;
#ifdef DEBUG
/* da for debug allocator - so scripts can parse the trace */
@@ -388,3 +397,12 @@ gslt_alloc_init()
return (gs_memory_t *)&gslt_mem;
}
+void
+gslt_alloc_print_leaks(void)
+{
+ dprintf1("number of allocs: %d\n", num_alloc_called);
+ dprintf1("number of frees: %d\n", num_free_called);
+ dprintf1("number of resizes: %d\n", num_resize_called);
+ dprintf1("number of leaked chunks: %d\n", num_alloc_called - num_free_called);
+}
+
diff --git a/tools/gslite/gslt_alloc.h b/tools/gslite/gslt_alloc.h
index e4185bfca..280a20dbd 100644
--- a/tools/gslite/gslt_alloc.h
+++ b/tools/gslite/gslt_alloc.h
@@ -1,3 +1,5 @@
/* A simple memory allocator, based on the the allocator for ghostpcl */
gs_memory_t *gslt_alloc_init(void);
+void gslt_alloc_print_leaks(void);
+
diff --git a/tools/gslite/gslt_font.h b/tools/gslite/gslt_font.h
new file mode 100644
index 000000000..8b33e3033
--- /dev/null
+++ b/tools/gslite/gslt_font.h
@@ -0,0 +1,138 @@
+/* Copyright (C) 2006 artofcode LLC.
+ All Rights Reserved.
+
+ This software is provided AS-IS with no warranty, either express or
+ implied.
+
+ This software is distributed under license and may not be copied, modified
+ or distributed except as expressly authorized under the terms of that
+ license. Refer to licensing information at http://www.artifex.com/
+ or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
+ San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
+*/
+
+/*
+ * Public types and functions for
+ * OpenType font API using Ghostscript graphics library.
+ *
+ * This file requires either gslite.h or the internal gs headers
+ * for gs_memory_t, gx_device, gs_state and gs_matrix.
+ */
+
+typedef struct gslt_font_s gslt_font_t;
+typedef struct gslt_glyph_metrics_s gslt_glyph_metrics_t;
+typedef struct gslt_glyph_bitmap_s gslt_glyph_bitmap_t;
+typedef struct gslt_outline_walker_s gslt_outline_walker_t;
+
+struct gslt_glyph_metrics_s
+{
+ float hadv, vadv, vorg;
+};
+
+struct gslt_glyph_bitmap_s
+{
+ int w, h, stride; /* bitmap size; stride is number of bytes per line */
+ int lsb, top; /* bitmap offset (left-side-bearing and top) */
+ unsigned char *data; /* bitmap data */
+#ifdef USE_OLD_GS
+ int refs; /* private for now */
+#else
+ void *cc; /* cc slot that the data uses */
+#endif
+};
+
+struct gslt_outline_walker_s
+{
+ void *user;
+ int (*moveto)(void *user, float x, float y);
+ int (*lineto)(void *user, float x, float y);
+ int (*curveto)(void *user, float x0, float y0, float x1, float y1, float x2, float y2);
+ int (*closepath)(void *user);
+};
+
+/*
+ * Create the font cache machinery.
+ */
+gs_font_dir * gslt_new_font_cache(gs_memory_t *mem);
+
+/*
+ * Destroy the font machinery (and all associated fonts).
+ */
+void gslt_free_font_cache(gs_memory_t *mem, gs_font_dir *cache);
+
+/*
+ * Create and initialize a font structure from the
+ * font file, using index to select which font in TTC font
+ * collections.
+ *
+ * The font object retains a pointer to the memory passed in,
+ * but does not assume ownership. Free the memory
+ * after freeing the font.
+ * Return NULL on failure.
+ */
+gslt_font_t * gslt_new_font(gs_memory_t *mem, gs_font_dir *cache, char *buf, int buflen, int index);
+
+/*
+ * Destroy a font structure.
+ */
+void gslt_free_font(gs_memory_t *mem, gslt_font_t *font);
+
+/*
+ * Return the number of encoding (cmap) sub-tables in a font.
+ * Return zero if there is no cmap table at all.
+ */
+int gslt_count_font_encodings(gslt_font_t *font);
+
+/*
+ * Identify the platform and encoding id of a cmap subtable.
+ */
+int gslt_identify_font_encoding(gslt_font_t *font, int idx, int *pid, int *eid);
+
+/*
+ * Select a cmap subtable for use with the gslt_encode_font_char() function.
+ */
+int gslt_select_font_encoding(gslt_font_t *font, int idx);
+
+/*
+ * Encode a character and return its glyph index.
+ * Glyph 0 is always the "undefined" character.
+ * Any unencoded characters encoded will map to glyph 0.
+ *
+ * Do not call this without having selected an encoding first.
+ */
+int gslt_encode_font_char(gslt_font_t *font, int key);
+
+/*
+ * Walk the outline of a glyph, calling the functions specified.
+ */
+int gslt_outline_font_glyph(gs_state *pgs, gslt_font_t *font, int gid, gslt_outline_walker_t *walker);
+
+/*
+ * Render a glyph using a transform matrix, and fill in the
+ * bitmap struct. All values are in device space.
+ *
+ * The data pointer will point into the internal
+ * glyph bitmap cache in ghostscript, treat it as read only.
+ *
+ * Return -1 on failure.
+ */
+int gslt_render_font_glyph(gs_state *pgs, gslt_font_t *font, gs_matrix *tm, int gid, gslt_glyph_bitmap_t *slot);
+
+/*
+ * The glyph bitmap data is reference counted in the cache.
+ * gslt_render_font_glyph will increase the reference count by one
+ * automatically. Use the following functions to increase and decrease
+ * the reference count manually. You must call gslt_release_font_glyph
+ * when you don't need the bitmap anymore.
+ */
+void gslt_retain_font_glyph(gs_memory_t *mem, gslt_glyph_bitmap_t *slot);
+void gslt_release_font_glyph(gs_memory_t *mem, gslt_glyph_bitmap_t *slot);
+
+/*
+ * Fill in the metrics for a glyph, scaled by the internal font matrix.
+ * The design space (usually 1000 or 2048 for an em) is mapped to 1.0.
+ *
+ * Return -1 on failure.
+ */
+int gslt_measure_font_glyph(gs_state *pgs, gslt_font_t *font, int gid, gslt_glyph_metrics_t *mtx);
+
diff --git a/tools/gslite/gslt_font_cache.c b/tools/gslite/gslt_font_cache.c
new file mode 100644
index 000000000..2a7e0022c
--- /dev/null
+++ b/tools/gslite/gslt_font_cache.c
@@ -0,0 +1,174 @@
+/* Copyright (C) 2006 artofcode LLC.
+ All Rights Reserved.
+
+ This software is provided AS-IS with no warranty, either express or
+ implied.
+
+ This software is distributed under license and may not be copied, modified
+ or distributed except as expressly authorized under the terms of that
+ license. Refer to licensing information at http://www.artifex.com/
+ or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
+ San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
+*/
+
+#include "gslt_font_int.h"
+
+#include "gslt.h"
+#include "gslt_font.h"
+
+
+/*
+ * The font cache is a gs_font_dir.
+ * It has some parameters that need to be set,
+ * do so here.
+ */
+
+gs_font_dir *
+gslt_new_font_cache(gs_memory_t *mem)
+{
+ gs_font_dir *fontdir;
+
+ int smax = 50; /* number of scaled fonts */
+ int bmax = 500000; /* space for cached chars */
+ int mmax = 200; /* number of cached font/matrix pairs */
+ int cmax = 5000; /* number of cached chars */
+ int upper = 32000; /* max size of a single cached char */
+
+ fontdir = gs_font_dir_alloc2_limits(mem, mem, smax, bmax, mmax, cmax, upper);
+ if (!fontdir)
+ {
+ gs_throw(-1, "cannot gs_font_dir_alloc2_limits()");
+ return NULL;
+ }
+
+ gs_setaligntopixels(fontdir, 1); /* no subpixels */
+ gs_setgridfittt(fontdir, 3); /* see gx_ttf_outline for values */
+
+ return fontdir;
+}
+
+void
+gslt_free_font_cache(gs_memory_t *mem, gs_font_dir *fontdir)
+{
+ gs_free_object(mem, fontdir, "gs_font_dir");
+}
+
+
+/*
+ * Find the offset and length of an SFNT table.
+ * Return -1 if no table by the specified name is found.
+ */
+
+int
+gslt_find_sfnt_table(gslt_font_t *xf, char *name, int *lengthp)
+{
+ byte *directory;
+ int offset;
+ int ntables;
+ int i;
+
+ if (xf->length < 12)
+ return -1;
+
+ if (!memcmp(xf->data, "ttcf", 4))
+ {
+ int nfonts = u32(xf->data + 8);
+ if (xf->subfontid < 0 || xf->subfontid >= nfonts)
+ return -1;
+ offset = u32(xf->data + 12 + xf->subfontid * 4);
+ }
+ else
+ {
+ offset = 0;
+ }
+
+ ntables = u16(xf->data + offset + 4);
+ if (xf->length < offset + 12 + ntables * 16)
+ return -1;
+
+ for (i = 0; i < ntables; i++)
+ {
+ byte *entry = xf->data + offset + 12 + i * 16;
+ if (!memcmp(entry, name, 4))
+ {
+ if (lengthp)
+ *lengthp = u32(entry + 12);
+ return u32(entry + 8);
+ }
+ }
+
+ return -1;
+}
+
+/*
+ * Load and initialize a font struct from a file.
+ */
+
+gslt_font_t *
+gslt_new_font(gs_memory_t *mem, gs_font_dir *fontdir, char *buf, int buflen, int subfontid)
+{
+ gslt_font_t *xf;
+ int t;
+
+ xf = (void*) gs_alloc_bytes(mem, sizeof(gslt_font_t), "gslt_font struct");
+ if (!xf)
+ {
+ gs_throw(-1, "out of memory");
+ return NULL;
+ }
+
+ xf->data = (byte*)buf;
+ xf->length = buflen;
+ xf->font = NULL;
+
+ xf->subfontid = subfontid;
+ xf->cmaptable = 0;
+ xf->cmapsubcount = 0;
+ xf->cmapsubtable = 0;
+ xf->usepua = 0;
+
+ xf->cffdata = 0;
+ xf->cffend = 0;
+ xf->gsubrs = 0;
+ xf->subrs = 0;
+ xf->charstrings = 0;
+
+ if (memcmp(xf->data, "OTTO", 4) == 0)
+ t = gslt_init_postscript_font(mem, fontdir, xf);
+ else if (memcmp(xf->data, "\0\1\0\0", 4) == 0)
+ t = gslt_init_truetype_font(mem, fontdir, xf);
+ else if (memcmp(xf->data, "true", 4) == 0)
+ t = gslt_init_truetype_font(mem, fontdir, xf);
+ else if (memcmp(xf->data, "ttcf", 4) == 0)
+ t = gslt_init_truetype_font(mem, fontdir, xf);
+ else
+ {
+ gslt_free_font(mem, xf);
+ gs_throw(-1, "not an opentype font");
+ return NULL;
+ }
+
+ if (t < 0)
+ {
+ gslt_free_font(mem, xf);
+ gs_rethrow(-1, "cannot init font");
+ return NULL;
+ }
+
+ t = gslt_load_sfnt_cmap(xf);
+ if (t < 0)
+ {
+ errprintf("warning: no cmap table found in font\n");
+ }
+
+ return xf;
+}
+
+void
+gslt_free_font(gs_memory_t *mem, gslt_font_t *xf)
+{
+ gs_font_finalize(xf->font);
+ gs_free_object(mem, xf->font, "font object");
+ gs_free_object(mem, xf, "gslt_font struct");
+}
+
diff --git a/tools/gslite/gslt_font_cff.c b/tools/gslite/gslt_font_cff.c
new file mode 100644
index 000000000..36ea82cd8
--- /dev/null
+++ b/tools/gslite/gslt_font_cff.c
@@ -0,0 +1,967 @@
+/* Copyright (C) 2006 artofcode LLC.
+ All Rights Reserved.
+
+ This software is provided AS-IS with no warranty, either express or
+ implied.
+
+ This software is distributed under license and may not be copied, modified
+ or distributed except as expressly authorized under the terms of that
+ license. Refer to licensing information at http://www.artifex.com/
+ or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
+ San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
+*/
+
+#include "gslt_font_int.h"
+
+#include "gslt.h"
+#include "gslt_font.h"
+
+/*
+ * OpenType Tables
+ *
+ * Required: cmap, head, hhea, hmtx, maxp, name, OS/2, post
+ * TrueType: cvt, fpgm, glyf, loca, prep
+ * Postscript: CFF, VORG
+ * Typographic: BASE, GDEF, GPOS, GSUB, JSTF
+ * Other: DSIG, gasp, hdmx, kern, LTSH, PCLT, VDMX, vhea, vmtx
+ */
+
+/* Access glyph data through the CharStrings INDEX */
+
+// zfont1.c
+// zfont2.c
+// zchar1.c
+// zcharout.c
+// gxtype1.c
+// gxfont1.h
+
+private byte * gslt_count_cff_index(byte *p, byte *e, int *countp);
+private byte * gslt_find_cff_index(byte *p, byte *e, int idx, byte **pp, byte **ep);
+
+private int subrbias(int count)
+{
+ return count < 1240 ? 107 : count < 33900 ? 1131 : 32768;
+}
+
+private int uofs(byte *p, int offsize)
+{
+ if (offsize == 1) return p[0];
+ if (offsize == 2) return u16(p);
+ if (offsize == 3) return u24(p);
+ if (offsize == 4) return u32(p);
+ return 0;
+}
+
+private byte *
+gslt_read_cff_real(byte *p, byte *e, float *val)
+{
+ char buf[64];
+ char *txt = buf;
+
+ /* b0 was 30 */
+
+ while (txt < buf + (sizeof buf) - 3 && p < e)
+ {
+ int b, n;
+
+ b = *p++;
+
+ n = (b >> 4) & 0xf;
+ if (n < 0xA) { *txt++ = n + '0'; }
+ else if (n == 0xA) { *txt++ = '.'; }
+ else if (n == 0xB) { *txt++ = 'E'; }
+ else if (n == 0xC) { *txt++ = 'E'; *txt++ = '-'; }
+ else if (n == 0xE) { *txt++ = '-'; }
+ else if (n == 0xF) { break; }
+
+ n = b & 0xf;
+ if (n < 0xA) { *txt++ = n + '0'; }
+ else if (n == 0xA) { *txt++ = '.'; }
+ else if (n == 0xB) { *txt++ = 'E'; }
+ else if (n == 0xC) { *txt++ = 'E'; *txt++ = '-'; }
+ else if (n == 0xE) { *txt++ = '-'; }
+ else if (n == 0xF) { break; }
+ }
+
+ *txt = 0;
+
+ *val = atof(buf);
+
+ return p;
+}
+
+private byte *
+gslt_read_cff_integer(byte *p, byte *e, int b0, int *val)
+{
+ int b1, b2, b3, b4;
+
+ if (b0 == 28)
+ {
+ if (p + 2 > e)
+ {
+ gs_throw(-1, "corrupt dictionary (integer)");
+ return 0;
+ }
+ b1 = *p++;
+ b2 = *p++;
+ *val = (b1 << 8) | b2;
+ }
+
+ else if (b0 == 29)
+ {
+ if (p + 4 > e)
+ {
+ gs_throw(-1, "corrupt dictionary (integer)");
+ return 0;
+ }
+ b1 = *p++;
+ b2 = *p++;
+ b3 = *p++;
+ b4 = *p++;
+ *val = (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
+ }
+
+ else if (b0 < 247)
+ {
+ *val = b0 - 139;
+ }
+
+ else if (b0 < 251)
+ {
+ if (p + 1 > e)
+ {
+ gs_throw(-1, "corrupt dictionary (integer)");
+ return 0;
+ }
+ b1 = *p++;
+ *val = (b0 - 247) * 256 + b1 + 108;
+ }
+
+ else
+ {
+ if (p + 1 > e)
+ {
+ gs_throw(-1, "corrupt dictionary (integer)");
+ return 0;
+ }
+ b1 = *p++;
+ *val = -(b0 - 251) * 256 - b1 - 108;
+ }
+
+ return p;
+}
+
+private int
+gslt_read_cff_dict(byte *p, byte *e, gslt_font_t *fontobj, gs_font_type1 *pt1)
+{
+ struct { int ival; float fval; } args[48];
+ int offset;
+ int b0, n;
+ float f;
+ int i;
+
+ int privatelen = 0;
+ int privateofs = 0;
+
+ offset = p - fontobj->cffdata;
+
+ n = 0;
+ while (p < e)
+ {
+ b0 = *p++;
+
+ if (b0 < 22)
+ {
+ if (b0 == 12)
+ {
+ if (p + 1 > e)
+ {
+ return gs_throw(-1, "corrupt dictionary (operator)");
+ }
+ b0 = 0x100 | *p++;
+ }
+
+ /* some CFF file offsets */
+
+ if (b0 == 17)
+ {
+ fontobj->charstrings = fontobj->cffdata + args[0].ival;
+ }
+
+ if (b0 == 18)
+ {
+ privatelen = args[0].ival;
+ privateofs = args[1].ival;
+ }
+
+ if (b0 == 19)
+ {
+ fontobj->subrs = fontobj->cffdata + offset + args[0].ival;
+ }
+
+ if (b0 == (256 | 36))
+ errprintf("warning: cid cff fonts not supported yet");
+ if (b0 == (256 | 37))
+ errprintf("warning: cid cff fonts not supported yet");
+
+ /* Type1 stuff that need to be set for the pt1 struct */
+
+ if (b0 == (256 | 6))
+ {
+ if (args[0].ival == 1)
+ {
+ pt1->data.interpret = gs_type1_interpret;
+ pt1->data.lenIV = -1; // FIXME
+ }
+ }
+
+ if (b0 == (256 | 7))
+ {
+ pt1->FontMatrix.xx = args[0].fval * 1000;
+ pt1->FontMatrix.xy = args[1].fval * 1000;
+ pt1->FontMatrix.yx = args[2].fval * 1000;
+ pt1->FontMatrix.yy = args[3].fval * 1000;
+ pt1->FontMatrix.tx = args[4].fval * 1000;
+ pt1->FontMatrix.ty = args[5].fval * 1000;
+ }
+
+ if (b0 == 5)
+ {
+ pt1->FontBBox.p.x = args[0].fval;
+ pt1->FontBBox.p.y = args[1].fval;
+ pt1->FontBBox.q.x = args[2].fval;
+ pt1->FontBBox.q.y = args[3].fval;
+ }
+
+ if (b0 == 20)
+ pt1->data.defaultWidthX = float2fixed(args[0].fval);
+
+ if (b0 == 21)
+ pt1->data.nominalWidthX = float2fixed(args[0].fval);
+
+ if (b0 == (256 | 19))
+ pt1->data.initialRandomSeed = args[0].ival;
+
+ /* Monday morning blues */
+
+ if (b0 == 6)
+ {
+ pt1->data.BlueValues.count = n / 2;
+ for (f = 0, i = 0; i < n; f += args[i].fval, i++)
+ pt1->data.BlueValues.values[i] = f;
+ }
+
+ if (b0 == 7)
+ {
+ pt1->data.OtherBlues.count = n / 2;
+ for (f = 0, i = 0; i < n; f += args[i].fval, i++)
+ pt1->data.OtherBlues.values[i] = f;
+ }
+
+ if (b0 == 8)
+ {
+ pt1->data.FamilyBlues.count = n / 2;
+ for (f = 0, i = 0; i < n; f += args[i].fval, i++)
+ pt1->data.FamilyBlues.values[i] = f;
+ }
+
+ if (b0 == 9)
+ {
+ pt1->data.FamilyOtherBlues.count = n / 2;
+ for (f = 0, i = 0; i < n; f += args[i].fval, i++)
+ pt1->data.FamilyOtherBlues.values[i] = f;
+ }
+
+ if (b0 == 10)
+ {
+ pt1->data.StdHW.count = 1;
+ pt1->data.StdHW.values[0] = args[0].fval;
+ }
+
+ if (b0 == 11)
+ {
+ pt1->data.StdVW.count = 1;
+ pt1->data.StdVW.values[0] = args[0].fval;
+ }
+
+ if (b0 == (256 | 9))
+ pt1->data.BlueScale = args[0].fval;
+
+ if (b0 == (256 | 10))
+ pt1->data.BlueShift = args[0].fval;
+
+ if (b0 == (256 | 11))
+ pt1->data.BlueFuzz = args[0].fval;
+
+ if (b0 == (256 | 12))
+ {
+ pt1->data.StemSnapH.count = n;
+ for (f = 0, i = 0; i < n; f += args[i].fval, i++)
+ pt1->data.StemSnapH.values[i] = f;
+ }
+
+ if (b0 == (256 | 13))
+ {
+ pt1->data.StemSnapV.count = n;
+ for (f = 0, i = 0; i < n; f += args[i].fval, i++)
+ pt1->data.StemSnapV.values[i] = f;
+ }
+
+ if (b0 == (256 | 14))
+ pt1->data.ForceBold = args[0].ival;
+
+ if (b0 == (256 | 17))
+ pt1->data.LanguageGroup = args[0].ival;
+
+ if (b0 == (256 | 18))
+ pt1->data.ExpansionFactor = args[0].fval;
+
+ n = 0;
+ }
+
+ else
+ {
+ if (b0 == 30)
+ {
+ p = gslt_read_cff_real(p, e, &args[n].fval);
+ if (!p)
+ return gs_throw(-1, "corrupt dictionary operand");
+ args[n].ival = (int) args[n].fval;
+ n++;
+ }
+ else if (b0 == 28 || b0 == 29 || (b0 >= 32 && b0 <= 254))
+ {
+ p = gslt_read_cff_integer(p, e, b0, &args[n].ival);
+ if (!p)
+ return gs_throw(-1, "corrupt dictionary operand");
+ args[n].fval = (float) args[n].ival;
+ n++;
+ }
+ else
+ {
+ return gs_throw1(-1, "corrupt dictionary operand (b0 = %d)", b0);
+ }
+ }
+ }
+
+ /* recurse for the private dictionary */
+ if (privatelen)
+ {
+ int code = gslt_read_cff_dict(
+ fontobj->cffdata + privateofs,
+ fontobj->cffdata + privateofs + privatelen,
+ fontobj, pt1);
+ if (code < 0)
+ return gs_rethrow(code, "cannot read private dictionary");
+ }
+
+ return 0;
+}
+
+/*
+ * Get the number of items in an INDEX, and return
+ * a pointer to the end of the INDEX or NULL on
+ * failure.
+ */
+private byte *
+gslt_count_cff_index(byte *p, byte *e, int *countp)
+{
+ int count, offsize, last;
+
+ if (p + 3 > e)
+ {
+ gs_throw(-1, "not enough data for index header");
+ return 0;
+ }
+
+ count = u16(p); p += 2;
+ *countp = count;
+
+ if (count == 0)
+ return p;
+
+ offsize = *p++;
+
+ if (offsize < 1 || offsize > 4)
+ {
+ gs_throw(-1, "corrupt index header");
+ return 0;
+ }
+
+ if (p + count * offsize > e)
+ {
+ gs_throw(-1, "not enough data for index offset table");
+ return 0;
+ }
+
+ p += count * offsize;
+ last = uofs(p, offsize);
+ p += offsize;
+ p --; /* stupid offsets */
+
+ if (p + last > e)
+ {
+ gs_throw(-1, "not enough data for index data");
+ return 0;
+ }
+
+ p += last;
+
+ return p;
+}
+
+/*
+ * Locate and store pointers to the data of an
+ * item in the index that starts at 'p'.
+ * Return pointer to the end of the index,
+ * or NULL on failure.
+ */
+private byte *
+gslt_find_cff_index(byte *p, byte *e, int idx, byte **pp, byte **ep)
+{
+ int count, offsize, sofs, eofs, last;
+
+ if (p + 3 > e)
+ {
+ gs_throw(-1, "not enough data for index header");
+ return 0;
+ }
+
+ count = u16(p); p += 2;
+ if (count == 0)
+ return 0;
+
+ offsize = *p++;
+
+ if (offsize < 1 || offsize > 4)
+ {
+ gs_throw(-1, "corrupt index header");
+ return 0;
+ }
+
+ if (p + count * offsize > e)
+ {
+ gs_throw(-1, "not enough data for index offset table");
+ return 0;
+ }
+
+ if (idx < 0 || idx >= count)
+ {
+ gs_throw(-1, "tried to access non-existing index item");
+ return 0;
+ }
+
+ sofs = uofs(p + idx * offsize, offsize);
+ eofs = uofs(p + (idx + 1) * offsize, offsize);
+ last = uofs(p + count * offsize, offsize);
+
+ p += count * offsize;
+ p += offsize;
+ p --; /* stupid offsets */
+
+ if (p + last > e)
+ {
+ gs_throw(-1, "not enough data for index data");
+ return 0;
+ }
+
+ if (sofs < 0 || eofs < 0 || sofs > eofs || eofs > last)
+ {
+ gs_throw(-1, "corrupt index offset table");
+ return 0;
+ }
+
+ *pp = p + sofs;
+ *ep = p + eofs;
+
+ return p + last;
+}
+
+/*
+ * Scan the CFF file structure and extract important data.
+ */
+
+private int
+gslt_read_cff_file(gslt_font_t *fontobj, gs_font_type1 *pt1)
+{
+ byte *p = fontobj->cffdata;
+ byte *e = fontobj->cffend;
+ byte *dictp, *dicte;
+ int ngsubrs;
+ int nsubrs;
+ int count;
+ int code;
+
+ /* CFF header */
+ {
+ int major, minor, hdrsize, offsize;
+
+ if (p + 4 > e)
+ return gs_throw(-1, "not enough data for header");
+
+ major = *p++;
+ minor = *p++;
+ hdrsize = *p++;
+ offsize = *p++;
+
+ if (major != 1 || minor != 0)
+ return gs_throw(-1, "not a CFF 1.0 file");
+
+ if (p + hdrsize - 4 > e)
+ return gs_throw(-1, "not enough data for extended header");
+ }
+
+ /* Name INDEX */
+ p = gslt_count_cff_index(p, e, &count);
+ if (!p)
+ return gs_throw(-1, "cannot read name index");
+ if (count != 1)
+ return gs_throw(-1, "file did not contain exactly one font");
+
+ /* Top Dict INDEX */
+ p = gslt_find_cff_index(p, e, 0, &dictp, &dicte);
+ if (!p)
+ return gs_throw(-1, "cannot read top dict index");
+
+ /* String index */
+ p = gslt_count_cff_index(p, e, &count);
+ if (!p)
+ return gs_throw(-1, "cannot read string index");
+
+ /* Global Subr INDEX */
+ fontobj->gsubrs = p;
+ p = gslt_count_cff_index(p, e, &ngsubrs);
+ if (!p)
+ return gs_throw(-1, "cannot read gsubr index");
+
+ /* Read the top and private dictionaries */
+ code = gslt_read_cff_dict(dictp, dicte, fontobj, pt1);
+ if (code < 0)
+ return gs_rethrow(code, "cannot read top dictionary");
+
+ /* Check the subrs index */
+ nsubrs = 0;
+ if (fontobj->subrs)
+ {
+ p = gslt_count_cff_index(fontobj->subrs, e, &nsubrs);
+ if (!p)
+ return gs_rethrow(-1, "cannot read subrs index");
+ }
+
+ /* Check the charstrings index */
+ if (fontobj->charstrings)
+ {
+ p = gslt_count_cff_index(fontobj->charstrings, e, &count);
+ if (!p)
+ return gs_rethrow(-1, "cannot read charstrings index");
+ }
+
+ pt1->data.subroutineNumberBias = subrbias(nsubrs);
+ pt1->data.gsubrNumberBias = subrbias(ngsubrs);
+ // nominal and defaultWidthX
+
+ return 0;
+}
+
+
+/*
+ *
+ */
+
+private gs_glyph
+gslt_post_callback_encode_char(gs_font *pfont, gs_char chr, gs_glyph_space_t spc)
+{
+ gslt_font_t *xf = pfont->client_data;
+ int value;
+ value = gslt_encode_font_char(xf, chr);
+ if (value == 0)
+ return gs_no_glyph;
+ return value;
+}
+
+private gs_char
+gslt_post_callback_decode_glyph(gs_font *p42, gs_glyph glyph)
+{
+ return GS_NO_CHAR;
+}
+
+private int
+gslt_post_callback_glyph_name(gs_font *pf, gs_glyph glyph, gs_const_string *pstr)
+{
+ return -1;
+}
+
+private int
+gslt_post_callback_glyph_info(gs_font *font, gs_glyph glyph,
+ const gs_matrix *pmat, int members, gs_glyph_info_t *info)
+{
+ return -1;
+}
+
+private int
+gslt_post_callback_glyph_outline(gs_font *font, int wmode, gs_glyph glyph,
+ const gs_matrix *pmat, gx_path *ppath, double sbw[4])
+{
+ dprintf2("glyph_outline wmode=%d glyph=%d\n", wmode, glyph);
+ return -1;
+}
+
+typedef struct gs_type1exec_state_s
+{
+ gs_type1_state cis; /* must be first */
+ /* i_ctx_t *i_ctx_p; */ /* so push/pop can access o-stack */
+ double sbw[4];
+ gs_rect char_bbox;
+ /*
+ * The following elements are only used locally to make the stack clean
+ * for OtherSubrs: they don't need to be declared for the garbage
+ * collector.
+ */
+ void * save_args[6];
+ int num_args;
+ bool AlignToPixels;
+} gs_type1exec_state;
+
+private int
+gslt_post_callback_glyph_data(gs_font_type1 * pfont, gs_glyph glyph, gs_glyph_data_t *pgd)
+{
+ gslt_font_t *fontobj = pfont->client_data;
+ byte *s, *e;
+ byte *p;
+
+ // z1_glyph_data
+ // zchar_charstring_data
+ // gs_glyph_data_from_string
+
+ dprintf1("get glyph data for %d\n", glyph);
+
+ p = gslt_find_cff_index(fontobj->charstrings, fontobj->cffend, glyph, &s, &e);
+ if (!p)
+ return gs_rethrow(-1, "cannot find charstring");
+
+ gs_glyph_data_from_string(pgd, s, e - s, NULL);
+
+ return 0;
+}
+
+private int
+gslt_post_callback_subr_data(gs_font_type1 * pfont,
+ int subr_num, bool global, gs_glyph_data_t *pgd)
+{
+ gslt_font_t *fontobj = pfont->client_data;
+ byte *s, *e;
+ byte *p;
+
+ dprintf2("get %s subr data for %d\n", global?"global":"local", subr_num);
+
+ if (global)
+ {
+ p = gslt_find_cff_index(fontobj->gsubrs, fontobj->cffend, subr_num, &s, &e);
+ if (!p)
+ return gs_rethrow(-1, "cannot find gsubr");
+ }
+ else
+ {
+ p = gslt_find_cff_index(fontobj->subrs, fontobj->cffend, subr_num, &s, &e);
+ if (!p)
+ return gs_rethrow(-1, "cannot find subr");
+ }
+
+ gs_glyph_data_from_string(pgd, s, e - s, NULL);
+
+ return 0;
+}
+
+private int
+gslt_post_callback_seac_data(gs_font_type1 * pfont, int ccode, gs_glyph * pglyph,
+ gs_const_string *gstr, gs_glyph_data_t *pgd)
+{
+ return gs_throw(-1, "seac is deprecated in CFF fonts");
+}
+
+private int
+gslt_post_callback_push(void *callback_data, const fixed *values, int count)
+{
+ return gs_throw(-1, "push not implemented");;
+}
+
+private int
+gslt_post_callback_pop(void *callback_data, fixed *value)
+{
+ return gs_throw(-1, "pop not implemented");;
+}
+
+
+private int
+gslt_cff_append(gs_state *pgs, gs_font_type1 *pt1, gs_glyph glyph, int donthint)
+{
+ int code, value;
+ gs_type1exec_state cxs;
+ gs_glyph_data_t gd;
+ gs_type1_state *const pcis = &cxs.cis;
+ gs_imager_state *pgis = (gs_imager_state*)pgs;
+ gs_glyph_data_t *pgd = &gd;
+ double wv[4];
+ double sbw[4];
+ gs_matrix mtx;
+
+ // get charstring data
+ code = gslt_post_callback_glyph_data(pt1, glyph, pgd);
+ if (code < 0)
+ return gs_rethrow(code, "cannot get glyph data");
+
+ gs_make_scaling(0.001, 0.001, &mtx);
+ mtx.tx = 0;
+ mtx.ty = 0;
+ gs_matrix_fixed_from_matrix(&pgis->ctm, &mtx);
+ pgis->flatness = 0;
+
+ code = gs_type1_interp_init(&cxs.cis, pgis, pgs->path, NULL, NULL, donthint, 0, pt1);
+ if (code < 0)
+ return gs_throw(code, "cannot init type1 interpreter");
+
+ gs_type1_set_callback_data(pcis, &cxs);
+
+ // TODO: check if this is set in the font dict
+ // gs_type1_set_lsb(pcis, &mpt);
+ // gs_type1_set_width(pcis, &mpt);
+
+ // ...
+
+ while (1)
+ {
+ code = pt1->data.interpret(pcis, pgd, &value);
+ switch (code)
+ {
+ case type1_result_callothersubr: /* unknown OtherSubr */
+ return_error(-15); /* can't handle it */
+ case type1_result_sbw: /* [h]sbw, just continue */
+ type1_cis_get_metrics(pcis, cxs.sbw);
+ type1_cis_get_metrics(pcis, sbw);
+ pgd = 0;
+ break;
+ case 0: /* all done */
+ default: /* code < 0, error */
+ return code;
+ }
+ }
+}
+
+private int
+gslt_post_callback_build_char(gs_text_enum_t *ptextenum, gs_state *pgs,
+ gs_font *pfont, gs_char chr, gs_glyph glyph)
+{
+ gs_show_enum *penum = (gs_show_enum*)ptextenum;
+ gs_font_type1 *pt1 = (gs_font_type1*)pfont;
+ const gs_rect *pbbox;
+ float sbw[4], w2[6];
+ int code;
+
+ dprintf2("build_char chr=%d glyph=%d\n", chr, glyph);
+
+ // get the metrics
+ w2[0] = 0;
+ w2[1] = 1;
+
+ pbbox = &pt1->FontBBox;
+ w2[2] = pbbox->p.x * 0.001;
+ w2[3] = pbbox->p.y * 0.001;
+ w2[4] = pbbox->q.x * 0.001;
+ w2[5] = pbbox->q.y * 0.001;
+
+ /* Expand the bbox when stroking */
+ if ( pfont->PaintType )
+ {
+ float expand = max(1.415, gs_currentmiterlimit(pgs)) * gs_currentlinewidth(pgs) / 2;
+ w2[2] -= expand, w2[3] -= expand;
+ w2[4] += expand, w2[5] += expand;
+ }
+
+ if ( (code = gs_moveto(pgs, 0.0, 0.0)) < 0 )
+ return code;
+
+ if ( (code = gs_setcachedevice(penum, pgs, w2)) < 0 )
+ return code;
+
+ code = gslt_cff_append(pgs, pt1, glyph,
+ gs_show_in_charpath(penum) != cpm_show);
+ if (code < 0)
+ return code;
+
+ code = (pfont->PaintType ? gs_stroke(pgs) : gs_fill(pgs));
+ if (code < 0)
+ return code;
+
+ return 0;
+}
+
+int
+gslt_init_postscript_font(gs_memory_t *mem,
+ gs_font_dir *fontdir, gslt_font_t *fontobj)
+{
+ gs_font_type1 *pt1;
+ int cffofs;
+ int cfflen;
+ int code;
+
+ /* Find the CFF table and parse it to create a charstring based font */
+ /* We don't need to support CFF files with multiple fonts */
+ /* Find the VORG table for easier vertical metrics */
+
+#if 0
+ gs_glyph_data_t;
+ gs_type1_data_procs_t {
+ z1_glyph_data, z1_subr_data, z1_seac_data, z1_push, z1_pop
+ };
+ gs_type1_data_s { procs; ...;
+ subroutineNumberBias;
+ gsubrNumberBias;
+ defaultWidthX;
+ nominalWidthX;
+ }
+ gs_font_type1 { font_base_common; data }
+#endif
+
+ cffofs = gslt_find_sfnt_table(fontobj, "CFF ", &cfflen);
+ if (cffofs < 0)
+ return gs_throw(-1, "cannot find CFF table");
+
+ if (cfflen < 0 || cffofs + cfflen > fontobj->length)
+ return gs_throw(-1, "corrupt CFF table location");
+
+ fontobj->cffdata = fontobj->data + cffofs;
+ fontobj->cffend = fontobj->data + cffofs + cfflen;
+
+ fontobj->gsubrs = 0;
+ fontobj->subrs = 0;
+ fontobj->charstrings = 0;
+
+ pt1 = (void*) gs_alloc_struct(mem, gs_font_type1, &st_gs_font_type1, "gslt_font type1");
+ if (!pt1)
+ return gs_throw(-1, "out of memory");
+
+ fontobj->font = (void*) pt1;
+
+ /*
+ * No shortage of things to initialize
+ */
+
+ // build_gs_font_procs
+ // build_gs_primitive_font
+ // build_gs_outline_font
+ // build_base_font = build_gs_simple_font
+ // build_gs_font
+ // init_gs_simple_font
+ // charstring_font_init
+ // glyph_outline = zchar1_glyph_outline
+ // e
+ // define_gs_font
+
+ /* Common to all fonts */
+
+ pt1->next = 0;
+ pt1->prev = 0;
+ pt1->memory = mem;
+
+ pt1->dir = fontdir; /* NB also set by gs_definefont later */
+ pt1->base = fontobj->font; /* NB also set by gs_definefont later */
+ pt1->is_resource = false;
+ gs_notify_init(&pt1->notify_list, gs_memory_stable(mem));
+ pt1->id = gs_next_ids(mem, 1);
+
+ pt1->client_data = fontobj; /* that's us */
+
+ gs_make_identity(&pt1->FontMatrix);
+ gs_make_identity(&pt1->orig_FontMatrix);
+
+ pt1->FontType = ft_encrypted2;
+ pt1->BitmapWidths = true;
+ pt1->ExactSize = fbit_use_outlines;
+ pt1->InBetweenSize = fbit_use_outlines;
+ pt1->TransformedChar = fbit_use_outlines;
+ pt1->WMode = 0;
+ pt1->PaintType = 0;
+ pt1->StrokeWidth = 0;
+
+ pt1->procs.define_font = gs_no_define_font;
+ pt1->procs.make_font = gs_no_make_font;
+ pt1->procs.font_info = gs_default_font_info;
+ // same_font
+ pt1->procs.encode_char = gslt_post_callback_encode_char;
+ pt1->procs.decode_glyph = gslt_post_callback_decode_glyph;
+ // enumerate_glyph
+ pt1->procs.glyph_info = gslt_post_callback_glyph_info;;
+ pt1->procs.glyph_outline = gslt_post_callback_glyph_outline;
+ pt1->procs.glyph_name = gslt_post_callback_glyph_name;
+ pt1->procs.init_fstack = gs_default_init_fstack;
+ pt1->procs.next_char_glyph = gs_default_next_char_glyph;
+ pt1->procs.build_char = gslt_post_callback_build_char;
+
+ pt1->font_name.size = 0;
+ pt1->key_name.size = 0;
+
+ /* Base font specific */
+
+ pt1->FontBBox.p.x = 0; // -0.5;
+ pt1->FontBBox.p.y = 0; // -0.5;
+ pt1->FontBBox.q.x = 0; // 1.5;
+ pt1->FontBBox.q.y = 0; // 1.5;
+
+ uid_set_UniqueID(&pt1->UID, pt1->id);
+
+ pt1->encoding_index = ENCODING_INDEX_UNKNOWN;
+ pt1->nearest_encoding_index = ENCODING_INDEX_UNKNOWN;
+
+ pt1->FAPI = 0;
+ pt1->FAPI_font_data = 0;
+
+ /* Type 1/2 specific */
+ /* defaults from the CFF spec */
+
+ pt1->data.procs.glyph_data = gslt_post_callback_glyph_data;
+ pt1->data.procs.subr_data = gslt_post_callback_subr_data;
+ pt1->data.procs.seac_data = gslt_post_callback_seac_data;
+ pt1->data.procs.push_values = gslt_post_callback_push;
+ pt1->data.procs.pop_value = gslt_post_callback_pop;
+
+ pt1->data.interpret = gs_type2_interpret;
+ pt1->data.proc_data = fontobj;
+ pt1->data.parent = NULL;
+ pt1->data.lenIV = -1; // DEFAULT_LENIV_2
+
+ pt1->data.subroutineNumberBias = 0;
+ pt1->data.gsubrNumberBias = 0;
+ pt1->data.initialRandomSeed = 0;
+ pt1->data.defaultWidthX = 0;
+ pt1->data.nominalWidthX = 0;
+
+ pt1->data.BlueFuzz = 1;
+ pt1->data.BlueScale = 0.039625;
+ pt1->data.BlueShift = 7;
+ pt1->data.BlueValues.count = 0;
+ pt1->data.ExpansionFactor = 0.06;
+ pt1->data.ForceBold = 0;
+ pt1->data.FamilyBlues.count = 0;
+ pt1->data.FamilyOtherBlues.count = 0;
+ pt1->data.LanguageGroup = 0;
+ pt1->data.OtherBlues.count = 0;
+
+ pt1->data.RndStemUp = 0;
+ memset(&pt1->data.StdHW, 0, sizeof(pt1->data.StdHW));
+ memset(&pt1->data.StdVW, 0, sizeof(pt1->data.StdVW));
+ memset(&pt1->data.StemSnapH, 0, sizeof(pt1->data.StemSnapH));
+ memset(&pt1->data.StemSnapV, 0, sizeof(pt1->data.StemSnapH));
+ memset(&pt1->data.WeightVector, 0, sizeof(pt1->data.WeightVector));
+
+ code = gslt_read_cff_file(fontobj, pt1);
+ if (code < 0)
+ {
+ // TODO free pt1 here?
+ return gs_rethrow(code, "cannot read cff file structure");
+ }
+
+ gs_definefont(fontdir, fontobj->font);
+
+ return 0;
+}
+
diff --git a/tools/gslite/gslt_font_encoding.c b/tools/gslite/gslt_font_encoding.c
new file mode 100644
index 000000000..fdb541e87
--- /dev/null
+++ b/tools/gslite/gslt_font_encoding.c
@@ -0,0 +1,183 @@
+/* Copyright (C) 2006 artofcode LLC.
+ All Rights Reserved.
+
+ This software is provided AS-IS with no warranty, either express or
+ implied.
+
+ This software is distributed under license and may not be copied, modified
+ or distributed except as expressly authorized under the terms of that
+ license. Refer to licensing information at http://www.artifex.com/
+ or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
+ San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
+*/
+
+#include "gslt_font_int.h"
+
+#include "gslt.h"
+#include "gslt_font.h"
+
+/*
+ * Locate the 'cmap' table and count the number of subtables.
+ */
+
+int
+gslt_load_sfnt_cmap(gslt_font_t *xf)
+{
+ byte *cmapdata;
+ int offset, length;
+ int nsubtables;
+
+ offset = gslt_find_sfnt_table(xf, "cmap", &length);
+ if (offset < 0)
+ return -1;
+
+ if (length < 4)
+ return -1;
+
+ cmapdata = xf->data + offset;
+
+ nsubtables = u16(cmapdata + 2);
+ if (nsubtables < 0)
+ return -1;
+ if (length < 4 + nsubtables * 8)
+ return -1;
+
+ xf->cmaptable = offset;
+ xf->cmapsubcount = nsubtables;
+ xf->cmapsubtable = 0;
+
+ return 0;
+}
+
+/*
+ * Return the number of cmap subtables.
+ */
+
+int
+gslt_count_font_encodings(gslt_font_t *xf)
+{
+ return xf->cmapsubcount;
+}
+
+/*
+ * Extract PlatformID and EncodingID for a cmap subtable.
+ */
+
+int
+gslt_identify_font_encoding(gslt_font_t *xf, int idx, int *pid, int *eid)
+{
+ byte *cmapdata, *entry;
+ if (idx < 0 || idx >= xf->cmapsubcount)
+ return -1;
+ cmapdata = xf->data + xf->cmaptable;
+ entry = cmapdata + 4 + idx * 8;
+ *pid = u16(entry + 0);
+ *eid = u16(entry + 2);
+ return 0;
+}
+
+/*
+ * Select a cmap subtable for use with encoding functions.
+ */
+
+int
+gslt_select_font_encoding(gslt_font_t *xf, int idx)
+{
+ byte *cmapdata, *entry;
+ int pid, eid;
+ if (idx < 0 || idx >= xf->cmapsubcount)
+ return -1;
+ cmapdata = xf->data + xf->cmaptable;
+ entry = cmapdata + 4 + idx * 8;
+ pid = u16(entry + 0);
+ eid = u16(entry + 2);
+ xf->cmapsubtable = xf->cmaptable + u32(entry + 4);
+ xf->usepua = (pid == 3 && eid == 0);
+ return 0;
+}
+
+/*
+ * Encode a character using the selected cmap subtable.
+ * TODO: extend this to cover more cmap formats.
+ */
+
+private int
+gslt_encode_font_char_int(gslt_font_t *xf, int code)
+{
+ byte *table;
+
+ /* no cmap selected: return identity */
+ if (xf->cmapsubtable <= 0)
+ return code;
+
+ table = xf->data + xf->cmapsubtable;
+
+ switch (u16(table))
+ {
+ case 0: /* Apple standard 1-to-1 mapping. */
+ return table[code + 6];
+
+ case 4: /* Microsoft/Adobe segmented mapping. */
+ {
+ int segCount2 = u16(table + 6);
+ byte *endCount = table + 14;
+ byte *startCount = endCount + segCount2 + 2;
+ byte *idDelta = startCount + segCount2;
+ byte *idRangeOffset = idDelta + segCount2;
+ int i2;
+
+ for (i2 = 0; i2 < segCount2 - 3; i2 += 2)
+ {
+ int delta, roff;
+ int start = u16(startCount + i2);
+ int glyph;
+
+ if ( code < start )
+ return 0;
+ if ( code > u16(endCount + i2) )
+ continue;
+ delta = s16(idDelta + i2);
+ roff = s16(idRangeOffset + i2);
+ if ( roff == 0 )
+ {
+ return ( code + delta ) & 0xffff; /* mod 65536 */
+ return 0;
+ }
+ glyph = u16(idRangeOffset + i2 + roff + ((code - start) << 1));
+ return (glyph == 0 ? 0 : glyph + delta);
+ }
+
+ /*
+ * The TrueType documentation says that the last range is
+ * always supposed to end with 0xffff, so this shouldn't
+ * happen; however, in some real fonts, it does.
+ */
+ return 0;
+ }
+
+ case 6: /* Single interval lookup. */
+ {
+ int firstCode = u16(table + 6);
+ int entryCount = u16(table + 8);
+ if ( code < firstCode || code >= firstCode + entryCount )
+ return 0;
+ return u16(table + 10 + ((code - firstCode) << 1));
+ }
+
+ default:
+ errprintf("error: unknown cmap format: %d\n", u16(table));
+ return 0;
+ }
+
+ return 0;
+}
+
+int
+gslt_encode_font_char(gslt_font_t *xf, int code)
+{
+ int gid = gslt_encode_font_char_int(xf, code);
+ if (gid == 0 && xf->usepua)
+ gid = gslt_encode_font_char_int(xf, 0xF000 | code);
+ return gid;
+}
+
diff --git a/tools/gslite/gslt_font_glyph.c b/tools/gslite/gslt_font_glyph.c
new file mode 100644
index 000000000..1ecec2717
--- /dev/null
+++ b/tools/gslite/gslt_font_glyph.c
@@ -0,0 +1,325 @@
+/* Copyright (C) 2006 artofcode LLC.
+ All Rights Reserved.
+
+ This software is provided AS-IS with no warranty, either express or
+ implied.
+
+ This software is distributed under license and may not be copied, modified
+ or distributed except as expressly authorized under the terms of that
+ license. Refer to licensing information at http://www.artifex.com/
+ or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
+ San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
+*/
+
+#include "gslt_font_int.h"
+
+#include "gslt.h"
+#include "gslt_font.h"
+
+void
+gslt_retain_font_glyph(gs_memory_t *mem, gslt_glyph_bitmap_t *slot)
+{
+ gx_retain_cached_char(slot->cc);
+}
+
+void
+gslt_release_font_glyph(gs_memory_t *mem, gslt_glyph_bitmap_t *slot)
+{
+ gx_release_cached_char(slot->cc);
+}
+
+/*
+ * Draw a glyph to the device, and extract the bitmap from
+ * the ccache afterwards... only works if the bitmap is not
+ * too large.
+ */
+
+int
+gslt_render_font_glyph(gs_state *pgs, gslt_font_t *xf, gs_matrix *tm, int gid, gslt_glyph_bitmap_t *slot)
+{
+ gs_fixed_point subpixel = {0, 0}; /* we don't use subpixel accurate device metrics */
+ gs_log2_scale_point oversampling = {0, 0}; /* we don't use oversampling */
+ gs_text_params_t params;
+ gs_text_enum_t *textenum;
+ gs_matrix matrix;
+ cached_fm_pair *ppair;
+ cached_char *cc;
+ int code;
+
+ /* get the real font matrix (this is a little dance) */
+ gs_setfont(pgs, xf->font); /* set pgs->font and invalidate existing charmatrix */
+ gs_setcharmatrix(pgs, tm); /* set the charmatrix to ctm * tm */
+ gs_currentcharmatrix(pgs, &matrix, true); /* extract charmatrix (and multiply by FontMatrix) */
+
+ // dprintf4("tm = [%g %g %g %g]\n", matrix.xx, matrix.xy, matrix.yx, matrix.yy);
+
+ /* find the font/matrix pair (or add it) */
+ code = gx_lookup_fm_pair(xf->font, &matrix, &oversampling, false, &ppair);
+ if (code != 0)
+ return gs_throw(-1, "cannot gx_lookup_fm_pair()");
+
+ cc = gx_lookup_cached_char(xf->font, ppair, gid, 0, 1, &subpixel);
+ if (!cc)
+ {
+ /* No luck ... now we need to get it into the cache somehow.
+ *
+ * We do this by rendering one glyph (that's why we need a device and pgs).
+ * The renderer always renders the bitmap into the cache, and draws
+ * from out of the cache when blitting to the device.
+ *
+ * Things don't get evicted from the cache until there is a collision,
+ * so we have a safe window to snarf it back out of the cache
+ * after it's been drawn to the device.
+ */
+
+ // dprintf1("cache miss for glyph %d\n", gid);
+
+ params.operation = TEXT_FROM_SINGLE_GLYPH | TEXT_DO_DRAW | TEXT_RETURN_WIDTH;
+ params.data.d_glyph = gid;
+ params.size = 1;
+
+ gs_moveto(pgs, 100.0, 100.0); // why?
+
+ code = gs_text_begin(pgs, &params, xf->font->memory, &textenum);
+ if (code != 0)
+ return gs_throw1(-1, "cannot gs_text_begin() (%d)", code);
+
+ code = gs_text_process(textenum);
+ if (code != 0)
+ return gs_throw1(-1, "cannot gs_text_process() (%d)", code);
+
+ gs_text_release(textenum, "gslt font render");
+
+ cc = gx_lookup_cached_char(xf->font, ppair, gid, 0, 1, &subpixel);
+ if (!cc)
+ {
+ /* merde! it rendered but was not placed in the cache. */
+ return gs_throw(-2, "cannot render from cache");
+ }
+ }
+
+ /* copy values from the cache into the client struct */
+ slot->w = cc->width;
+ slot->h = cc->height;
+ slot->stride = cc_raster(cc);
+ slot->lsb = fixed2int(cc->offset.x);
+ slot->top = fixed2int(cc->offset.y);
+
+ slot->cc = cc;
+ slot->data = cc_bits(cc);
+ gx_retain_cached_char(cc);
+
+#define XXX
+#ifndef XXX
+ static int xxx = 0; /* declaration out in the wild not allowed in ansi c */
+ dprintf1("glyph %d\n", xxx);
+ debug_dump_bitmap(cc_bits(cc), cc_raster(cc), cc->height, "");
+ {
+ char fn[32];
+ sprintf(fn, "glyph%d.pbm", xxx);
+ FILE *fo = fopen(fn, "wb");
+ if (!fo)
+ return -1;
+ fprintf(fo, "P4\n%d %d\n", cc->width, cc->height);
+ int y;
+ int s = (cc->width + 7) / 8;
+ for (y = 0; y < cc->height; y++)
+ fwrite(cc_bits(cc) + y * cc_raster(cc), 1, s, fo);
+ fclose(fo);
+ }
+ xxx ++;
+#endif
+
+ return 0;
+}
+
+int
+gslt_outline_font_glyph(gs_state *pgs, gslt_font_t *xf, int gid, gslt_outline_walker_t *walk)
+{
+ gs_text_params_t params;
+ gs_text_enum_t *textenum;
+ gs_matrix matrix;
+ segment *seg;
+ curve_segment *cseg;
+
+ gs_gsave(pgs);
+ gs_make_identity(&matrix);
+ gs_setmatrix(pgs, &matrix);
+ gs_scale(pgs, 1000.0, 1000.0); /* otherwise we hit serious precision problems with fixpoint math */
+
+ /* set gstate params */
+ gs_setfont(pgs, xf->font); /* set pgs->font and invalidate existing charmatrix */
+ gs_make_identity(&matrix);
+ gs_setcharmatrix(pgs, &matrix); /* set the charmatrix to identity */
+
+ /* reset the path */
+ gs_newpath(pgs);
+ gs_moveto(pgs, 0.0, 0.0);
+
+ /* draw the glyph, in charpath mode */
+ params.operation = TEXT_FROM_SINGLE_GLYPH | TEXT_DO_FALSE_CHARPATH | TEXT_RETURN_WIDTH;
+ params.data.d_glyph = gid;
+ params.size = 1;
+
+ if (gs_text_begin(pgs, &params, xf->font->memory, &textenum) != 0)
+ return gs_throw(-1, "cannot gs_text_begin()");
+ if (gs_text_process(textenum) != 0)
+ return gs_throw(-1, "cannot gs_text_process()");
+ gs_text_release(textenum, "gslt font outline");
+
+ /* walk the resulting path */
+ seg = (segment*)pgs->path->first_subpath;
+ while (seg)
+ {
+ switch (seg->type)
+ {
+ case s_start:
+ walk->moveto(walk->user,
+ fixed2float(seg->pt.x) * 0.001,
+ fixed2float(seg->pt.y) * 0.001);
+ break;
+ case s_line:
+ walk->lineto(walk->user,
+ fixed2float(seg->pt.x) * 0.001,
+ fixed2float(seg->pt.y) * 0.001);
+ break;
+ case s_line_close:
+ walk->closepath(walk->user);
+ break;
+ case s_curve:
+ cseg = (curve_segment*)seg;
+ walk->curveto(walk->user,
+ fixed2float(cseg->p1.x) * 0.001,
+ fixed2float(cseg->p1.y) * 0.001,
+ fixed2float(cseg->p2.x) * 0.001,
+ fixed2float(cseg->p2.y) * 0.001,
+ fixed2float(seg->pt.x) * 0.001,
+ fixed2float(seg->pt.y) * 0.001);
+ break;
+ }
+ seg = seg->next;
+ }
+
+ /* and toss it away... */
+ gs_newpath(pgs);
+
+ gs_grestore(pgs);
+ return 0;
+}
+
+int
+gslt_measure_font_glyph(gs_state *pgs, gslt_font_t *xf, int gid, gslt_glyph_metrics_t *mtx)
+{
+ int head, format, loca, glyf;
+ int ofs, len;
+ int idx, i, n;
+ int hadv, vadv, vorg;
+ int vtop, ymax;
+ int scale;
+
+ /* some insane defaults */
+
+ scale = 2048; /* units-per-em */
+ mtx->hadv = 0.5;
+ mtx->vadv = -1.0;
+ mtx->vorg = 1.0;
+
+ /*
+ * Horizontal metrics are easy.
+ */
+
+ ofs = gslt_find_sfnt_table(xf, "hhea", &len);
+ if (ofs < 0)
+ return gs_throw(-1, "cannot find hhea table");
+
+ if (len < 2 * 18)
+ return gs_throw(-1, "hhea table is too short");
+
+ vorg = u16(xf->data + ofs + 4); /* ascender is default vorg */
+ n = u16(xf->data + ofs + 17 * 2);
+
+ ofs = gslt_find_sfnt_table(xf, "hmtx", &len);
+ if (ofs < 0)
+ return gs_throw(-1, "cannot find hmtx table");
+
+ idx = gid;
+ if (idx > n - 1)
+ idx = n - 1;
+
+ hadv = u16(xf->data + ofs + idx * 4);
+ vadv = hadv;
+
+ /*
+ * Vertical metrics are hairy (with missing tables).
+ */
+
+ ofs = gslt_find_sfnt_table(xf, "OS/2", &len);
+ if (ofs > 0 && len > 70)
+ {
+ vorg = u16(xf->data + ofs + 68); /* sTypoAscender */
+ }
+
+ ofs = gslt_find_sfnt_table(xf, "vhea", &len);
+ if (ofs > 0)
+ {
+ if (len < 2 * 18)
+ return gs_throw(-1, "vhea table is too short");
+
+ n = u16(xf->data + ofs + 17 * 2);
+
+ ofs = gslt_find_sfnt_table(xf, "vmtx", &len);
+ if (ofs < 0)
+ return gs_throw(-1, "cannot find vmtx table");
+
+ idx = gid;
+ if (idx > n - 1)
+ idx = n - 1;
+
+ vadv = u16(xf->data + ofs + idx * 4);
+ vtop = u16(xf->data + ofs + idx * 4 + 2);
+
+ head = gslt_find_sfnt_table(xf, "head", &len);
+ if (head > 0)
+ {
+ scale = u16(xf->data + head + 18); /* units per em */
+ }
+
+ glyf = gslt_find_sfnt_table(xf, "glyf", &len);
+ loca = gslt_find_sfnt_table(xf, "loca", &len);
+ if (head > 0 && glyf > 0 && loca > 0)
+ {
+ format = u16(xf->data + head + 50); /* indexToLocaFormat */
+
+ if (format == 0)
+ ofs = u16(xf->data + loca + gid * 2);
+ else
+ ofs = u32(xf->data + loca + gid * 4);
+
+ ymax = u16(xf->data + glyf + ofs + 8); /* yMax */
+
+ vorg = ymax + vtop;
+ }
+ }
+
+ ofs = gslt_find_sfnt_table(xf, "VORG", &len);
+ if (ofs > 0)
+ {
+ vorg = u16(xf->data + ofs + 6);
+ n = u16(xf->data + ofs + 6);
+ for (i = 0; i < n; i++)
+ {
+ if (u16(xf->data + ofs + 8 + 4 * i) == gid)
+ {
+ vorg = s16(xf->data + ofs + 8 + 4 * i + 2);
+ break;
+ }
+ }
+ }
+
+ mtx->hadv = hadv / (float) scale;
+ mtx->vadv = vadv / (float) scale;
+ mtx->vorg = vorg / (float) scale;
+
+ return 0;
+}
+
diff --git a/tools/gslite/gslt_font_int.h b/tools/gslite/gslt_font_int.h
new file mode 100644
index 000000000..439fbe3c0
--- /dev/null
+++ b/tools/gslite/gslt_font_int.h
@@ -0,0 +1,107 @@
+/* Copyright (C) 2006 artofcode LLC.
+ All Rights Reserved.
+
+ This software is provided AS-IS with no warranty, either express or
+ implied.
+
+ This software is distributed under license and may not be copied, modified
+ or distributed except as expressly authorized under the terms of that
+ license. Refer to licensing information at http://www.artifex.com/
+ or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
+ San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
+*/
+
+/* No shortage of gslib headers to include... */
+
+#ifndef GSLITE
+#define GSLITE
+#endif
+
+#include <stdlib.h>
+#include "stdio_.h"
+#include "math_.h"
+#include "string_.h"
+
+#include "gp.h"
+
+#include "gscdefs.h"
+#include "gserror.h"
+#include "gserrors.h"
+#include "gslib.h"
+#include "gsmatrix.h"
+#include "gsstate.h"
+#include "gscoord.h"
+#include "gspaint.h"
+#include "gspath.h"
+#include "gspath2.h"
+#include "gsutil.h"
+#include "gsgdata.h"
+
+#include "gx.h"
+#include "gxdevice.h"
+#include "gxmatrix.h"
+#include "gxpath.h"
+
+#include "gxfont.h"
+#include "gxchar.h"
+#include "gxtype1.h"
+#include "gxfont1.h"
+#include "gxfont42.h"
+#include "gxfcache.h"
+
+#include "gzstate.h"
+#include "gzpath.h"
+
+/*
+ * Font API internals.
+ */
+
+struct gslt_font_s
+{
+ byte *data;
+ int length;
+ gs_font *font;
+
+ int subfontid;
+ int cmaptable;
+ int cmapsubcount;
+ int cmapsubtable;
+ int usepua;
+
+ /* these are for CFF opentypes only */
+ byte *cffdata;
+ byte *cffend;
+ byte *gsubrs;
+ byte *subrs;
+ byte *charstrings;
+};
+
+int gslt_find_sfnt_table(struct gslt_font_s *xf, char *name, int *lengthp);
+int gslt_load_sfnt_cmap(struct gslt_font_s *xf);
+int gslt_init_truetype_font(gs_memory_t *mem, gs_font_dir *xfc, struct gslt_font_s *xf);
+int gslt_init_postscript_font(gs_memory_t *mem, gs_font_dir *xfc, struct gslt_font_s *xf);
+
+/*
+ * Big-endian memory accessor functions
+ */
+
+private inline int s16(byte *p)
+{
+ return (signed short)( (p[0] << 8) | p[1] );
+}
+
+private inline int u16(byte *p)
+{
+ return (p[0] << 8) | p[1];
+}
+
+private inline int u24(byte *p)
+{
+ return (p[0] << 16) | (p[1] << 8) | p[2];
+}
+
+private inline int u32(byte *p)
+{
+ return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
+}
+
diff --git a/tools/gslite/gslt_font_test.c b/tools/gslite/gslt_font_test.c
new file mode 100644
index 000000000..eb7c8d6ef
--- /dev/null
+++ b/tools/gslite/gslt_font_test.c
@@ -0,0 +1,296 @@
+/* Copyright (C) 2006 artofcode LLC.
+ All Rights Reserved.
+
+ This software is provided AS-IS with no warranty, either express or
+ implied.
+
+ This software is distributed under license and may not be copied, modified
+ or distributed except as expressly authorized under the terms of that
+ license. Refer to licensing information at http://www.artifex.com/
+ or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
+ San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
+*/
+
+/* $Id: gslt_font_api_test.c 2490 2006-08-08 22:33:47Z giles $ */
+/* gslt OpenType font library example client */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <gserror.h>
+
+#include "gslt.h"
+#include "gslt_font.h"
+
+/* these are not strictly needed */
+extern void gs_erasepage(gs_state *pgs);
+extern void gs_moveto(gs_state *pgs, double, double);
+extern void gs_output_page(gs_state *pgs, int, int);
+extern char gs_debug[];
+
+/*
+ * Read a file from disk into memory.
+ */
+
+int readfile(char *filename, char **datap, int *lengthp)
+{
+ FILE *fp;
+ int t, n;
+ char *p;
+
+ fp = fopen(filename, "rb");
+ if (!fp)
+ return gs_throw(-1, "cannot open font file");
+
+ t = fseek(fp, 0, 2);
+ if (t < 0)
+ {
+ fclose(fp);
+ return gs_throw(-1, "cannot seek in font file");
+ }
+
+ n = ftell(fp);
+ if (n < 0)
+ {
+ fclose(fp);
+ return gs_throw(-1, "cannot tell in font file");
+ }
+
+ t = fseek(fp, 0, 0);
+ if (t < 0)
+ {
+ fclose(fp);
+ return gs_throw(-1, "cannot seek in font file");
+ }
+
+ p = malloc(n);
+ if (!p)
+ {
+ fclose(fp);
+ return gs_throw(-1, "out of memory");
+ }
+
+ t = fread(p, 1, n, fp);
+ if (t != n)
+ {
+ free(p);
+ fclose(fp);
+ return gs_throw(-1, "cannot read font file data");
+ }
+
+ t = fclose(fp);
+ if (t < 0)
+ {
+ gs_throw(-1, "cannot close font file");
+ /* ... continue anyway */
+ }
+
+ *lengthp = n;
+ *datap = p;
+
+ return 0;
+}
+
+/*
+ * Test program.
+ */
+
+static int mymoveto(void *ctx, float x, float y)
+{
+ x *= 1000; y *= 1000;
+ printf("%g %g moveto\n", x, y);
+ return 0;
+}
+
+static int mylineto(void *ctx, float x, float y)
+{
+ x *= 1000; y *= 1000;
+ printf("%g %g lineto\n", x, y);
+ return 0;
+}
+
+static int mycurveto(void *ctx, float x0, float y0, float x1, float y1, float x2, float y2)
+{
+ x0 *= 1000; y0 *= 1000;
+ x1 *= 1000; y1 *= 1000;
+ x2 *= 1000; y2 *= 1000;
+ printf("%g %g %g %g %g %g curveto\n", x0, y0, x1, y1, x2, y2);
+ return 0;
+}
+
+static int myclosepath(void *ctx)
+{
+ printf("closepath\n");
+ return 0;
+}
+
+int
+main(int argc, const char *argv[])
+{
+ gs_memory_t *mem;
+ gx_device *dev;
+ gs_state *pgs;
+ gs_font_dir *cache;
+ gslt_font_t *font;
+ gslt_outline_walker_t walk;
+ gslt_glyph_bitmap_t slot;
+ gslt_glyph_metrics_t mtx;
+ gs_matrix ctm;
+ int code;
+ char *s;
+ char *devicename;
+ char *filename;
+ int i, n, pid, eid, best;
+ char *buf;
+ int len;
+
+ char *text;
+
+ devicename = getenv("DEVICE");
+ if (!devicename)
+ devicename = "nullpage";
+
+ mem = gslt_init_library();
+ dev = gslt_init_device(mem, devicename);
+ pgs = gslt_init_state(mem, dev);
+
+ if (argc < 2)
+ {
+ filename = "/Users/tor/src/work/gslite/TrajanPro-Regular.otf";
+ // filename = "/Users/tor/src/work/gslite/GenR102.TTF";
+ // return gs_throw(1, "usage: gslt_font_api_test font.otf");
+ }
+ else
+ {
+ filename = argv[argc-1];
+ }
+
+ n = readfile(filename, &buf, &len);
+ if (n < 0)
+ return gs_rethrow1(1, "cannot read font file '%s'", filename);
+
+ gs_debug['k'] = 1; /* debug character cache machinery */
+
+ /*
+ * Set up ghostscript library
+ */
+
+ // gslt_get_device_param(mem, dev, "Name");
+ gslt_set_device_param(mem, dev, "OutputFile", "-");
+
+ // so we see what device calls are made
+ gs_erasepage(pgs);
+ gs_moveto(pgs, 5.0, 20.0);
+
+ /*
+ * Create a font cache
+ */
+
+ cache = gslt_new_font_cache(mem);
+ if (!cache)
+ return gs_rethrow(1, "cannot create font cache");
+
+ /*
+ * Create the font and select an encoding
+ */
+
+ font = gslt_new_font(mem, cache, buf, len, 0);
+ if (!font)
+ return gs_rethrow(1, "cannot create font");
+
+ n = gslt_count_font_encodings(font);
+ for (best = 0, i = 0; i < n; i++)
+ {
+ gslt_identify_font_encoding(font, i, &pid, &eid);
+ printf("encoding %d/%d = ( %d %d )\n", i + 1, n, pid, eid);
+ if (pid == 3 && eid == 0)
+ best = i;
+ }
+ gslt_select_font_encoding(font, best);
+
+ /*
+ * Test outline extraction.
+ */
+
+ printf("walking the outline\n");
+
+ walk.user = NULL;
+ walk.moveto = mymoveto;
+ walk.lineto = mylineto;
+ walk.curveto = mycurveto;
+ walk.closepath = myclosepath;
+
+ code = gslt_outline_font_glyph(pgs, font, gslt_encode_font_char(font, 'I'), &walk);
+ if (code < 0)
+ printf("error in gslt_outline_font_glyph\n");
+
+ /*
+ * Test bitmap rendering.
+ */
+
+ printf("getting bitmaps\n");
+
+ text = "Pack my box with five dozen liquor jugs!";
+
+text = "ii";
+
+ ctm.xx = 100.0;
+ ctm.xy = 0.0;
+ ctm.yx = 0.0;
+ ctm.yy = 100.0;
+ ctm.tx = ctm.ty = 0.0;
+
+ for (s = text; *s; s++)
+ {
+ int gid = gslt_encode_font_char(font, *s);
+
+ printf("char '%c' -> glyph %d\n", *s, gid);
+
+ code = gslt_measure_font_glyph(pgs, font, gid, &mtx);
+ if (code < 0)
+ {
+ printf("error in gslt_measure_font_glyph\n");
+ }
+
+ printf("glyph %3d: hadv=%f vadv=%f vorg=%f ", gid, mtx.hadv, mtx.vadv, mtx.vorg);
+
+ code = gslt_render_font_glyph(pgs, font, &ctm, gid, &slot);
+ if (code < 0)
+ {
+ printf("error in gslt_render_font_glyph\n");
+ return 1;
+ }
+
+ printf(" -> %dx%d+(%d,%d)\n",
+ slot.w, slot.h,
+ slot.lsb, slot.top);
+
+ ctm.xx = 0.0;
+ ctm.xy = 100.0;
+ ctm.yx = -100.0;
+ ctm.yy = 0.0;
+ ctm.tx = ctm.ty = 0.0;
+
+ gslt_release_font_glyph(mem, &slot);
+ }
+
+ /*
+ * Clean up.
+ */
+
+ // show device.
+ gs_output_page(pgs, 1, 1);
+
+ gslt_free_font(mem, font);
+ gslt_free_font_cache(mem, cache);
+ free(buf);
+
+ gslt_free_state(mem, pgs);
+ gslt_free_device(mem, dev);
+ gslt_free_library(mem);
+
+ gslt_alloc_print_leaks();
+
+ return 0;
+}
+
diff --git a/tools/gslite/gslt_font_ttf.c b/tools/gslite/gslt_font_ttf.c
new file mode 100644
index 000000000..90d871e8e
--- /dev/null
+++ b/tools/gslite/gslt_font_ttf.c
@@ -0,0 +1,196 @@
+/* Copyright (C) 2006 artofcode LLC.
+ All Rights Reserved.
+
+ This software is provided AS-IS with no warranty, either express or
+ implied.
+
+ This software is distributed under license and may not be copied, modified
+ or distributed except as expressly authorized under the terms of that
+ license. Refer to licensing information at http://www.artifex.com/
+ or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
+ San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
+*/
+
+#include "gslt_font_int.h"
+
+#include "gslt.h"
+#include "gslt_font.h"
+
+/*
+ * A bunch of callback functions that the ghostscript
+ * font machinery will call. The most important one
+ * is the build_char function. These are specific to
+ * truetype (loca/glyf) flavored opentypes.
+ */
+
+private gs_glyph
+gslt_true_callback_encode_char(gs_font *pfont, gs_char chr, gs_glyph_space_t spc)
+{
+ gslt_font_t *xf = pfont->client_data;
+ int value;
+ value = gslt_encode_font_char(xf, chr);
+ if (value == 0)
+ return gs_no_glyph;
+ return value;
+}
+
+private gs_char
+gslt_true_callback_decode_glyph(gs_font *p42, gs_glyph glyph)
+{
+ return GS_NO_CHAR;
+}
+
+private int
+gslt_true_callback_glyph_name(gs_font *pf, gs_glyph glyph, gs_const_string *pstr)
+{
+ return 0;
+}
+
+private int
+gslt_true_callback_string_proc(gs_font_type42 *p42, ulong offset, uint length, const byte **pdata)
+{
+ /* NB bounds check offset + length - use gs_object_size for memory
+ buffers - if file read should fail */
+ gslt_font_t *xf = p42->client_data;
+// ulong adjusted_offset = offset + ttc_offset;
+ *pdata = xf->data + offset;
+ return 0;
+}
+
+private int
+gslt_true_callback_build_char(gs_text_enum_t *ptextenum, gs_state *pgs, gs_font *pfont,
+ gs_char chr, gs_glyph glyph)
+{
+ gs_show_enum *penum = (gs_show_enum*)ptextenum;
+ gs_font_type42 *p42 = (gs_font_type42*)pfont;
+ const gs_rect *pbbox;
+ float sbw[4], w2[6];
+ int code;
+
+ code = gs_type42_get_metrics(p42, glyph, sbw);
+ if (code < 0)
+ return code;
+
+ w2[0] = sbw[2];
+ w2[1] = sbw[3];
+
+ pbbox = &p42->FontBBox;
+ w2[2] = pbbox->p.x;
+ w2[3] = pbbox->p.y;
+ w2[4] = pbbox->q.x;
+ w2[5] = pbbox->q.y;
+
+ dprintf6(" bbox (%g %g) %g %g %g %g\n", w2[0], w2[1], w2[2], w2[3], w2[4], w2[5]);
+
+ /* Expand the bbox when stroking */
+ if ( pfont->PaintType )
+ {
+ float expand = max(1.415, gs_currentmiterlimit(pgs)) * gs_currentlinewidth(pgs) / 2;
+ w2[2] -= expand, w2[3] -= expand;
+ w2[4] += expand, w2[5] += expand;
+ }
+
+ if ( (code = gs_moveto(pgs, 0.0, 0.0)) < 0 )
+ return code;
+
+ if ( (code = gs_setcachedevice(penum, pgs, w2)) < 0 )
+ return code;
+
+ code = gs_type42_append(glyph, pgs,
+ gx_current_path(pgs),
+ ptextenum, (gs_font*)p42,
+ gs_show_in_charpath(penum) != cpm_show);
+ if (code < 0)
+ return code;
+
+ code = (pfont->PaintType ? gs_stroke(pgs) : gs_fill(pgs));
+ if (code < 0)
+ return code;
+
+ return 0;
+}
+
+/*
+ * Initialize the ghostscript font machinery for a truetype
+ * (type42 in postscript terminology) font.
+ */
+
+int
+gslt_init_truetype_font(gs_memory_t *mem, gs_font_dir *fontdir, gslt_font_t *xf)
+{
+ xf->font = (void*) gs_alloc_struct(mem, gs_font_type42, &st_gs_font_type42, "gslt_font type42");
+ if (!xf->font)
+ return gs_throw(-1, "out of memory");
+
+ /* no shortage of things to initialize */
+ {
+ gs_font_type42 *p42 = (gs_font_type42*) xf->font;
+
+ /* Common to all fonts: */
+
+ p42->next = 0;
+ p42->prev = 0;
+ p42->memory = mem;
+
+ p42->dir = fontdir; /* NB also set by gs_definefont later */
+ p42->base = xf->font; /* NB also set by gs_definefont later */
+ p42->is_resource = false;
+ gs_notify_init(&p42->notify_list, gs_memory_stable(mem));
+ p42->id = gs_next_ids(mem, 1);
+
+ p42->client_data = xf; /* that's us */
+
+ gs_make_identity(&p42->FontMatrix);
+ gs_make_identity(&p42->orig_FontMatrix); /* NB ... original or zeroes? */
+
+ p42->FontType = ft_TrueType;
+ p42->BitmapWidths = true;
+ p42->ExactSize = fbit_use_outlines;
+ p42->InBetweenSize = fbit_use_outlines;
+ p42->TransformedChar = fbit_use_outlines;
+ p42->WMode = 0;
+ p42->PaintType = 0;
+ p42->StrokeWidth = 0;
+
+ p42->procs.init_fstack = gs_default_init_fstack;
+ p42->procs.next_char_glyph = gs_default_next_char_glyph;
+ p42->procs.glyph_name = gslt_true_callback_glyph_name;
+ p42->procs.decode_glyph = gslt_true_callback_decode_glyph;
+ p42->procs.define_font = gs_no_define_font;
+ p42->procs.make_font = gs_no_make_font;
+ p42->procs.font_info = gs_default_font_info;
+ p42->procs.glyph_info = gs_default_glyph_info;
+ p42->procs.glyph_outline = gs_no_glyph_outline;
+ p42->procs.encode_char = gslt_true_callback_encode_char;
+ p42->procs.build_char = gslt_true_callback_build_char;
+
+ p42->font_name.size = 0;
+ p42->key_name.size = 0;
+
+ /* Base font specific: */
+
+ p42->FontBBox.p.x = 0;
+ p42->FontBBox.p.y = 0;
+ p42->FontBBox.q.x = 0;
+ p42->FontBBox.q.y = 0;
+
+ uid_set_UniqueID(&p42->UID, p42->id);
+
+ p42->encoding_index = ENCODING_INDEX_UNKNOWN;
+ p42->nearest_encoding_index = ENCODING_INDEX_UNKNOWN;
+
+ p42->FAPI = 0;
+ p42->FAPI_font_data = 0;
+
+ /* Type 42 specific: */
+
+ p42->data.string_proc = gslt_true_callback_string_proc;
+ p42->data.proc_data = xf;
+ gs_type42_font_init(p42, xf->subfontid);
+ }
+
+ gs_definefont(fontdir, xf->font);
+
+ return 0;
+}
+
diff --git a/tools/gslite/gslt_image.c b/tools/gslite/gslt_image.c
index a1c0bc32d..210d8b96a 100644
--- a/tools/gslite/gslt_image.c
+++ b/tools/gslite/gslt_image.c
@@ -11,7 +11,7 @@
San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
*/
-/* $Id: gslt_image.c 2460 2006-07-14 18:49:12Z giles $ */
+/* $Id$ */
/* gslt image loading implementation */
#include "memory_.h"
diff --git a/tools/gslite/gslt_image.h b/tools/gslite/gslt_image.h
index e974860f5..85069c009 100644
--- a/tools/gslite/gslt_image.h
+++ b/tools/gslite/gslt_image.h
@@ -11,7 +11,7 @@
San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
*/
-/* $Id: gslt_image.h 2460 2006-07-14 18:49:12Z giles $*/
+/* $Id$*/
/* gslt image loading interface */
#ifndef gslt_image_INCLUDED
diff --git a/tools/gslite/gslt_image_jpeg.c b/tools/gslite/gslt_image_jpeg.c
index 0cc7a9ea7..65eb77cf5 100644
--- a/tools/gslite/gslt_image_jpeg.c
+++ b/tools/gslite/gslt_image_jpeg.c
@@ -11,7 +11,7 @@
San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
*/
-/* $Id: gslt_image_jpeg.c 2460 2006-07-14 18:49:12Z giles $ */
+/* $Id$ */
/* gslt image loading implementation for JPEG images */
#include "std.h"
diff --git a/tools/gslite/gslt_image_png.c b/tools/gslite/gslt_image_png.c
index 68a87becd..28e5cc78e 100644
--- a/tools/gslite/gslt_image_png.c
+++ b/tools/gslite/gslt_image_png.c
@@ -11,7 +11,7 @@
San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
*/
-/* $Id: gslt_image_png.c 2460 2006-07-14 18:49:12Z giles $ */
+/* $Id$ */
/* gslt image loading implementation for PNG images */
#include "std.h"
diff --git a/tools/gslite/gslt_image_test.c b/tools/gslite/gslt_image_test.c
index e045650fc..8de66db5f 100644
--- a/tools/gslite/gslt_image_test.c
+++ b/tools/gslite/gslt_image_test.c
@@ -11,7 +11,7 @@
San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
*/
-/* $Id: gslt_image_test.c 2461 2006-07-14 18:54:03Z giles $ */
+/* $Id$ */
/* example client for the gslt image loading library */
#include <stdlib.h>
@@ -184,8 +184,9 @@ main(int argc, const char *argv[])
gs_output_page(gs, 1, 1);
/* clean up the library */
- gslt_free_library(mem, dev, gs);
-
+ gslt_free_state(mem, gs);
+ gslt_free_device(mem, dev);
+ gslt_free_library(mem);
return code;
}
diff --git a/tools/gslite/gslt_image_threads_test.c b/tools/gslite/gslt_image_threads_test.c
new file mode 100755
index 000000000..0dd9f6bd8
--- /dev/null
+++ b/tools/gslite/gslt_image_threads_test.c
@@ -0,0 +1,219 @@
+/* Copyright (C) 2006 artofcode LLC.
+ All Rights Reserved.
+
+ This software is provided AS-IS with no warranty, either express or
+ implied.
+
+ This software is distributed under license and may not be copied, modified
+ or distributed except as expressly authorized under the terms of that
+ license. Refer to licensing information at http://www.artifex.com/
+ or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
+ San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
+*/
+
+/* $Id: gslt_image_test.c 2666 2006-10-27 10:25:54Z tor $ */
+/* example client for the gslt image loading library */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <pthread.h>
+
+typedef unsigned char byte;
+#include "gslt.h"
+#include "gslt_image.h"
+
+extern void gs_erasepage(gs_state *gs);
+extern void gs_moveto(gs_state *gs, double, double);
+extern void gs_output_page(gs_state *gs, int, int);
+
+gslt_image_t *
+decode_image_file(gs_memory_t *mem, FILE *in)
+{
+ gslt_image_t *image;
+ int len, bytes;
+ byte *buf;
+
+ /* get compressed data size */
+ fseek(in, 0, SEEK_END);
+ len = ftell(in);
+
+ /* load the file into memory */
+ fseek(in, 0, SEEK_SET);
+ buf = malloc(len);
+ if (buf == NULL) return NULL;
+
+ bytes = fread(buf, 1, len, in);
+ if (bytes != len) {
+ free(buf);
+ return NULL;
+ }
+
+ image = gslt_image_decode(mem, buf, len);
+ free(buf);
+
+ return image;
+}
+
+gslt_image_t *
+decode_image_filename(gs_memory_t *mem, const char *filename)
+{
+ gslt_image_t *image;
+ FILE *in;
+
+ in = fopen(filename, "rb");
+ if (in == NULL) return NULL;
+
+ image = decode_image_file(mem, in);
+ fclose(in);
+
+ return image;
+}
+
+/* write out the image as a pnm file for verification */
+int
+write_image_file(gslt_image_t *image, FILE *out)
+{
+ byte *row;
+ int j, bytes;
+
+ if (image == NULL || image->samples == NULL) {
+ fprintf(stderr, "ignoring empty image object\n");
+ return -1;
+ }
+
+ if (image->components == 1 && image->bits == 1) {
+ /* PBM file */
+ int i;
+ int rowbytes = (image->width+7)>>3;
+ byte *local = malloc(rowbytes);
+
+ fprintf(out, "P4\n%d %d\n", image->width, image->height);
+ row = image->samples;
+ for (j = 0; j < image->height; j++) {
+ /* PBM images are inverted relative to our XPS/PS convention */
+ for (i = 0; i < rowbytes; i++)
+ local[i] = row[i] ^ 0xFF;
+ bytes = fwrite(local, 1, rowbytes, out);
+ row += image->stride;
+ }
+ free(local);
+ } else if (image->components == 1 && image->bits == 8) {
+ /* PGM file */
+ fprintf(out, "P5\n%d %d\n255\n", image->width, image->height);
+ row = image->samples;
+ for (j = 0; j < image->height; j++) {
+ bytes = fwrite(row, 1, image->width, out);
+ row += image->stride;
+ }
+ } else {
+ /* PPM file */
+ fprintf(out, "P6\n%d %d\n255\n", image->width, image->height);
+ row = image->samples;
+ for (j = 0; j < image->height; j++) {
+ bytes = fwrite(row, image->components, image->width, out);
+ row += image->stride;
+ }
+ }
+
+ return 0;
+}
+
+int
+write_image_filename(gslt_image_t *image, const char *filename)
+{
+ FILE *out;
+ int error;
+
+ out = fopen(filename, "wb");
+ if (out == NULL) {
+ fprintf(stderr, "could not open '%s' for writing\n", filename);
+ return -1;
+ }
+
+ error = write_image_file(image, out);
+ fclose(out);
+
+ return error;
+}
+
+/* global input filename. */
+char *filename;
+
+void *
+print_image(void *threadid)
+{
+ gs_memory_t *mem;
+ gx_device *dev;
+ gs_state *gs;
+ gslt_image_t *image;
+ char *s;
+ int code = 0;
+
+ /* get the device from the environment, or default */
+ s = getenv("DEVICE");
+ if (!s)
+ s = "nullpage";
+
+ /* initialize the graphicis library and set up a drawing state */
+ mem = gslt_init_library();
+ dev = gslt_init_device(mem, s);
+ gs = gslt_init_state(mem, dev);
+
+ gslt_get_device_param(mem, dev, "Name");
+ gslt_set_device_param(mem, dev, "OutputFile", "gslt.out");
+
+ /* prepare page for drawing (unused) */
+ gs_erasepage(gs);
+ gs_moveto(gs, 72.0, 72.0);
+
+
+ /* load and decode the image */
+ image = decode_image_filename(mem, filename);
+ if (image == NULL) {
+ fprintf(stderr, "reading image failed.\n");
+ code = -1;
+ }
+ /* save an uncompressed copy for verification */
+ {
+ char outname[50];
+ sprintf(outname, "out_%d.pnm", (int)threadid);
+ fprintf(stderr, "writing %s\n", outname);
+ write_image_filename(image, outname);
+ }
+
+ /* image could be drawn to the page here */
+
+ /* release the image */
+ gslt_image_free(mem, image);
+
+ /* output the page (unused) */
+ gs_output_page(gs, 1, 1);
+
+ /* clean up the library */
+ gslt_free_state(mem, gs);
+ gslt_free_device(mem, dev);
+ gslt_free_library(mem);
+
+ pthread_exit(NULL);
+}
+
+int
+main(int argc, const char *argv[])
+{
+
+ pthread_t thread1, thread2;
+ int ret;
+ int t1 = 1;
+ int t2 = 2;
+
+ filename = argv[argc-1];
+ fprintf(stderr, "loading '%s'\n", filename);
+
+ if ( ((ret=pthread_create(&thread1, NULL, print_image, (void *)t1)) != 0) ||
+ ((ret=pthread_create(&thread2, NULL, print_image, (void *)t2)) != 0) ) {
+ fprintf(stderr, "Error creating thread code=%d", ret);
+ exit(-1);
+ }
+ pthread_exit(NULL);
+}
+
diff --git a/tools/gslite/gslt_image_tiff.c b/tools/gslite/gslt_image_tiff.c
index a9a53026f..4d6a611ae 100644
--- a/tools/gslite/gslt_image_tiff.c
+++ b/tools/gslite/gslt_image_tiff.c
@@ -11,7 +11,7 @@
San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
*/
-/* $Id: gslt_image_tiff.c 2460 2006-07-14 18:49:12Z giles $ */
+/* $Id$ */
/* gslt image loading implementation for TIFF images */
#include "std.h"
diff --git a/tools/gslite/gslt_init.c b/tools/gslite/gslt_init.c
index 29f3a80bc..4d58f984c 100644
--- a/tools/gslite/gslt_init.c
+++ b/tools/gslite/gslt_init.c
@@ -166,9 +166,19 @@ gs_state *gslt_init_state(gs_memory_t *mem, gx_device *dev)
return pgs;
}
-void gslt_free_library(gs_memory_t *mem, gx_device *dev, gs_state *pgs)
+void gslt_free_state(gs_memory_t *mem, gs_state *pgs)
{
- gs_lib_finit(0, 0, mem);
+ gs_state_free(pgs);
+}
+
+void gslt_free_device(gs_memory_t *mem, gx_device *dev)
+{
+ gs_free_object(mem, dev, "gslt device"); // TODO: how do i free devices?
+}
+
+void gslt_free_library(gs_memory_t *mem)
+{
+ // TODO: how do i free the allocator?
}
#if 0
diff --git a/tools/gslite/gslt_lib_gcc.mak b/tools/gslite/gslt_lib_gcc.mak
new file mode 100755
index 000000000..8dd9e4cce
--- /dev/null
+++ b/tools/gslite/gslt_lib_gcc.mak
@@ -0,0 +1,140 @@
+# gslite library makefile.
+MAKEFILE=gslt_lib_gcc.mak
+
+# this is where we build everything. The ghostscript makefiles will
+# need all of these set to work properly.
+GENDIR=./obj
+GLGENDIR=./obj
+GLOBJDIR=./obj
+
+# location of ghostscript source code.
+GLSRCDIR=../../gs/src
+
+# sigh. will we ever fix this?
+GX_COLOR_INDEX_DEFINE=-DGX_COLOR_INDEX_TYPE="unsigned long long"
+
+# set up flags. NB refactor duplication - see gccdefs.mak included
+# below and figure out how best to set up GCFLAGS, XCFLAGS, and
+# .*FLAGS
+
+GCFLAGS=-DGSLITE -Wall -Wpointer-arith -Wstrict-prototypes -Wwrite-strings -DNDEBUG $(GX_COLOR_INDEX_DEFINE) -fPIC
+XCFLAGS=-DGSLITE -Wall -Wpointer-arith -Wstrict-prototypes -Wwrite-strings -DNDEBUG $(GX_COLOR_INDEX_DEFINE) -fPIC
+
+DD=$(GLGENDIR)/
+
+# output devices - none required.
+DEVICES=
+
+# required features in addition to libcore.dev. NB This should be
+# pruned.
+FEATURES=\
+ $(DD)page.dev $(DD)gsnogc.dev $(DD)ttflib.dev $(DD)sdctd.dev\
+ $(DD)psf1lib.dev $(DD)psf2lib.dev\
+ $(DD)path1lib.dev $(DD)shadelib.dev $(DD)cidlib.dev\
+ $(DD)psl3lib.dev $(DD)slzwd.dev $(DD)szlibd.dev\
+ $(DD)cmaplib.dev $(DD)libpng.dev
+
+# jpeg
+JSRCDIR=../../gs/jpeg
+JGENDIR=$(GENDIR)
+JOBJDIR=$(GENDIR)
+
+# zlib
+ZSRCDIR=../../gs/zlib
+ZGENDIR=$(GENDIR)
+ZOBJDIR=$(GENDIR)
+
+# lib png
+PSRCDIR=../../gs/libpng
+PGENDIR=$(GENDIR)
+POBJDIR=$(GENDIR)
+
+SHARE_ZLIB=0
+SHARE_LIBPNG=0
+SHARE_JPEG=0
+
+# ill-named extra libraries.
+STDLIBS=-lm
+
+# shared library NB - needs soname.
+GSLITE_LIB=libgslt.so
+
+all: $(GSLITE_LIB)
+
+# gs library config and miscellany.
+GSXLIBS=$(GLOBJDIR)/gsargs.$(OBJ) $(GLOBJDIR)/gsfemu.$(OBJ) $(GLOBJDIR)/gconfig.$(OBJ) $(GLOBJDIR)/gscdefs.$(OBJ)
+
+# invoke the gs *library* makefile to build needed
+# devices, objects and configuration files.
+GSLIB_PARTS=$(GLOBJDIR)/ld.tr
+$(GSLIB_PARTS): $(MAKEFILE)
+ -mkdir $(GLOBJDIR)
+ $(MAKE) \
+ GCFLAGS='$(GCFLAGS)' \
+ STDLIBS="$(STDLIBS)" \
+ FEATURE_DEVS="$(FEATURES)"\
+ DEVICE_DEVS="$(DEVICES)"\
+ GLSRCDIR=$(GLSRCDIR) GLGENDIR=$(GLGENDIR) GLOBJDIR=$(GLOBJDIR) \
+ JSRCDIR=$(JSRCDIR) JGENDIR=$(JGENDIR) JOBJDIR=$(JOBJDIR)\
+ ZSRCDIR=$(ZSRCDIR) ZGENDIR=$(ZGENDIR) ZOBJDIR=$(ZOBJDIR)\
+ PSRCDIR=$(PSRCDIR) PGENDIR=$(PGENDIR) POBJDIR=$(POBJDIR)\
+ SHARE_ZLIB=$(SHARE_ZLIB) SHARE_LIBPNG=$(SHARE_LIBPNG) SHARE_JPEG=$(SHARE_JPEG)\
+ -f $(GLSRCDIR)/ugcclib.mak \
+ $(GLOBJDIR)/ld.tr \
+ $(GSXLIBS)
+ $(GLOBJDIR)/jpeglib_.h
+
+# ---------------------------------
+# settings needed for building the gslite objects of gslt.mak
+
+GSLTSRCDIR=.
+
+# common definitions - CC_, I_ etc.
+COMMONDIR=../../common
+include $(COMMONDIR)/unixdefs.mak
+include $(COMMONDIR)/gccdefs.mak
+
+# include for gslt sources
+include gslt.mak
+
+# ---------------------------------
+# put gslite and graphics library objects in one library
+
+# ---------------------------------
+# put gslite and graphics library objects in one library
+
+LIBS = -lgslt -lpthread -L./
+
+
+# NB missing soname, version business.
+$(GSLITE_LIB): $(GSLIB_PARTS) $(GSLT_OBJS) $(MAKEFILE)
+ gcc -Xlinker -V -shared -Wl `cat obj/ld.tr | sed 's/\\\\//g'` $(GSXLIBS) $(GSLT_OBJS) -o $(GSLITE_LIB) $(STDLIBS)
+
+$(GSLTOBJ)gslt_image_test.$(OBJ) : $(GSLITE_LIB) $(GSLTSRC)gslt_image_test.c
+ $(GSLT_CC) $(GSLTO_)gslt_image_test.$(OBJ) $(C_) $(GSLTSRC)gslt_image_test.c
+
+$(GSLTOBJ)gslt_font_test.$(OBJ) : $(GSLITE_LIB) $(GSLTSRC)gslt_font_test.c
+ $(GSLT_CC) $(GSLTO_)gslt_font_test.$(OBJ) $(C_) $(GSLTSRC)gslt_font_test.c
+
+$(GSLTOBJ)gslt_image_threads_test.$(OBJ) : $(GSLITE_LIB) $(GSLTSRC)gslt_image_threads_test.c
+ $(GSLT_CC) $(GSLTO_)gslt_image_threads_test.$(OBJ) $(C_) $(GSLTSRC)gslt_image_threads_test.c
+
+gslt_image_test: $(GSLTOBJ)gslt_image_test.$(OBJ) $(gslt_OBJS)
+ $(CC) $(CPPFLAGS) $(CFLAGS) $(INCLUDES) -o $@ $^ $(LDFLAGS) $(LIBS)
+
+gslt_font_test: $(GSLTOBJ)gslt_font_test.$(OBJ) $(gslt_OBJS)
+ $(CC) $(CPPFLAGS) $(CFLAGS) $(INCLUDES) -o $@ $^ $(LDFLAGS) $(LIBS)
+
+gslt_image_threads_test: $(GSLTOBJ)gslt_image_threads_test.$(OBJ) $(gslt_OBJS)
+ $(CC) $(CPPFLAGS) $(CFLAGS) $(INCLUDES) -o $@ $^ $(LDFLAGS) $(LIBS)
+
+
+test: $(GSLITE_LIB) gslt_image_test gslt_font_test gslt_image_threads_test
+ (export LD_LIBRARY_PATH=.; ./gslt_image_test tiger.jpg; \
+ ./gslt_font_test CenturySchL-Bold.ttf; ./gslt_image_threads_test tiger.jpg)
+
+
+clean:
+ $(RM) *.pnm *.pbm *.so *.o *~ obj/*
+
+.PHONY: clean test all
diff --git a/tools/gslite/gslt_lib_msvc.mak b/tools/gslite/gslt_lib_msvc.mak
new file mode 100755
index 000000000..250da63a6
--- /dev/null
+++ b/tools/gslite/gslt_lib_msvc.mak
@@ -0,0 +1,145 @@
+# gslite library makefile.
+
+MAKEFILE=gslt_lib_msvc.mak
+MSVC_VERSION=8
+
+# Debugging options. For production system DEBUG=0 and TDEBUG=0.
+DEBUG=1
+TDEBUG=1
+
+DEVSTUDIO=
+NOPRIVATE=0
+
+COMPILE_INITS=0
+
+
+# this is where we build everything. The ghostscript makefiles will
+# need all of these set to work properly.
+GENDIR=.\obj
+GLGENDIR=.\obj
+GLOBJDIR=.\obj
+
+# location of ghostscript source code.
+GLSRCDIR=..\..\gs\src
+
+# sigh. will we ever fix this? Definitions to force gx_color_index
+# to 64 bits and define GSLITE.
+
+XCFLAGS=/DGSLITE
+
+DD=$(GLGENDIR)
+
+# output devices - none required.
+DEVICES=
+
+# required features in addition to libcore.dev. NB This should be
+# pruned.
+FEATURES=\
+ $(DD)\page.dev $(DD)\gsnogc.dev $(DD)\ttflib.dev $(DD)\sdctd.dev\
+ $(DD)\psf1lib.dev $(DD)\psf2lib.dev\
+ $(DD)\path1lib.dev $(DD)\shadelib.dev $(DD)\cidlib.dev\
+ $(DD)\psl3lib.dev $(DD)\slzwd.dev $(DD)\szlibd.dev\
+ $(DD)\cmaplib.dev $(DD)\libpng.dev
+
+# jpeg
+JSRCDIR=..\..\gs\jpeg
+JGENDIR=$(GENDIR)
+JOBJDIR=$(GENDIR)
+
+# zlib
+ZSRCDIR=..\..\gs\zlib
+ZGENDIR=$(GENDIR)
+ZOBJDIR=$(GENDIR)
+
+# lib png
+PSRCDIR=..\..\gs\libpng
+PGENDIR=$(GENDIR)
+POBJDIR=$(GENDIR)
+
+# indicate we do not want use system shared libraries for zlib, png,
+# and jpeg.
+SHARE_ZLIB=0
+SHARE_LIBPNG=0
+SHARE_JPEG=0
+
+STDLIBS=-lm
+
+GSLITE_LIB=libgslt.lib
+all: $(GSLITE_LIB)
+
+# invoke the gs *library* makefile to build needed
+# devices, objects and configuration files.
+GSLIB_PARTS=$(GLOBJDIR)\ld.tr
+$(GSLIB_PARTS): $(MAKEFILE)
+ -mkdir $(GLOBJDIR)
+ $(MAKE) \
+ DEBUG=$(DEBUG) \
+ TDEBUG=$(TDEBUG) \
+ MSVC_VERSION=$(MSVC_VERSION) \
+ DEVSTUDIO=$(DEVSTUDIO) \
+ GCFLAGS=$(GCFLAGS) \
+ XCFLAGS=$(XCFLAGS) \
+ STDLIBS=$(STDLIBS) \
+ FEATURE_DEVS="$(FEATURES)"\
+ DEVICE_DEVS="$(DEVICES)"\
+ GLSRCDIR=$(GLSRCDIR) GLGENDIR=$(GLGENDIR) GLOBJDIR=$(GLOBJDIR) \
+ JSRCDIR=$(JSRCDIR) JGENDIR=$(JGENDIR) JOBJDIR=$(JOBJDIR)\
+ ZSRCDIR=$(ZSRCDIR) ZGENDIR=$(ZGENDIR) ZOBJDIR=$(ZOBJDIR)\
+ PSRCDIR=$(PSRCDIR) PGENDIR=$(PGENDIR) POBJDIR=$(POBJDIR)\
+ SHARE_ZLIB=$(SHARE_ZLIB) SHARE_LIBPNG=$(SHARE_LIBPNG) SHARE_JPEG=$(SHARE_JPEG)\
+ /f $(GLSRCDIR)\msvclib.mak \
+ $(GLOBJDIR)\ld.tr \
+ $(GLOBJDIR)\gsargs.obj $(GLOBJDIR)\gsfemu.obj \
+ $(GLOBJDIR)\gconfig.obj $(GLOBJDIR)\gscdefs.obj \
+ $(GLOBJDIR)\jpeglib_.h
+
+
+# ---------------------------------
+# settings needed for building the gslite objects of gslt.mak
+
+GSLTSRCDIR=.
+
+
+# common definitions - CC_, I_ etc.
+COMMONDIR=..\..\common
+!include $(COMMONDIR)\pcdefs.mak
+!include $(COMMONDIR)\msvcdefs.mak
+!include $(GLSRCDIR)\msvccmd.mak
+
+# include for gslt sources
+!include gslt.mak
+
+# ---------------------------------
+# put gslite and graphics library objects in one library
+
+
+
+# windows clutter.
+MSXLIBS=shell32.lib comdlg32.lib gdi32.lib user32.lib winspool.lib advapi32.lib
+# gs library config and miscellany.
+GSXLIBS=$(GLOBJDIR)\gsargs.obj $(GLOBJDIR)\gsfemu.obj $(GLOBJDIR)\gconfig.obj $(GLOBJDIR)\gscdefs.obj
+
+$(GSLITE_LIB): $(GSLIB_PARTS) $(GSLT_OBJS) $(GSXLIBS) $(MAKEFILE)
+ lib /out:$(GSLITE_LIB) @obj\ld.tr $(GSLT_OBJS) $(MSXLIBS) $(GSXLIBS)
+
+# the dependency on GSLIB_LIB is needed because the c compiler line
+# @ccf32.tr is a needed side effect from building the library.
+$(GSLTOBJ)gslt_image_test.$(OBJ) : $(GSLITE_LIB) $(GSLTSRC)gslt_image_test.c
+ $(GSLT_CC) $(GSLTO_)gslt_image_test.$(OBJ) $(C_) $(GSLTSRC)gslt_image_test.c
+
+$(GSLTOBJ)gslt_font_test.$(OBJ) : $(GSLITE_LIB) $(GSLTSRC)gslt_font_test.c
+ $(GSLT_CC) $(GSLTO_)gslt_font_test.$(OBJ) $(C_) $(GSLTSRC)gslt_font_test.c
+
+gslt_image_test.exe: $(GSLTOBJ)gslt_image_test.$(OBJ) $(GSLT_OBJS) $(GSLITE_LIB)
+ link $(GSLTOBJ)gslt_image_test.$(OBJ) $(GSLITE_LIB)
+
+gslt_font_test.exe: $(GSLTOBJ)gslt_font_test.$(OBJ) $(GSLT_OBJS) $(GSLITE_LIB)
+ link $(GSLTOBJ)gslt_font_test.$(OBJ) $(GSLITE_LIB)
+
+
+test: gslt_font_test.exe gslt_image_test.exe
+ gslt_font_test CenturySchL-Bold.ttf
+ gslt_image_test tiger.jpg
+
+clean:
+ del *.pnm *.pbm *.lib *.exe obj\*.obj *.obj obj\*.tr
diff --git a/tools/gslite/gslt_stubs.c b/tools/gslite/gslt_stubs.c
new file mode 100644
index 000000000..307994d8a
--- /dev/null
+++ b/tools/gslite/gslt_stubs.c
@@ -0,0 +1,44 @@
+/* Copyright (C) 2006 artofcode LLC.
+ All Rights Reserved.
+
+ This software is provided AS-IS with no warranty, either express or
+ implied.
+
+ This software is distributed under license and may not be copied, modified
+ or distributed except as expressly authorized under the terms of that
+ license. Refer to licensing information at http://www.artifex.com/
+ or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
+ San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
+*/
+
+/* $Id: $ */
+/* gslt stubs */
+
+/* NB includes and stubs copied from plplatf.c */
+#include "string_.h"
+#include "gdebug.h"
+#include "gsio.h"
+#include "gstypes.h"
+#include "gsmemory.h"
+#include "gsstruct.h"
+#include "gp.h"
+#include "gslib.h"
+
+/* ---------------- Stubs ---------------- */
+
+/* Stubs for GC */
+const gs_ptr_procs_t ptr_struct_procs = { NULL, NULL, NULL };
+const gs_ptr_procs_t ptr_string_procs = { NULL, NULL, NULL };
+const gs_ptr_procs_t ptr_const_string_procs = { NULL, NULL, NULL };
+void * /* obj_header_t * */
+gs_reloc_struct_ptr(const void * /* obj_header_t * */ obj, gc_state_t *gcst)
+{ return (void *)obj;
+}
+void
+gs_reloc_string(gs_string *sptr, gc_state_t *gcst)
+{
+}
+void
+gs_reloc_const_string(gs_const_string *sptr, gc_state_t *gcst)
+{
+}
diff --git a/tools/gslite/gslt_test.c b/tools/gslite/gslt_test.c
index 758d972eb..a09890dcd 100644
--- a/tools/gslite/gslt_test.c
+++ b/tools/gslite/gslt_test.c
@@ -11,7 +11,7 @@
San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
*/
-/* $Id: gslt_test.c 2453 2006-07-14 17:08:19Z giles $ */
+/* $Id$ */
/* Test program for Ghostscript library */
/* Capture stdin/out/err before gsio.h redefines them. */
@@ -208,11 +208,12 @@ main(int argc, const char *argv[])
gs_erasepage(pgs);
if (tests[achar - '1']) {
+ dprintf1("gslt test case = %d\n", achar - '1');
code = (*tests[achar - '1']) (pgs, mem);
gs_output_page(pgs, 1, 1);
if (code)
dprintf1("**** Test returned code = %d.\n", code);
- dputs("Done. Press <enter> to exit.");
+ dputs("Done. Press <enter> to exit.\n");
fgetc(gs_stdin);
} else {
dputs("test not defined\n");
@@ -938,14 +939,14 @@ test8(gs_state * pgs, gs_memory_t * mem)
gs_setrgbcolor(pgs, 1.0, 1.0, 0.0);
gs_rectfill(pgs, &r, 1);
gs_setpattern(pgs, &ccolor);
- gs_settexturetransparent(pgs, true);
+ // gs_settexturetransparent(pgs, true);
gs_rectfill(pgs, &r, 1);
r.p.x += 150;
r.q.x += 150;
gs_setrgbcolor(pgs, 1.0, 1.0, 0.0);
gs_rectfill(pgs, &r, 1);
gs_setpattern(pgs, &ccolor);
- gs_settexturetransparent(pgs, false);
+ // gs_settexturetransparent(pgs, false);
gs_rectfill(pgs, &r, 1);
}
return 0;
diff --git a/tools/gslite/tiger.jpg b/tools/gslite/tiger.jpg
new file mode 100644
index 000000000..d3bd2c465
--- /dev/null
+++ b/tools/gslite/tiger.jpg
Binary files differ