summaryrefslogtreecommitdiff
path: root/gs/src
diff options
context:
space:
mode:
authorHenry Stiles <henry.stiles@artifex.com>1999-10-03 08:21:45 +0000
committerHenry Stiles <henry.stiles@artifex.com>1999-10-03 08:21:45 +0000
commitee50b36ccabde111c6d77c5f9892213d53060a18 (patch)
tree35f7e38774b082c4cdbe4f4fad881903862a83c2 /gs/src
parent0ea97dbf2a40bc347a20134197643bc1daef6de8 (diff)
This is the first gs593 integration it is *NOT* a release. Normally
each file is checked in with an associated log entry, in order to check in all of the code simultaneously we batch all of the file name's modified and change descriptions here (Note: Aladdin code changes are documented in gs/doc/News.htm) - pcstate.h - removes show enumeration from pcl state. - pctop.c, pxtop.c - gs_grestore_no_wraparound()'s is now gs_grestore_only(). - pxgstate.c - ENUM_RETURN_CONST_STRING_PTR() now takes a gs string argument instead of the string's data as it did previously. - plmain.c - - The library no longer initializes io devices. Adds gs_iodev_init() to main() procedure. Also, gs_c_param_list_rewrite() is renamed to gs_c_param_list_write_more(). - pcltop.mak - adds pipe.dev for operating system pipe support. - pctext.c, pglabel.c, pxfont.c, plfont.c - extensive modifications to support the text api (gstext.h) - use gs_text_enum_t instead of gs_show_enum. - removes enumeration allocation, this is now done by the text "begin" functions. - update "next_char" procs and "encode char" procs to take a glyph argument and the character argument is now passed by value (pcl nor xl make use of the glyph argument). - char_path_n_init() replaced with gs_charpath_begin(). - gs_show_n_init() replaced with gs_show_begin(). - gs_show_next() is now handled by gs_process_text(). - gs_release_text() added. - gs_xyshow_n_init() replace with gs_xyshow_begin(). Passing of x and y coordinates modified to support the new interface. Unfortunately, we need to transform the coordinates into the space of the font scaling matrix, that is the current ctm for xl when the the text is processed. This differs from postscript which appears to have the regular user->device matrix in the graphics state during processing. - (plfont.c) - gs_notify_init() is now part of the pfont initialization procedure, related TODO: cut over to gs_font_alloc() and gs_font_base_alloc(). - all gs files - removes uninitialized rcs identifiers. KNOWN PROBLEMS: occassional pxl and pcl crashes in gdev_mem_set_line_ptrs() when running in color due to null base (data) pointer. git-svn-id: http://svn.ghostscript.com/ghostpcl/trunk/ghostpcl@985 06663e23-700e-0410-b217-a244a6096597
Diffstat (limited to 'gs/src')
-rw-r--r--gs/src/#gdevmrop.h#94
-rw-r--r--gs/src/ansi2knr.c106
-rw-r--r--gs/src/bcwin32.mak21
-rw-r--r--gs/src/bfont.h4
-rw-r--r--gs/src/ccfont.h31
-rw-r--r--gs/src/contrib.mak65
-rw-r--r--gs/src/devs.mak357
-rwxr-xr-xgs/src/dvx-gcc.mak5
-rw-r--r--gs/src/dwimg.cpp10
-rw-r--r--gs/src/dwtext.cpp10
-rw-r--r--gs/src/echogs.c17
-rw-r--r--gs/src/files.h24
-rw-r--r--gs/src/gconf.c4
-rw-r--r--gs/src/gdevbbox.c741
-rw-r--r--gs/src/gdevbbox.h48
-rw-r--r--gs/src/gdevbit.c4
-rw-r--r--gs/src/gdevbmp.c35
-rw-r--r--gs/src/gdevbmpa.c20
-rw-r--r--gs/src/gdevbmpc.c19
-rw-r--r--gs/src/gdevcd8.c2
-rw-r--r--gs/src/gdevcgm.c14
-rw-r--r--gs/src/gdevclj.c14
-rw-r--r--gs/src/gdevcljc.c15
-rw-r--r--gs/src/gdevddrw.c48
-rw-r--r--gs/src/gdevdfax.c8
-rw-r--r--gs/src/gdevdjet.c8
-rw-r--r--gs/src/gdevdrop.c5
-rw-r--r--gs/src/gdevlj56.c53
-rw-r--r--gs/src/gdevm1.c19
-rw-r--r--gs/src/gdevm16.c34
-rw-r--r--gs/src/gdevm2.c2
-rw-r--r--gs/src/gdevm24.c3
-rw-r--r--gs/src/gdevm4.c4
-rw-r--r--gs/src/gdevm8.c4
-rw-r--r--gs/src/gdevmem.h7
-rw-r--r--gs/src/gdevmiff.c8
-rw-r--r--gs/src/gdevmr1.c2
-rw-r--r--gs/src/gdevmr2n.c4
-rw-r--r--gs/src/gdevnfwd.c5
-rw-r--r--gs/src/gdevp2up.c4
-rw-r--r--gs/src/gdevpbm.c8
-rw-r--r--gs/src/gdevpcx.c4
-rw-r--r--gs/src/gdevpdf.c1435
-rw-r--r--gs/src/gdevpdfd.c12
-rw-r--r--gs/src/gdevpdff.c1080
-rw-r--r--gs/src/gdevpdfi.c38
-rw-r--r--gs/src/gdevpdfm.c1494
-rw-r--r--gs/src/gdevpdfo.c1090
-rw-r--r--gs/src/gdevpdfo.h235
-rw-r--r--gs/src/gdevpdfp.c26
-rw-r--r--gs/src/gdevpdfr.c425
-rw-r--r--gs/src/gdevpdft.c1133
-rw-r--r--gs/src/gdevpdfu.c692
-rw-r--r--gs/src/gdevpdfx.h716
-rw-r--r--gs/src/gdevpipe.c9
-rw-r--r--gs/src/gdevplnx.c10
-rw-r--r--gs/src/gdevpng.c16
-rw-r--r--gs/src/gdevprn.c74
-rw-r--r--gs/src/gdevps.c41
-rw-r--r--gs/src/gdevpsd1.c479
-rw-r--r--gs/src/gdevpsde.c276
-rw-r--r--gs/src/gdevpsdf.c392
-rw-r--r--gs/src/gdevpsdf.h145
-rw-r--r--gs/src/gdevpsdi.c4
-rw-r--r--gs/src/gdevpsdp.c144
-rw-r--r--gs/src/gdevpsds.c24
-rw-r--r--gs/src/gdevpsdt.c776
-rw-r--r--gs/src/gdevpsim.c6
-rw-r--r--gs/src/gdevtfax.c7
-rw-r--r--gs/src/gdevtfax.h (renamed from gs/src/t)16
-rw-r--r--gs/src/gdevtfnx.c8
-rw-r--r--gs/src/gdevupd.c8
-rw-r--r--gs/src/gdevvec.c16
-rw-r--r--gs/src/gdevwpr2.c1
-rw-r--r--gs/src/gdevx.c629
-rw-r--r--gs/src/gdevx.h150
-rw-r--r--gs/src/gdevxalt.c84
-rw-r--r--gs/src/gdevxcmp.c149
-rw-r--r--gs/src/gdevxcmp.h49
-rw-r--r--gs/src/gdevxini.c330
-rw-r--r--gs/src/gdevxres.c4
-rw-r--r--gs/src/gdevxxf.c12
-rw-r--r--gs/src/genarch.c6
-rw-r--r--gs/src/genconf.c27
-rw-r--r--gs/src/genht.c5
-rw-r--r--gs/src/gp.h28
-rw-r--r--gs/src/gp_gnrdl.c68
-rw-r--r--gs/src/gp_iwatc.c26
-rw-r--r--gs/src/gp_mshdl.c122
-rw-r--r--gs/src/gp_msio.c27
-rw-r--r--gs/src/gp_mswin.c10
-rw-r--r--gs/src/gp_os2.c17
-rw-r--r--gs/src/gp_unix.c13
-rw-r--r--gs/src/gpcheck.h3
-rw-r--r--gs/src/gs.mak6
-rw-r--r--gs/src/gsalloc.c205
-rw-r--r--gs/src/gsalphac.c10
-rw-r--r--gs/src/gsbitops.c82
-rw-r--r--gs/src/gsbittab.c59
-rw-r--r--gs/src/gsccode.h34
-rw-r--r--gs/src/gscdef.c4
-rw-r--r--gs/src/gschar.c1395
-rw-r--r--gs/src/gschar.h11
-rw-r--r--gs/src/gschar0.c96
-rw-r--r--gs/src/gscie.c25
-rw-r--r--gs/src/gsciemap.c4
-rw-r--r--gs/src/gscolor.c10
-rw-r--r--gs/src/gscolor2.c35
-rw-r--r--gs/src/gscparam.c6
-rw-r--r--gs/src/gscpm.h3
-rw-r--r--gs/src/gscrd.c20
-rw-r--r--gs/src/gscscie.c19
-rw-r--r--gs/src/gscsepr.c8
-rw-r--r--gs/src/gscspace.c16
-rw-r--r--gs/src/gsdevice.c181
-rw-r--r--gs/src/gsdevice.h1
-rw-r--r--gs/src/gsdevmem.c3
-rw-r--r--gs/src/gsdll32w.lnk11
-rw-r--r--gs/src/gsdparam.c1
-rw-r--r--gs/src/gsdsrc.c8
-rw-r--r--gs/src/gserror.h4
-rw-r--r--gs/src/gsfcmap.c8
-rw-r--r--gs/src/gsfname.c (renamed from gs/src/zfname.c)68
-rw-r--r--gs/src/gsfname.h (renamed from gs/src/fname.h)32
-rw-r--r--gs/src/gsfont.c416
-rw-r--r--gs/src/gsfont0.c20
-rw-r--r--gs/src/gsfunc.c87
-rw-r--r--gs/src/gsfunc.h77
-rw-r--r--gs/src/gsfunc0.c83
-rw-r--r--gs/src/gsfunc3.c165
-rw-r--r--gs/src/gshsb.h3
-rw-r--r--gs/src/gsht1.c28
-rw-r--r--gs/src/gshtscr.c10
-rw-r--r--gs/src/gsimage.c6
-rw-r--r--gs/src/gsimpath.c3
-rwxr-xr-xgs/src/gsindent33
-rw-r--r--gs/src/gsiodev.c1
-rw-r--r--gs/src/gsline.c17
-rw-r--r--gs/src/gsline.h11
-rw-r--r--gs/src/gsmalloc.c10
-rw-r--r--gs/src/gsmatrix.c15
-rw-r--r--gs/src/gsmemlok.c37
-rw-r--r--gs/src/gsmemory.c46
-rw-r--r--gs/src/gsmemory.h7
-rw-r--r--gs/src/gsmemraw.h33
-rw-r--r--gs/src/gsmemret.c28
-rw-r--r--gs/src/gsmisc.c19
-rw-r--r--gs/src/gsnogc.c31
-rw-r--r--gs/src/gsnorop.c3
-rw-r--r--gs/src/gsnotify.c115
-rw-r--r--gs/src/gsnotify.h88
-rw-r--r--gs/src/gsparam.h2
-rw-r--r--gs/src/gsparamx.c18
-rw-r--r--gs/src/gsparamx.h2
-rw-r--r--gs/src/gspath.c1
-rw-r--r--gs/src/gspcolor.c9
-rw-r--r--gs/src/gsptype1.c31
-rw-r--r--gs/src/gsrefct.h33
-rw-r--r--gs/src/gsropc.c12
-rw-r--r--gs/src/gsshade.c2
-rw-r--r--gs/src/gsstate.c36
-rw-r--r--gs/src/gsstate.h7
-rw-r--r--gs/src/gsstruct.h208
-rw-r--r--gs/src/gsstype.h23
-rwxr-xr-xgs/src/gssubst23
-rw-r--r--gs/src/gstext.c302
-rw-r--r--gs/src/gstext.h135
-rw-r--r--gs/src/gstype1.c4
-rw-r--r--gs/src/gstype1.h3
-rw-r--r--gs/src/gstype2.c18
-rw-r--r--gs/src/gstype42.c305
-rw-r--r--gs/src/gsutil.c1
-rw-r--r--gs/src/gxacpath.c34
-rw-r--r--gs/src/gxalloc.h35
-rw-r--r--gs/src/gxccache.c2
-rw-r--r--gs/src/gxchar.c1305
-rw-r--r--gs/src/gxchar.h77
-rw-r--r--gs/src/gxcie.h58
-rw-r--r--gs/src/gxcldev.h18
-rw-r--r--gs/src/gxclip.c8
-rw-r--r--gs/src/gxclip2.c6
-rw-r--r--gs/src/gxclip2.h7
-rw-r--r--gs/src/gxclist.c27
-rw-r--r--gs/src/gxclist.h11
-rw-r--r--gs/src/gxclpath.c36
-rw-r--r--gs/src/gxclpath.h12
-rw-r--r--gs/src/gxclrast.c8
-rw-r--r--gs/src/gxcmap.c6
-rw-r--r--gs/src/gxcmap.h5
-rw-r--r--gs/src/gxcpath.c36
-rw-r--r--gs/src/gxcpath.h9
-rw-r--r--gs/src/gxcspace.h14
-rw-r--r--gs/src/gxdevice.h23
-rw-r--r--gs/src/gxfarith.h14
-rw-r--r--gs/src/gxfcache.h4
-rw-r--r--gs/src/gxfill.c4
-rw-r--r--gs/src/gxfixed.h28
-rw-r--r--gs/src/gxfont.h294
-rw-r--r--gs/src/gxfont0.h9
-rw-r--r--gs/src/gxfont1.h8
-rw-r--r--gs/src/gxfont42.h29
-rw-r--r--gs/src/gxfunc.h4
-rw-r--r--gs/src/gxhint2.c43
-rw-r--r--gs/src/gxht.c6
-rw-r--r--gs/src/gxi12bit.c5
-rw-r--r--gs/src/gxicolor.c3
-rw-r--r--gs/src/gxifast.c23
-rw-r--r--gs/src/gximage3.c11
-rw-r--r--gs/src/gximono.c3
-rw-r--r--gs/src/gxiodev.h16
-rw-r--r--gs/src/gxipixel.c13
-rw-r--r--gs/src/gxiscale.c75
-rw-r--r--gs/src/gxline.h10
-rw-r--r--gs/src/gxmatrix.h5
-rw-r--r--gs/src/gxmclip.c13
-rw-r--r--gs/src/gxmclip.h4
-rw-r--r--gs/src/gxobj.h90
-rw-r--r--gs/src/gxp1fill.c4
-rw-r--r--gs/src/gxp1impl.h (renamed from gs/src/gxp1fill.h)19
-rw-r--r--gs/src/gxpaint.c4
-rw-r--r--gs/src/gxpaint.h9
-rw-r--r--gs/src/gxpath.c8
-rw-r--r--gs/src/gxpath2.c21
-rw-r--r--gs/src/gxpcopy.c20
-rw-r--r--gs/src/gxshade1.c50
-rw-r--r--gs/src/gxstroke.c125
-rw-r--r--gs/src/gxtext.h172
-rw-r--r--gs/src/gxtype1.c11
-rw-r--r--gs/src/gxxfont.h18
-rw-r--r--gs/src/gzstate.h6
-rw-r--r--gs/src/ialloc.c92
-rw-r--r--gs/src/ialloc.h11
-rw-r--r--gs/src/ibnum.c2
-rw-r--r--gs/src/iccfont.c88
-rw-r--r--gs/src/ichar.h44
-rw-r--r--gs/src/icharout.h19
-rw-r--r--gs/src/icontext.c42
-rw-r--r--gs/src/icontext.h3
-rw-r--r--gs/src/icstate.h1
-rw-r--r--gs/src/idebug.c24
-rw-r--r--gs/src/idebug.h3
-rw-r--r--gs/src/idict.c93
-rw-r--r--gs/src/idosave.h42
-rw-r--r--gs/src/ifilter2.h31
-rw-r--r--gs/src/ifont.h5
-rw-r--r--gs/src/ifrpred.h30
-rw-r--r--gs/src/ifunc.h20
-rw-r--r--gs/src/ifwpred.h30
-rw-r--r--gs/src/igc.c287
-rw-r--r--gs/src/igc.h5
-rw-r--r--gs/src/igcref.c163
-rw-r--r--gs/src/igcstr.h2
-rw-r--r--gs/src/iimage.h5
-rw-r--r--gs/src/iimage2.h9
-rw-r--r--gs/src/iinit.c16
-rw-r--r--gs/src/iinit.h40
-rw-r--r--gs/src/ilocate.c192
-rw-r--r--gs/src/imain.c91
-rw-r--r--gs/src/imain.h9
-rw-r--r--gs/src/imainarg.c1
-rw-r--r--gs/src/imemory.h16
-rw-r--r--gs/src/iname.c395
-rw-r--r--gs/src/iname.h4
-rw-r--r--gs/src/inamedef.h128
-rw-r--r--gs/src/inameidx.h85
-rw-r--r--gs/src/inames.h6
-rw-r--r--gs/src/inamestr.h98
-rw-r--r--gs/src/inobtokn.c1
-rwxr-xr-xgs/src/instcopy31
-rw-r--r--gs/src/int.mak171
-rw-r--r--gs/src/interp.c148
-rw-r--r--gs/src/interp.h7
-rw-r--r--gs/src/iparam.c184
-rw-r--r--gs/src/iparam.h63
-rw-r--r--gs/src/iparray.h4
-rw-r--r--gs/src/ipcolor.h3
-rw-r--r--gs/src/ireclaim.c98
-rw-r--r--gs/src/isave.c207
-rw-r--r--gs/src/isave.h32
-rw-r--r--gs/src/iscan.c94
-rw-r--r--gs/src/iscan.h1
-rw-r--r--gs/src/iscanbin.c8
-rw-r--r--gs/src/iscanbin.h37
-rw-r--r--gs/src/iscannum.c10
-rw-r--r--gs/src/iscannum.h9
-rw-r--r--gs/src/isstate.h6
-rw-r--r--gs/src/istack.c62
-rw-r--r--gs/src/istack.h16
-rw-r--r--gs/src/istkparm.h44
-rw-r--r--gs/src/istream.h7
-rw-r--r--gs/src/istruct.h6
-rw-r--r--gs/src/iutil.c52
-rw-r--r--gs/src/iutil.h32
-rw-r--r--gs/src/ivmem2.h29
-rw-r--r--gs/src/lib.mak200
-rw-r--r--gs/src/math_.h4
-rw-r--r--gs/src/memory_.h8
-rw-r--r--gs/src/msvc32.mak4
-rw-r--r--gs/src/msvccmd.mak6
-rw-r--r--gs/src/msvclib.mak9
-rw-r--r--gs/src/oparc.h34
-rw-r--r--gs/src/openvms.mak1
-rw-r--r--gs/src/openvms.mmk1
-rw-r--r--gs/src/opextern.h44
-rw-r--r--gs/src/os2.mak3
-rw-r--r--gs/src/pipe_.h10
-rw-r--r--gs/src/sbwbs.c30
-rw-r--r--gs/src/scf.h7
-rw-r--r--gs/src/scfd.c55
-rw-r--r--gs/src/scfdgen.c7
-rw-r--r--gs/src/scfdtab.c1829
-rw-r--r--gs/src/scfetab.c5
-rw-r--r--gs/src/scfx.h8
-rw-r--r--gs/src/sdct.h2
-rw-r--r--gs/src/sdctc.c3
-rw-r--r--gs/src/sdcte.c25
-rw-r--r--gs/src/seexec.c4
-rw-r--r--gs/src/sfilter1.c12
-rw-r--r--gs/src/sfilter2.c67
-rw-r--r--gs/src/shc.h44
-rw-r--r--gs/src/siscale.c41
-rw-r--r--gs/src/sjpegc.c3
-rw-r--r--gs/src/slzwce.c4
-rw-r--r--gs/src/slzwd.c4
-rw-r--r--gs/src/slzwx.h6
-rw-r--r--gs/src/spdiff.c2
-rw-r--r--gs/src/spngp.c16
-rw-r--r--gs/src/spngpx.h6
-rw-r--r--gs/src/spprint.c (renamed from gs/src/gdevpstr.c)6
-rw-r--r--gs/src/spprint.h (renamed from gs/src/gdevpstr.h)13
-rw-r--r--gs/src/spsdf.c267
-rw-r--r--gs/src/spsdf.h86
-rw-r--r--gs/src/std.h19
-rw-r--r--gs/src/stdpre.h28
-rw-r--r--gs/src/store.h53
-rw-r--r--gs/src/stream.c241
-rw-r--r--gs/src/stream.h29
-rw-r--r--gs/src/strimpl.h26
-rw-r--r--gs/src/string_.h26
-rw-r--r--gs/src/szlibc.c4
-rw-r--r--gs/src/ugcclib.mak6
-rw-r--r--gs/src/unix-aux.mak11
-rwxr-xr-xgs/src/unix-gcc.mak46
-rwxr-xr-xgs/src/unixansi.mak4
-rw-r--r--gs/src/unixinst.mak14
-rw-r--r--gs/src/unixtrad.mak4
-rw-r--r--gs/src/version.mak6
-rw-r--r--gs/src/watc.mak27
-rw-r--r--gs/src/watcw32.mak188
-rw-r--r--gs/src/wccommon.mak10
-rw-r--r--gs/src/winint.mak30
-rw-r--r--gs/src/winlib.mak13
-rw-r--r--gs/src/zarith.c45
-rw-r--r--gs/src/zarray.c7
-rw-r--r--gs/src/zbfont.c24
-rw-r--r--gs/src/zcfont.c82
-rw-r--r--gs/src/zchar.c249
-rw-r--r--gs/src/zchar1.c200
-rw-r--r--gs/src/zchar32.c1
-rw-r--r--gs/src/zchar42.c32
-rw-r--r--gs/src/zcharout.c111
-rw-r--r--gs/src/zcharx.c177
-rw-r--r--gs/src/zcie.c1
-rw-r--r--gs/src/zcolor.c4
-rw-r--r--gs/src/zcolor1.c39
-rw-r--r--gs/src/zcontext.c129
-rw-r--r--gs/src/zcontrol.c5
-rw-r--r--gs/src/zcrd.c2
-rw-r--r--gs/src/zdevice.c6
-rw-r--r--gs/src/zdevice2.c19
-rw-r--r--gs/src/zdict.c5
-rw-r--r--gs/src/zdpnext.c4
-rw-r--r--gs/src/zdps.c22
-rw-r--r--gs/src/zdps1.c41
-rw-r--r--gs/src/zfcmap.c5
-rw-r--r--gs/src/zfdctd.c2
-rw-r--r--gs/src/zfdcte.c4
-rw-r--r--gs/src/zfdecode.c16
-rw-r--r--gs/src/zfile.c145
-rw-r--r--gs/src/zfileio.c6
-rw-r--r--gs/src/zfilter.c30
-rw-r--r--gs/src/zfilter2.c10
-rw-r--r--gs/src/zfont.c29
-rw-r--r--gs/src/zfont0.c26
-rw-r--r--gs/src/zfont1.c58
-rw-r--r--gs/src/zfont32.c4
-rw-r--r--gs/src/zfont42.c116
-rw-r--r--gs/src/zfproc.c49
-rw-r--r--gs/src/zfreuse.c19
-rw-r--r--gs/src/zfunc.c35
-rw-r--r--gs/src/zfunc0.c16
-rw-r--r--gs/src/zfunc3.c28
-rw-r--r--gs/src/zfunc4.c299
-rw-r--r--gs/src/zfzlib.c10
-rw-r--r--gs/src/zgeneric.c16
-rw-r--r--gs/src/zgstate.c32
-rw-r--r--gs/src/zht1.c2
-rw-r--r--gs/src/zht2.c28
-rw-r--r--gs/src/zimage.c41
-rw-r--r--gs/src/zimage2.c18
-rw-r--r--gs/src/ziodev.c72
-rw-r--r--gs/src/ziodev2.c8
-rw-r--r--gs/src/zlib.mak14
-rw-r--r--gs/src/zmath.c25
-rw-r--r--gs/src/zmedia2.c6
-rw-r--r--gs/src/zmisc.c23
-rw-r--r--gs/src/zpacked.c12
-rw-r--r--gs/src/zpath1.c1
-rw-r--r--gs/src/zpcolor.c6
-rw-r--r--gs/src/zrelbit.c27
-rw-r--r--gs/src/zshade.c117
-rw-r--r--gs/src/ztrap.c2
-rw-r--r--gs/src/ztype.c9
-rw-r--r--gs/src/zupath.c11
-rw-r--r--gs/src/zusparam.c13
-rw-r--r--gs/src/zvmem.c16
-rw-r--r--gs/src/zvmem2.c1
417 files changed, 20575 insertions, 11519 deletions
diff --git a/gs/src/#gdevmrop.h# b/gs/src/#gdevmrop.h#
new file mode 100644
index 000000000..ba891e931
--- /dev/null
+++ b/gs/src/#gdevmrop.h#
@@ -0,0 +1,94 @@
+/* Copyright (C) 1995, 1996, 1998, 1999 Aladdin Enterprises. All rights reserved.
+
+ This file is part of Aladdin Ghostscript.
+
+ Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
+ or distributor accepts any responsibility for the consequences of using it,
+ or for whether it serves any particular purpose or works at all, unless he
+ or she says so in writing. Refer to the Aladdin Ghostscript Free Public
+ License (the "License") for full details.
+
+ Every copy of Aladdin Ghostscript must include a copy of the License,
+ normally in a plain ASCII text file named PUBLIC. The License grants you
+ the right to copy, modify and redistribute Aladdin Ghostscript, but only
+ under certain conditions described in the License. Among other things, the
+ License requires that the copyright notice and this notice be preserved on
+ all copies.
+ */
+
+
+/* Definitions for device RasterOp implementations. */
+/* Requires gxdevmem.h, gsropt.h */
+
+#ifndef gdevmrop_INCLUDED
+# define gdevmrop_INCLUDED
+
+/*
+ * Define whether we implement transparency correctly, or whether we
+ * implement it as documented in the H-P manuals.
+ */
+#define TRANSPARENCY_PER_H_P
+
+/*
+ * Compute the effective RasterOp for the 1-bit case,
+ * taking transparency into account.
+ */
+gs_rop3_t gs_transparent_rop(P1(gs_logical_operation_t lop));
+
+#ifdef DEBUG
+/* Trace a [strip_]copy_rop call. */
+void trace_copy_rop(P16(const char *cname, gx_device * dev,
+ const byte * sdata, int sourcex, uint sraster,
+ gx_bitmap_id id, const gx_color_index * scolors,
+ const gx_strip_bitmap * textures,
+ const gx_color_index * tcolors,
+ int x, int y, int width, int height,
+ int phase_x, int phase_y, gs_logical_operation_t lop));
+#endif
+
+/* Define the implementations of RasterOp for memory devices. */
+
+
+/*
+ * PostScript colors normally act as the texture for RasterOp, with a null
+ * (all zeros) source. For images with CombineWithColor = true, we need
+ * a way to use the image data as the source. We implement this with a
+ * device that applies RasterOp with a specified texture to drawing
+ * operations, treating the drawing color as source rather than texture.
+ * The texture is a gx_device_color; it may be any type of color, even a
+ * pattern.
+ */
+#ifndef gx_device_color_DEFINED
+# define gx_device_color_DEFINED
+typedef struct gx_device_color_s gx_device_color;
+#endif
+
+#ifndef gx_device_rop_texture_DEFINED
+# define gx_device_rop_texture_DEFINED
+typedef struct gx_device_rop_texture_s gx_device_rop_texture;
+#endif
+
+struct gx_device_rop_texture_s {
+ gx_device_forward_common;
+ gs_logical_operation_t log_op;
+ gx_device_color texture;
+};
+
+#define private_st_device_rop_texture() /* in gdevrops.c */\
+ gs_private_st_composite_use_final(st_device_rop_texture,\
+ gx_device_rop_texture, "gx_device_rop_texture",\
+ device_rop_texture_enum_ptrs, device_rop_texture_reloc_ptrs,\
+ gx_device_finalize)
+
+/* Create a RasterOp source device. */
+int gx_alloc_rop_texture_device(P3(gx_device_rop_texture ** prsdev,
+ gs_memory_t * mem,
+ client_name_t cname));
+
+/* Initialize a RasterOp source device. */
+void gx_make_rop_texture_device(P4(gx_device_rop_texture * rsdev,
+ gx_device * target,
+ gs_logical_operation_t lop,
+ const gx_device_color * texture));
+
+#endif /* gdevmrop_INCLUDED */
diff --git a/gs/src/ansi2knr.c b/gs/src/ansi2knr.c
index cff4ac330..d32587cf0 100644
--- a/gs/src/ansi2knr.c
+++ b/gs/src/ansi2knr.c
@@ -37,21 +37,21 @@ program under the GPL.
* There are no error messages.
*
* ansi2knr recognizes function definitions by seeing a non-keyword
- * identifier at the left margin, followed by a left parenthesis,
- * with a right parenthesis as the last character on the line,
- * and with a left brace as the first token on the following line
- * (ignoring possible intervening comments), except that a line
+ * identifier at the left margin, followed by a left parenthesis, with a
+ * right parenthesis as the last character on the line, and with a left
+ * brace as the first token on the following line (ignoring possible
+ * intervening comments and/or preprocessor directives), except that a line
* consisting of only
* identifier1(identifier2)
* will not be considered a function definition unless identifier2 is
* the word "void", and a line consisting of
* identifier1(identifier2, <<arbitrary>>)
* will not be considered a function definition.
- * ansi2knr will recognize a multi-line header provided
- * that no intervening line ends with a left or right brace or a semicolon.
- * These algorithms ignore whitespace and comments, except that
- * the function name must be the first thing on the line.
- * The following constructs will confuse it:
+ * ansi2knr will recognize a multi-line header provided that no intervening
+ * line ends with a left or right brace or a semicolon. These algorithms
+ * ignore whitespace, comments, and preprocessor directives, except that
+ * the function name must be the first thing on the line. The following
+ * constructs will confuse it:
* - Any other construct that starts at the left margin and
* follows the above syntax (such as a macro or function call).
* - Some macros that tinker with the syntax of function headers.
@@ -61,6 +61,8 @@ program under the GPL.
* The original and principal author of ansi2knr is L. Peter Deutsch
* <ghost@aladdin.com>. Other authors are noted in the change history
* that follows (in reverse chronological order):
+ lpd 1999-08-17 added code to allow preprocessor directives
+ wherever comments are allowed
lpd 1999-04-12 added minor fixes from Pavel Roskin
<pavel_roskin@geocities.com> for clean compilation with
gcc -W -Wall
@@ -196,6 +198,8 @@ program under the GPL.
#define isidfirstchar(ch) (is_alpha(ch) || (ch) == '_')
/* Forward references */
+char *ppdirforward();
+char *ppdirbackward();
char *skipspace();
char *scanstring();
int writeblanks();
@@ -298,7 +302,7 @@ f: if ( line >= buf + (bufsize - 1) ) /* overflow check */
goto wl;
if ( fgets(line, (unsigned)(buf + bufsize - line), in) == NULL )
goto wl;
- switch ( *skipspace(more, 1) )
+ switch ( *skipspace(ppdirforward(more), 1) )
{
case '{':
/* Definitely a function header. */
@@ -349,32 +353,70 @@ wl: fputs(buf, out);
return 0;
}
-/* Skip over whitespace and comments, in either direction. */
+/*
+ * Skip forward or backward over one or more preprocessor directives.
+ */
+char *
+ppdirforward(p)
+ char *p;
+{
+ for (; *p == '#'; ++p) {
+ for (; *p != '\r' && *p != '\n'; ++p)
+ if (*p == 0)
+ return p;
+ if (*p == '\r' && p[1] == '\n')
+ ++p;
+ }
+ return p;
+}
+char *
+ppdirbackward(p, limit)
+ char *p;
+ char *limit;
+{
+ char *np = p;
+
+ for (;; p = --np) {
+ if (*np == '\n' && np[-1] == '\r')
+ --np;
+ for (; np > limit && np[-1] != '\r' && np[-1] != '\n'; --np)
+ if (np[-1] == 0)
+ return np;
+ if (*np != '#')
+ return p;
+ }
+}
+
+/*
+ * Skip over whitespace, comments, and preprocessor directives,
+ * in either direction.
+ */
char *
skipspace(p, dir)
- register char *p;
- register int dir; /* 1 for forward, -1 for backward */
-{ for ( ; ; )
- { while ( is_space(*p) )
- p += dir;
- if ( !(*p == '/' && p[dir] == '*') )
- break;
- p += dir; p += dir;
- while ( !(*p == '*' && p[dir] == '/') )
- { if ( *p == 0 )
- return p; /* multi-line comment?? */
- p += dir;
- }
- p += dir; p += dir;
- }
- return p;
+ char *p;
+ int dir; /* 1 for forward, -1 for backward */
+{
+ for ( ; ; ) {
+ while ( is_space(*p) )
+ p += dir;
+ if ( !(*p == '/' && p[dir] == '*') )
+ break;
+ p += dir; p += dir;
+ while ( !(*p == '*' && p[dir] == '/') ) {
+ if ( *p == 0 )
+ return p; /* multi-line comment?? */
+ p += dir;
+ }
+ p += dir; p += dir;
+ }
+ return p;
}
/* Scan over a quoted string, in either direction. */
char *
scanstring(p, dir)
- register char *p;
- register int dir;
+ char *p;
+ int dir;
{
for (p += dir; ; p += dir)
if (*p == '"' && p[-dir] != '\\')
@@ -412,14 +454,14 @@ writeblanks(start, end)
int
test1(buf)
char *buf;
-{ register char *p = buf;
+{ char *p = buf;
char *bend;
char *endfn;
int contin;
if ( !isidfirstchar(*p) )
return 0; /* no name at left margin */
- bend = skipspace(buf + strlen(buf) - 1, -1);
+ bend = skipspace(ppdirbackward(buf + strlen(buf) - 1, buf), -1);
switch ( *bend )
{
case ';': contin = 0 /*2*/; break;
@@ -498,7 +540,7 @@ convert1(buf, out, header, convert_varargs)
int header; /* Boolean */
int convert_varargs; /* Boolean */
{ char *endfn;
- register char *p;
+ char *p;
/*
* The breaks table contains pointers to the beginning and end
* of each argument.
diff --git a/gs/src/bcwin32.mak b/gs/src/bcwin32.mak
index 879264bb9..19da27fff 100644
--- a/gs/src/bcwin32.mak
+++ b/gs/src/bcwin32.mak
@@ -199,7 +199,7 @@ SYNC=winsync
# Choose the language feature(s) to include. See gs.mak for details.
-FEATURE_DEVS=$(PSD)psl3.dev $(PSD)pdf.dev $(PSD)dpsnext.dev $(PSD)ttfont.dev
+FEATURE_DEVS=$(PSD)psl3.dev $(PSD)pdf.dev $(PSD)dpsnext.dev $(PSD)ttfont.dev $(PSD)mshandle.dev $(PSD)pipe.dev
# Choose whether to compile the .ps initialization files into the executable.
# See gs.mak for details.
@@ -277,9 +277,11 @@ PCFBASM=
dosdefault: default $(BINDIR)\gs16spl.exe
-# Define the switch for output files.
+# Define the switches for the compilers.
+C_=-c
O_=-o
+RO_=-fo
# Define the compilation flags.
@@ -365,6 +367,7 @@ CC_=$(CC_WX) $(CO)
CC_D=$(CC_WX)
CC_INT=$(CC_WX)
CC_LEAF=$(CC_)
+CC_NO_WARN=$(CC_)
# No additional flags are needed for Windows compilation.
CCWINFLAGS=
@@ -373,8 +376,8 @@ CCWINFLAGS=
# nmake expands macros when encountered, not when used,
# so this must precede the !include statements.
-# ****** HACK ****** *.tr and *.map are still created in the current directory.
-BEGINFILES2=$(BINDIR)\gs16spl.exe *.tr *.map
+# ****** HACK ****** *.tr is still created in the current directory.
+BEGINFILES2=$(BINDIR)\gs16spl.exe *.tr
# Include the generic makefiles.
@@ -437,7 +440,7 @@ $(GS_XE): $(GSDLL_DLL) $(DWOBJ) $(GSCONSOLE_XE)\
$(LINK) /Tpe $(LCT) @&&!
$(LIBDIR)\c0w32 +
$(DWOBJ) +
-,$(GS_XE),$(GS), +
+,$(GS_XE),$(GLOBJ)$(GS), +
$(LIBDIR)\import32 +
$(LIBDIR)\cw32, +
$(GLSRCDIR)\dwmain32.def, +
@@ -449,7 +452,7 @@ $(GSCONSOLE_XE): $(OBJC) $(GS_OBJ).res $(GLSRCDIR)\dw32c.def
$(LINK) /Tpe /ap $(LCT) $(DEBUGLINK) @&&!
$(LIBDIR)\c0w32 +
$(OBJC) +
-,$(GSCONSOLE_XE),$(GSCONSOLE), +
+,$(GSCONSOLE_XE),$(GLOBJ)$(GSCONSOLE), +
$(LIBDIR)\import32 +
$(LIBDIR)\cw32, +
$(GLSRCDIR)\dw32c.def, +
@@ -462,7 +465,7 @@ $(GSDLL_DLL): $(GS_ALL) $(DEVS_ALL) $(GLOBJ)gsdll.$(OBJ)\
-del $(GLGEN)gswin32.tr
copy $(ld_tr) $(GLGEN)gswin32.tr
echo $(LIBDIR)\c0d32 $(GLOBJ)gsdll + >> $(GLGEN)gswin32.tr
- $(LINK) $(LCT) /Tpd @$(GLGEN)gswin32.tr $(INTASM) ,$(GSDLL_DLL),$(GSDLL),@$(GLGENDIR)\lib.tr @$(LIBCTR),$(GLSRCDIR)\gsdll32.def,$(GSDLL_OBJ).res
+ $(LINK) $(LCT) /Tpd @$(GLGEN)gswin32.tr $(INTASM) ,$(GSDLL_DLL),$(GLOBJ)$(GSDLL),@$(GLGENDIR)\lib.tr @$(LIBCTR),$(GLSRCDIR)\gsdll32.def,$(GSDLL_OBJ).res
!else
# The big graphical EXE
@@ -472,7 +475,7 @@ $(GS_XE): $(GSCONSOLE_XE) $(GS_ALL) $(DEVS_ALL)\
copy $(ld_tr) $(GLGEN)gswin32.tr
echo $(LIBDIR)\c0w32 $(GLOBJ)gsdll + >> $(GLGEN)gswin32.tr
echo $(DWOBJNO) $(INTASM) >> $(GLGEN)gswin32.tr
- $(LINK) $(LCT) /Tpe @$(GLGEN)gswin32.tr ,$(GS_XE),$(GS),@$(GLGENDIR)\lib.tr @$(LIBCTR),$(GLSRCDIR)\dwmain32.def,$(GS_OBJ).res
+ $(LINK) $(LCT) /Tpe @$(GLGEN)gswin32.tr ,$(GS_XE),$(GLOBJ)$(GS),@$(GLGENDIR)\lib.tr @$(LIBCTR),$(GLSRCDIR)\dwmain32.def,$(GS_OBJ).res
# The big console mode EXE
$(GSCONSOLE_XE): $(GS_ALL) $(DEVS_ALL)\
@@ -481,7 +484,7 @@ $(GSCONSOLE_XE): $(GS_ALL) $(DEVS_ALL)\
copy $(ld_tr) $(GLGEN)gswin32.tr
echo $(LIBDIR)\c0w32 $(GLOBJ)gsdll + >> $(GLGEN)gswin32.tr
echo $(OBJCNO) $(INTASM) >> $(GLGEN)gswin32.tr
- $(LINK) $(LCT) /Tpe /ap @$(GLGEN)gswin32.tr ,$(GSCONSOLE_XE),$(GSCONSOLE),@$(GLGENDIR)\lib.tr @$(LIBCTR),$(GLSRCDIR)\dw32c.def,$(GS_OBJ).res
+ $(LINK) $(LCT) /Tpe /ap @$(GLGEN)gswin32.tr ,$(GSCONSOLE_XE),$(GLOBJ)$(GSCONSOLE),@$(GLGENDIR)\lib.tr @$(LIBCTR),$(GLSRCDIR)\dw32c.def,$(GS_OBJ).res
!endif
# Access to 16 spooler from Win32s
diff --git a/gs/src/bfont.h b/gs/src/bfont.h
index 55967ce02..3a79f941c 100644
--- a/gs/src/bfont.h
+++ b/gs/src/bfont.h
@@ -26,7 +26,8 @@
#include "ifont.h"
/* In zfont.c */
-int add_FID(P3(i_ctx_t *i_ctx_p, ref * pfdict, gs_font * pfont));
+int add_FID(P4(i_ctx_t *i_ctx_p, ref *pfdict, gs_font *pfont,
+ gs_ref_memory_t *imem));
font_proc_make_font(zdefault_make_font);
font_proc_make_font(zbase_make_font);
@@ -66,5 +67,6 @@ int build_gs_font(P7(i_ctx_t *, os_ptr, gs_font **, font_type,
gs_memory_type_ptr_t, const build_proc_refs *,
build_font_options_t));
int define_gs_font(P1(gs_font *));
+gs_glyph zfont_encode_char(P3(gs_font *pfont, gs_char chr, gs_glyph_space_t ignored));
#endif /* bfont_INCLUDED */
diff --git a/gs/src/ccfont.h b/gs/src/ccfont.h
index f700595ff..d8003a692 100644
--- a/gs/src/ccfont.h
+++ b/gs/src/ccfont.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1992, 1995, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1992, 1995, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -62,23 +62,26 @@ typedef struct {
/* (only used for string dicts) */
} cfont_dict_keys;
-/* We pass a procedure vector to the font initialization routine */
-/* to avoid having externs, which compromise sharability. */
+/*
+ * We pass a procedure vector to the font initialization routine
+ * to avoid having externs, which compromise sharability.
+ */
typedef struct cfont_procs_s {
- int (*ref_dict_create) (P4(ref *, const cfont_dict_keys *,
+ int (*ref_dict_create) (P5(i_ctx_t *, ref *, const cfont_dict_keys *,
cfont_string_array, const ref *));
- int (*string_dict_create) (P4(ref *, const cfont_dict_keys *,
+ int (*string_dict_create) (P5(i_ctx_t *, ref *, const cfont_dict_keys *,
cfont_string_array,
cfont_string_array));
- int (*num_dict_create) (P5(ref *, const cfont_dict_keys *,
+ int (*num_dict_create) (P6(i_ctx_t *, ref *, const cfont_dict_keys *,
cfont_string_array, const ref *,
const char *));
- int (*name_array_create) (P3(ref *, cfont_string_array, int));
- int (*string_array_create) (P4(ref *, cfont_string_array,
- int /*size */ ,
- uint /*protection */ ));
- int (*name_create) (P2(ref *, const char *));
- int (*ref_from_string) (P3(ref *, const char *, uint));
+ int (*name_array_create) (P4(i_ctx_t *, ref *, cfont_string_array, int));
+ int (*string_array_create) (P5(i_ctx_t *, ref *, cfont_string_array,
+ int /*size */ , uint /*protection */ ));
+ int (*scalar_array_create) (P5(i_ctx_t *, ref *, const ref *,
+ int /*size */ , uint /*protection */ ));
+ int (*name_create) (P3(i_ctx_t *, ref *, const char *));
+ int (*ref_from_string) (P4(i_ctx_t *, ref *, const char *, uint));
} cfont_procs;
/*
@@ -87,7 +90,7 @@ typedef struct cfont_procs_s {
* a tiny procedural interface for getting access to the compiled font table.
*/
#define ccfont_proc(proc)\
- int proc(P2(const cfont_procs *, ref *))
+ int proc(P3(i_ctx_t *, const cfont_procs *, ref *))
typedef ccfont_proc((*ccfont_fproc));
/*
@@ -96,6 +99,6 @@ typedef ccfont_proc((*ccfont_fproc));
*/
extern int ccfont_fprocs(P2(int *, const ccfont_fproc **));
-#define ccfont_version 18 /* for checking against libraries */
+#define ccfont_version 19 /* for checking against libraries */
#endif /* ccfont_INCLUDED */
diff --git a/gs/src/contrib.mak b/gs/src/contrib.mak
index e6553b2c7..c9818b5cf 100644
--- a/gs/src/contrib.mak
+++ b/gs/src/contrib.mak
@@ -34,8 +34,6 @@ CONTRIB_MAK=$(GLSRC)contrib.mak
# * att3b1 AT&T 3b1/Unixpc monochrome display [3b1 only]
# * sonyfb Sony Microsystems monochrome display [Sony only]
# * sunview SunView window system [SunOS only]
-# Platform-independent:
-# * sxlcrt CRT sixels, e.g. for VT240-like terminals
# Printers:
# * ap3250 Epson AP3250 printer
# * appledmp Apple Dot Matrix Printer (should also work with Imagewriter)
@@ -59,7 +57,6 @@ CONTRIB_MAK=$(GLSRC)contrib.mak
# * declj250 alternate DEC LJ250 driver
# * djet500c H-P DeskJet 500C alternate driver
# (does not work on 550C or 560C)
-# * dl2100 DEC DEClaser 2100 printer
# * dnj650c H-P DesignJet 650C
# epson Epson-compatible dot matrix printers (9- or 24-pin)
# * eps9mid Epson-compatible 9-pin, interleaved lines
@@ -74,14 +71,9 @@ CONTRIB_MAK=$(GLSRC)contrib.mak
# * iwlo Apple Imagewriter in low-resolution mode
# * iwlq Apple Imagewriter LQ in 320 x 216 dpi mode
# * jetp3852 IBM Jetprinter ink-jet color printer (Model #3852)
-# * la50 DEC LA50 printer
-# * la70 DEC LA70 printer
# * la70t DEC LA70 printer with low-resolution text enhancement
-# * la75 DEC LA75 printer
-# * la75plus DEC LA75plus printer
# * lbp8 Canon LBP-8II laser printer
# * lips3 Canon LIPS III laser printer in English (CaPSL) mode
-# * ln03 DEC LN03 printer
# * lj250 DEC LJ250 Companion color printer
# * lj3100sw H-P LaserJet 3100 (requires installed HP-Software)
# + lj4dith H-P LaserJet 4 with Floyd-Steinberg dithering
@@ -111,7 +103,6 @@ CONTRIB_MAK=$(GLSRC)contrib.mak
# * tek4696 Tektronix 4695/4696 inkjet plotter
# * uniprint Unified printer driver -- Configurable Color ESC/P-,
# ESC/P2-, HP-RTL/PCL mono/color driver
-# * xes Xerox XES printers (2700, 3700, 4045, etc.)
# Fax systems:
# * dfaxhigh DigiBoard, Inc.'s DigiFAX software format (high resolution)
# * dfaxlow DigiFAX low (normal) resolution
@@ -193,16 +184,6 @@ $(GLOBJ)gdevsun.$(OBJ) : $(GLSRC)gdevsun.c $(GDEV) $(malloc__h)\
$(gscdefs_h) $(gserrors_h) $(gsmatrix_h)
$(GLCC) $(GLO_)gdevsun.$(OBJ) $(C_) $(GLSRC)gdevsun.c
-### ------------------------- DEC sixel displays ------------------------ ###
-### Note: this driver was contributed by a user: please contact ###
-### Phil Keegstra (keegstra@tonga.gsfc.nasa.gov) if you have questions. ###
-
-# This is a "printer" device, but it probably shouldn't be.
-# I don't know why the implementor chose to do it this way.
-sxlcrt_=$(GLOBJ)gdevln03.$(OBJ)
-$(DD)sxlcrt.dev : $(sxlcrt_) $(DD)page.dev
- $(SETPDEV) $(DD)sxlcrt $(sxlcrt_)
-
###### --------------- Memory-buffered printer devices --------------- ######
### --------------------- The Apple printer devices --------------------- ###
@@ -568,38 +549,6 @@ $(GLOBJ)gdevlbp8.$(OBJ) : $(GLSRC)gdevlbp8.c $(PDEVH)
$(GLCC) $(GLO_)gdevlbp8.$(OBJ) $(C_) $(GLSRC)gdevlbp8.c
### -------- The DEC LN03/DL2100/LA50/LA70/LA75 printer devices -------- ###
-### Note: this driver was contributed by users: please contact ###
-### Ulrich Mueller (ulm@vsnhd1.cern.ch) if you have questions. ###
-### For questions about the DEClaser 2100, please contact ###
-### Nick Brown (nick.brown@coe.int). ###
-### For questions about LA50 and LA75, please contact ###
-### Ian MacPhedran (macphed@dvinci.USask.CA). ###
-### For questions about the LA70, please contact ###
-### Bruce Lowekamp (lowekamp@csugrad.cs.vt.edu). ###
-### For questions about the LA75plus, please contact ###
-### Andre' Beck (Andre_Beck@IRS.Inf.TU-Dresden.de). ###
-
-ln03_=$(GLOBJ)gdevln03.$(OBJ)
-$(DD)ln03.dev : $(ln03_) $(DD)page.dev
- $(SETPDEV) $(DD)ln03 $(ln03_)
-
-$(DD)dl2100.dev : $(ln03_) $(DD)page.dev
- $(SETPDEV) $(DD)dl2100 $(ln03_)
-
-$(DD)la50.dev : $(ln03_) $(DD)page.dev
- $(SETPDEV) $(DD)la50 $(ln03_)
-
-$(DD)la70.dev : $(ln03_) $(DD)page.dev
- $(SETPDEV) $(DD)la70 $(ln03_)
-
-$(DD)la75.dev : $(ln03_) $(DD)page.dev
- $(SETPDEV) $(DD)la75 $(ln03_)
-
-$(DD)la75plus.dev : $(ln03_) $(DD)page.dev
- $(SETPDEV) $(DD)la75plus $(ln03_)
-
-$(GLOBJ)gdevln03.$(OBJ) : $(GLSRC)gdevln03.c $(PDEVH)
- $(GLCC) $(GLO_)gdevln03.$(OBJ) $(C_) $(GLSRC)gdevln03.c
# LA70 driver with low-resolution text enhancement.
@@ -759,17 +708,6 @@ $(DD)tek4696.dev : $(tek4696_) $(DD)page.dev
$(GLOBJ)gdevtknk.$(OBJ) : $(GLSRC)gdevtknk.c $(PDEVH) $(malloc__h)
$(GLCC) $(GLO_)gdevtknk.$(OBJ) $(C_) $(GLSRC)gdevtknk.c
-### ----------------- The Xerox XES printer device --------------------- ###
-### Note: this driver was contributed by users: please contact ###
-### Peter Flass (flass@lbdrscs.bitnet) if you have questions. ###
-
-xes_=$(GLOBJ)gdevxes.$(OBJ)
-$(DD)xes.dev : $(xes_) $(DD)page.dev
- $(SETPDEV) $(DD)xes $(xes_)
-
-$(GLOBJ)gdevxes.$(OBJ) : $(GLSRC)gdevxes.c $(PDEVH)
- $(GLCC) $(GLO_)gdevxes.$(OBJ) $(C_) $(GLSRC)gdevxes.c
-
###### ------------------------- Fax devices ------------------------- ######
### ------------------------- The DigiFAX device ------------------------ ###
@@ -789,7 +727,8 @@ $(DD)dfaxhigh.dev : $(dfax_) $(DD)tfax.dev
$(SETDEV) $(DD)dfaxhigh $(dfax_)
$(ADDMOD) $(GLGEN)dfaxhigh -include $(DD)tfax
-$(GLOBJ)gdevdfax.$(OBJ) : $(GLSRC)gdevdfax.c $(PDEVH) $(scfx_h) $(strimpl_h)
+$(GLOBJ)gdevdfax.$(OBJ) : $(GLSRC)gdevdfax.c $(PDEVH)\
+ $(gdevtfax_h) $(scfx_h) $(strimpl_h)
$(GLCC) $(GLO_)gdevdfax.$(OBJ) $(C_) $(GLSRC)gdevdfax.c
###### --------------------- Raster file formats --------------------- ######
diff --git a/gs/src/devs.mak b/gs/src/devs.mak
index 5331f7f2a..7bd91f12a 100644
--- a/gs/src/devs.mak
+++ b/gs/src/devs.mak
@@ -127,6 +127,7 @@ GDEV=$(AK) $(ECHOGS_XE) $(GDEVH)
# bitrgb Plain bits, RGB
# bitcmyk Plain bits, CMYK
# bmpmono Monochrome MS Windows .BMP file format
+# bmpgray 8-bit gray .BMP file format
# bmpsep1 Separated 1-bit CMYK .BMP file format, primarily for testing
# bmpsep8 Separated 8-bit CMYK .BMP file format, primarily for testing
# bmp16 4-bit (EGA/VGA) .BMP file format
@@ -300,10 +301,10 @@ $(GLOBJ)gdevpcfb.$(OBJ) : $(GLSRC)gdevpcfb.c $(GDEV) $(memory__h) $(gconfigv_h)\
# The EGA/VGA family includes EGA and VGA. Many SuperVGAs in 800x600,
# 16-color mode can share the same code; see the next section below.
-$(DD)ega.dev : $(EGAVGA)
+$(DD)ega.dev : $(DEVS_MAK) $(EGAVGA)
$(SETDEV) $(DD)ega $(EGAVGA)
-$(DD)vga.dev : $(EGAVGA)
+$(DD)vga.dev : $(DEVS_MAK) $(EGAVGA)
$(SETDEV) $(DD)vga $(EGAVGA)
### ------------------------- SuperVGA displays ------------------------ ###
@@ -315,7 +316,7 @@ $(DD)vga.dev : $(EGAVGA)
# where NNN is the display mode in decimal. See Use.htm for the modes
# for some popular display chipsets.
-$(DD)svga16.dev : $(EGAVGA)
+$(DD)svga16.dev : $(DEVS_MAK) $(EGAVGA)
$(SETDEV) $(DD)svga16 $(EGAVGA)
# More capable SuperVGAs have a wide variety of slightly differing
@@ -331,28 +332,28 @@ $(GLOBJ)gdevsvga.$(OBJ) : $(GLSRC)gdevsvga.c $(GDEV) $(memory__h) $(gconfigv_h)\
# The SuperVGA family includes: Avance Logic Inc., ATI Wonder, S3,
# Trident, Tseng ET3000/4000, and VESA.
-$(DD)ali.dev : $(SVGA)
+$(DD)ali.dev : $(DEVS_MAK) $(SVGA)
$(SETDEV) $(DD)ali $(SVGA)
-$(DD)atiw.dev : $(SVGA)
+$(DD)atiw.dev : $(DEVS_MAK) $(SVGA)
$(SETDEV) $(DD)atiw $(SVGA)
-$(DD)cirr.dev : $(SVGA)
+$(DD)cirr.dev : $(DEVS_MAK) $(SVGA)
$(SETDEV) $(DD)cirr $(SVGA)
-$(DD)tseng.dev : $(SVGA)
+$(DD)tseng.dev : $(DEVS_MAK) $(SVGA)
$(SETDEV) $(DD)tseng $(SVGA)
-$(DD)tvga.dev : $(SVGA)
+$(DD)tvga.dev : $(DEVS_MAK) $(SVGA)
$(SETDEV) $(DD)tvga $(SVGA)
-$(DD)vesa.dev : $(SVGA)
+$(DD)vesa.dev : $(DEVS_MAK) $(SVGA)
$(SETDEV) $(DD)vesa $(SVGA)
# The S3 driver doesn't share much code with the others.
s3vga_=$(GLOBJ)gdevs3ga.$(OBJ) $(GLOBJ)gdevsvga.$(OBJ) $(GLOBJ)gdevpccm.$(OBJ)
-$(DD)s3vga.dev : $(SVGA) $(s3vga_)
+$(DD)s3vga.dev : $(DEVS_MAK) $(SVGA) $(s3vga_)
$(SETDEV) $(DD)s3vga $(SVGA)
$(ADDMOD) $(DD)s3vga -obj $(s3vga_)
@@ -370,7 +371,7 @@ $(GLOBJ)gdevs3ga.$(OBJ) : $(GLSRC)gdevs3ga.c $(GDEV) $(gdevpcfb_h) $(gdevsvga_h)
### Erik Talvola (talvola@gnu.ai.mit.edu). ###
lvga256_=$(GLOBJ)gdevl256.$(OBJ)
-$(DD)lvga256.dev : $(lvga256_)
+$(DD)lvga256.dev : $(DEVS_MAK) $(lvga256_)
$(SETDEV) $(DD)lvga256 $(lvga256_)
$(ADDMOD) $(DD)lvga256 -lib vga vgagl
@@ -378,7 +379,7 @@ $(GLOBJ)gdevl256.$(OBJ) : $(GLSRC)gdevl256.c $(GDEV)
$(GLCC) $(GLO_)gdevl256.$(OBJ) $(C_) $(GLSRC)gdevl256.c
vgalib_=$(GLOBJ)gdevvglb.$(OBJ) $(GLOBJ)gdevpccm.$(OBJ)
-$(DD)vgalib.dev : $(vgalib_)
+$(DD)vgalib.dev : $(DEVS_MAK) $(vgalib_)
$(SETDEV2) $(DD)vgalib $(vgalib_)
$(ADDMOD) $(DD)vgalib -lib vga
@@ -393,33 +394,39 @@ $(GLOBJ)gdevvglb.$(OBJ) : $(GLSRC)gdevvglb.c $(GDEV) $(gdevpccm_h) $(gsparam_h)
x__h=$(GLSRC)x_.h
gdevxcmp_h=$(GLSRC)gdevxcmp.h
-gdevx_h=$(GLSRC)gdevx.h $(gdevxcmp_h)
+gdevx_h=$(GLSRC)gdevx.h $(gdevbbox_h) $(gdevxcmp_h)
# See the main makefile for the definition of XLIBS.
-x11_=$(GLOBJ)gdevx.$(OBJ) $(GLOBJ)gdevxcmp.$(OBJ) $(GLOBJ)gdevxini.$(OBJ) $(GLOBJ)gdevxres.$(OBJ) $(GLOBJ)gdevxxf.$(OBJ) $(GLOBJ)gdevemap.$(OBJ)
-$(DD)x11_.dev : $(x11_)
+x11_=$(GLOBJ)gdevx.$(OBJ) $(GLOBJ)gdevxcmp.$(OBJ) $(GLOBJ)gdevxini.$(OBJ)\
+ $(GLOBJ)gdevxres.$(OBJ) $(GLOBJ)gdevxxf.$(OBJ)\
+ $(GLOBJ)gdevemap.$(OBJ) $(GLOBJ)gsparamx.$(OBJ)
+$(DD)x11_.dev : $(DEVS_MAK) $(x11_) $(GLD)bbox.dev
$(SETMOD) $(DD)x11_ $(x11_)
$(ADDMOD) $(DD)x11_ -lib $(XLIBS)
+ $(ADDMOD) $(DD)x11_ -include $(GLD)bbox
-$(DD)x11.dev : $(DD)x11_.dev
+$(DD)x11.dev : $(DEVS_MAK) $(DD)x11_.dev
$(SETDEV2) $(DD)x11 -include $(DD)x11_
# See the main makefile for the definition of XINCLUDE.
GDEVX=$(GDEV) $(x__h) $(gdevx_h) $(TOP_MAKEFILES)
$(GLOBJ)gdevx.$(OBJ) : $(GLSRC)gdevx.c $(GDEVX) $(math__h) $(memory__h)\
$(gscoord_h) $(gsdevice_h) $(gsiparm2_h) $(gsmatrix_h) $(gsparam_h)\
- $(gxgetbit_h) $(gxiparam_h) $(gxpath_h)
+ $(gxdevmem_h) $(gxgetbit_h) $(gxiparam_h) $(gxpath_h)
$(GLCC) $(XINCLUDE) $(GLO_)gdevx.$(OBJ) $(C_) $(GLSRC)gdevx.c
$(GLOBJ)gdevxcmp.$(OBJ) : $(GLSRC)gdevxcmp.c $(GDEVX) $(math__h)
$(GLCC) $(XINCLUDE) $(GLO_)gdevxcmp.$(OBJ) $(C_) $(GLSRC)gdevxcmp.c
$(GLOBJ)gdevxini.$(OBJ) : $(GLSRC)gdevxini.c $(GDEVX) $(memory__h)\
- $(gserrors_h)
+ $(gserrors_h) $(gsparamx_h) $(gxdevmem_h) $(gdevbbox_h)
$(GLCC) $(XINCLUDE) $(GLO_)gdevxini.$(OBJ) $(C_) $(GLSRC)gdevxini.c
-$(GLOBJ)gdevxres.$(OBJ) : $(GLSRC)gdevxres.c $(GDEVX) $(std_h)
- $(GLCC) $(XINCLUDE) $(GLO_)gdevxres.$(OBJ) $(C_) $(GLSRC)gdevxres.c
+# We have to compile gdevxres without warnings, because there is a
+# const/non-const cast required by the X headers that we can't work around.
+$(GLOBJ)gdevxres.$(OBJ) : $(GLSRC)gdevxres.c $(std_h) $(x__h)\
+ $(gsmemory_h) $(gstypes_h) $(gxdevice_h) $(gdevx_h)
+ $(CC_NO_WARN) $(GLCCFLAGS) $(XINCLUDE) $(GLO_)gdevxres.$(OBJ) $(C_) $(GLSRC)gdevxres.c
$(GLOBJ)gdevxxf.$(OBJ) : $(GLSRC)gdevxxf.c $(GDEVX) $(math__h) $(memory__h)\
$(gsstruct_h) $(gsutil_h) $(gxxfont_h)
@@ -434,37 +441,37 @@ $(GLOBJ)gdevxxf.$(OBJ) : $(GLSRC)gdevxxf.c $(GDEVX) $(math__h) $(memory__h)\
# x11gray2 pretends to be a 2-bit gray-scale device.
# x11gray4 pretends to be a 4-bit gray-scale device.
# x11mono pretends to be a black-and-white device.
-x11alt_=$(GLOBJ)gdevxalt.$(OBJ) $(GLOBJ)gdevdcrd.$(OBJ)
-$(DD)x11alt_.dev : $(x11alt_) $(DD)x11_.dev
+x11alt_=$(GLOBJ)gdevxalt.$(OBJ)
+$(DD)x11alt_.dev : $(DEVS_MAK) $(x11alt_) $(DD)x11_.dev
$(SETMOD) $(DD)x11alt_ $(x11alt_)
$(ADDMOD) $(DD)x11alt_ -include $(DD)x11_
-$(DD)x11alpha.dev : $(DD)x11alt_.dev
+$(DD)x11alpha.dev : $(DEVS_MAK) $(DD)x11alt_.dev
$(SETDEV2) $(DD)x11alpha -include $(DD)x11alt_
-$(DD)x11cmyk.dev : $(DD)x11alt_.dev
+$(DD)x11cmyk.dev : $(DEVS_MAK) $(DD)x11alt_.dev
$(SETDEV2) $(DD)x11cmyk -include $(DD)x11alt_
-$(DD)x11cmyk2.dev : $(DD)x11alt_.dev
+$(DD)x11cmyk2.dev : $(DEVS_MAK) $(DD)x11alt_.dev
$(SETDEV2) $(DD)x11cmyk2 -include $(DD)x11alt_
-$(DD)x11cmyk4.dev : $(DD)x11alt_.dev
+$(DD)x11cmyk4.dev : $(DEVS_MAK) $(DD)x11alt_.dev
$(SETDEV2) $(DD)x11cmyk4 -include $(DD)x11alt_
-$(DD)x11cmyk8.dev : $(DD)x11alt_.dev
+$(DD)x11cmyk8.dev : $(DEVS_MAK) $(DD)x11alt_.dev
$(SETDEV2) $(DD)x11cmyk8 -include $(DD)x11alt_
-$(DD)x11gray2.dev : $(DD)x11alt_.dev
+$(DD)x11gray2.dev : $(DEVS_MAK) $(DD)x11alt_.dev
$(SETDEV2) $(DD)x11gray2 -include $(DD)x11alt_
-$(DD)x11gray4.dev : $(DD)x11alt_.dev
+$(DD)x11gray4.dev : $(DEVS_MAK) $(DD)x11alt_.dev
$(SETDEV2) $(DD)x11gray4 -include $(DD)x11alt_
-$(DD)x11mono.dev : $(DD)x11alt_.dev
+$(DD)x11mono.dev : $(DEVS_MAK) $(DD)x11alt_.dev
$(SETDEV2) $(DD)x11mono -include $(DD)x11alt_
$(GLOBJ)gdevxalt.$(OBJ) : $(GLSRC)gdevxalt.c $(GDEVX) $(math__h) $(memory__h)\
- $(gsdevice_h) $(gsparam_h) $(gdevdcrd_h)
+ $(gsdevice_h) $(gsparam_h) $(gsstruct_h)
$(GLCC) $(XINCLUDE) $(GLO_)gdevxalt.$(OBJ) $(C_) $(GLSRC)gdevxalt.c
###### --------------- Memory-buffered printer devices --------------- ######
@@ -488,51 +495,51 @@ $(GLOBJ)gdevpcl.$(OBJ) : $(GLSRC)gdevpcl.c $(PDEVH) $(gdevpcl_h)
$(GLOBJ)gdevdjet.$(OBJ) : $(GLSRC)gdevdjet.c $(PDEVH) $(gdevpcl_h)
$(GLCC) $(GLO_)gdevdjet.$(OBJ) $(C_) $(GLSRC)gdevdjet.c
-$(DD)deskjet.dev : $(HPMONO) $(GLD)page.dev
+$(DD)deskjet.dev : $(DEVS_MAK) $(HPMONO) $(GLD)page.dev
$(SETPDEV2) $(DD)deskjet $(HPMONO)
-$(DD)djet500.dev : $(HPMONO) $(GLD)page.dev
+$(DD)djet500.dev : $(DEVS_MAK) $(HPMONO) $(GLD)page.dev
$(SETPDEV2) $(DD)djet500 $(HPMONO)
-$(DD)fs600.dev : $(HPMONO) $(GLD)page.dev
+$(DD)fs600.dev : $(DEVS_MAK) $(HPMONO) $(GLD)page.dev
$(SETPDEV2) $(DD)fs600 $(HPMONO)
-$(DD)laserjet.dev : $(HPMONO) $(GLD)page.dev
+$(DD)laserjet.dev : $(DEVS_MAK) $(HPMONO) $(GLD)page.dev
$(SETPDEV2) $(DD)laserjet $(HPMONO)
-$(DD)ljetplus.dev : $(HPMONO) $(GLD)page.dev
+$(DD)ljetplus.dev : $(DEVS_MAK) $(HPMONO) $(GLD)page.dev
$(SETPDEV2) $(DD)ljetplus $(HPMONO)
### Selecting ljet2p provides TIFF (mode 2) compression on LaserJet III,
### IIIp, IIId, IIIsi, IId, and IIp.
-$(DD)ljet2p.dev : $(HPMONO) $(GLD)page.dev
+$(DD)ljet2p.dev : $(DEVS_MAK) $(HPMONO) $(GLD)page.dev
$(SETPDEV2) $(DD)ljet2p $(HPMONO)
### Selecting ljet3 provides Delta Row (mode 3) compression on LaserJet III,
### IIIp, IIId, IIIsi.
-$(DD)ljet3.dev : $(HPMONO) $(GLD)page.dev
+$(DD)ljet3.dev : $(DEVS_MAK) $(HPMONO) $(GLD)page.dev
$(SETPDEV2) $(DD)ljet3 $(HPMONO)
### Selecting ljet3d also provides duplex printing capability.
-$(DD)ljet3d.dev : $(HPMONO) $(GLD)page.dev
+$(DD)ljet3d.dev : $(DEVS_MAK) $(HPMONO) $(GLD)page.dev
$(SETPDEV2) $(DD)ljet3d $(HPMONO)
### Selecting ljet4 or ljet4d also provides Delta Row compression on
### LaserJet IV series.
-$(DD)ljet4.dev : $(HPMONO) $(GLD)page.dev
+$(DD)ljet4.dev : $(DEVS_MAK) $(HPMONO) $(GLD)page.dev
$(SETPDEV2) $(DD)ljet4 $(HPMONO)
-$(DD)ljet4d.dev : $(HPMONO) $(GLD)page.dev
+$(DD)ljet4d.dev : $(DEVS_MAK) $(HPMONO) $(GLD)page.dev
$(SETPDEV2) $(DD)ljet4d $(HPMONO)
-$(DD)lp2563.dev : $(HPMONO) $(GLD)page.dev
+$(DD)lp2563.dev : $(DEVS_MAK) $(HPMONO) $(GLD)page.dev
$(SETPDEV2) $(DD)lp2563 $(HPMONO)
-$(DD)oce9050.dev : $(HPMONO) $(GLD)page.dev
+$(DD)oce9050.dev : $(DEVS_MAK) $(HPMONO) $(GLD)page.dev
$(SETPDEV2) $(DD)oce9050 $(HPMONO)
### -------------------- The H-P Color LaserJet 5/5M -------------------- ###
@@ -545,7 +552,7 @@ $(DD)oce9050.dev : $(HPMONO) $(GLD)page.dev
### Henry Stiles <henrys@meerkat.dimensional.com>
cljet5_=$(GLOBJ)gdevclj.$(OBJ) $(HPPCL)
-$(DD)cljet5.dev : $(cljet5_) $(GLD)page.dev
+$(DD)cljet5.dev : $(DEVS_MAK) $(cljet5_) $(GLD)page.dev
$(SETPDEV) $(DD)cljet5 $(cljet5_)
$(GLOBJ)gdevclj.$(OBJ) : $(GLSRC)gdevclj.c $(math__h) $(PDEVH)\
@@ -553,7 +560,7 @@ $(GLOBJ)gdevclj.$(OBJ) : $(GLSRC)gdevclj.c $(math__h) $(PDEVH)\
$(GLCC) $(GLO_)gdevclj.$(OBJ) $(C_) $(GLSRC)gdevclj.c
cljet5c_=$(GLOBJ)gdevcljc.$(OBJ) $(HPPCL)
-$(DD)cljet5c.dev : $(cljet5c_) $(GLD)page.dev
+$(DD)cljet5c.dev : $(DEVS_MAK) $(cljet5c_) $(GLD)page.dev
$(SETPDEV) $(DD)cljet5c $(cljet5c_)
$(GLOBJ)gdevcljc.$(OBJ) : $(GLSRC)gdevcljc.c $(math__h) $(PDEVH) $(gdevpcl_h)
@@ -574,10 +581,10 @@ gdevpxen_h=$(GLSRC)gdevpxen.h
gdevpxop_h=$(GLSRC)gdevpxop.h
ljet5_=$(GLOBJ)gdevlj56.$(OBJ) $(HPPCL)
-$(DD)lj5mono.dev : $(ljet5_) $(GLD)page.dev
+$(DD)lj5mono.dev : $(DEVS_MAK) $(ljet5_) $(GLD)page.dev
$(SETPDEV) $(DD)lj5mono $(ljet5_)
-$(DD)lj5gray.dev : $(ljet5_) $(GLD)page.dev
+$(DD)lj5gray.dev : $(DEVS_MAK) $(ljet5_) $(GLD)page.dev
$(SETPDEV) $(DD)lj5gray $(ljet5_)
$(GLOBJ)gdevlj56.$(OBJ) : $(GLSRC)gdevlj56.c $(PDEVH) $(gdevpcl_h)\
@@ -588,29 +595,32 @@ $(GLOBJ)gdevlj56.$(OBJ) : $(GLSRC)gdevlj56.c $(PDEVH) $(gdevpcl_h)\
# Support for PostScript and PDF
-gdevpsdf_h=$(GLSRC)gdevpsdf.h $(gdevvec_h) $(gsparam_h) $(scfx_h) $(strimpl_h)
+gdevpsdf_h=$(GLSRC)gdevpsdf.h $(gdevvec_h) $(gsparam_h)\
+ $(sa85x_h) $(scfx_h) $(spsdf_h) $(strimpl_h)
gdevpsds_h=$(GLSRC)gdevpsds.h $(strimpl_h)
-gdevpstr_h=$(GLSRC)gdevpstr.h
-psdf_1=$(GLOBJ)gdevpsde.$(OBJ) $(GLOBJ)gdevpsdf.$(OBJ) $(GLOBJ)gdevpsdi.$(OBJ)
-psdf_2=$(GLOBJ)gdevpsdp.$(OBJ) $(GLOBJ)gdevpsds.$(OBJ) $(GLOBJ)gdevpstr.$(OBJ)
+psdf_1=$(GLOBJ)gdevpsd1.$(OBJ) $(GLOBJ)gdevpsdf.$(OBJ) $(GLOBJ)gdevpsdi.$(OBJ)
+psdf_2=$(GLOBJ)gdevpsdp.$(OBJ) $(GLOBJ)gdevpsds.$(OBJ) $(GLOBJ)gdevpsdt.$(OBJ)
psdf_3=$(GLOBJ)scfparam.$(OBJ) $(GLOBJ)sdcparam.$(OBJ) $(GLOBJ)sdeparam.$(OBJ)
-psdf_=$(psdf_1) $(psdf_2) $(psdf_3)
-$(DD)psdf.dev : $(ECHOGS_XE) $(psdf_) $(GLD)vector.dev $(GLD)pngp.dev
+psdf_4=$(GLOBJ)spprint.$(OBJ) $(GLOBJ)spsdf.$(OBJ)
+psdf_=$(psdf_1) $(psdf_2) $(psdf_3) $(psdf_4)
+$(DD)psdf.dev : $(DEVS_MAK) $(ECHOGS_XE) $(psdf_) $(GLD)vector.dev $(GLD)pngp.dev
$(SETMOD) $(DD)psdf $(psdf_1)
$(ADDMOD) $(DD)psdf -obj $(psdf_2)
$(ADDMOD) $(DD)psdf -obj $(psdf_3)
+ $(ADDMOD) $(DD)psdf -obj $(psdf_4)
$(ADDMOD) $(DD)psdf -include $(GLD)vector $(GLD)pngp
-$(GLOBJ)gdevpsde.$(OBJ) : $(GLSRC)gdevpsde.c $(GXERR) $(memory__h)\
+$(GLOBJ)gdevpsd1.$(OBJ) : $(GLSRC)gdevpsd1.c $(GXERR) $(memory__h)\
$(gsccode_h) $(gsmatrix_h) $(gxfixed_h) $(gxfont_h) $(gxfont1_h)\
- $(stream_h)\
- $(gdevpsdf_h) $(gdevpstr_h)
- $(GLCC) $(GLO_)gdevpsde.$(OBJ) $(C_) $(GLSRC)gdevpsde.c
+ $(sfilter_h) $(stream_h) $(sstring_h)\
+ $(gdevpsdf_h) $(spprint_h)
+ $(GLCC) $(GLO_)gdevpsd1.$(OBJ) $(C_) $(GLSRC)gdevpsd1.c
-$(GLOBJ)gdevpsdf.$(OBJ) : $(GLSRC)gdevpsdf.c $(GXERR) $(string__h)\
+$(GLOBJ)gdevpsdf.$(OBJ) : $(GLSRC)gdevpsdf.c $(GXERR) $(memory__h)\
+ $(gxfont_h)\
$(sa85x_h) $(scanchar_h) $(scfx_h) $(sstring_h) $(strimpl_h)\
- $(gdevpsdf_h) $(gdevpstr_h)
+ $(gdevpsdf_h) $(spprint_h)
$(GLCC) $(GLO_)gdevpsdf.$(OBJ) $(C_) $(GLSRC)gdevpsdf.c
$(GLOBJ)gdevpsdi.$(OBJ) : $(GLSRC)gdevpsdi.c $(GXERR)\
@@ -624,26 +634,27 @@ $(GLOBJ)gdevpsdi.$(OBJ) : $(GLSRC)gdevpsdi.c $(GXERR)\
$(GLOBJ)gdevpsdp.$(OBJ) : $(GLSRC)gdevpsdp.c $(GDEVH)\
$(string__h) $(jpeglib__h)\
$(scfx_h) $(sdct_h) $(slzwx_h) $(srlx_h) $(strimpl_h) $(szlibx_h)\
- $(gsparamx_h) $(gdevpsdf_h) $(gdevpstr_h)
+ $(gsparamx_h) $(gsutil_h) $(gdevpsdf_h) $(spprint_h)
$(GLJCC) $(GLO_)gdevpsdp.$(OBJ) $(C_) $(GLSRC)gdevpsdp.c
$(GLOBJ)gdevpsds.$(OBJ) : $(GLSRC)gdevpsds.c $(GX) $(memory__h)\
$(gdevpsds_h) $(gserrors_h) $(gxdcconv_h)
$(GLCC) $(GLO_)gdevpsds.$(OBJ) $(C_) $(GLSRC)gdevpsds.c
-$(GLOBJ)gdevpstr.$(OBJ) : $(GLSRC)gdevpstr.c\
- $(math__h) $(stdio__h) $(string__h)\
- $(gdevpstr_h) $(stream_h)
- $(GLCC) $(GLO_)gdevpstr.$(OBJ) $(C_) $(GLSRC)gdevpstr.c
+$(GLOBJ)gdevpsdt.$(OBJ) : $(GLSRC)gdevpsdt.c $(GXERR) $(memory__h)\
+ $(gsmatrix_h) $(gsutil_h) $(gxfont_h) $(gxfont42_h)\
+ $(spprint_h) $(stream_h)\
+ $(gdevpsdf_h)
+ $(GLCC) $(GLO_)gdevpsdt.$(OBJ) $(C_) $(GLSRC)gdevpsdt.c
# PostScript and EPS writers
pswrite_=$(GLOBJ)gdevps.$(OBJ) $(GLOBJ)scantab.$(OBJ) $(GLOBJ)sfilter2.$(OBJ)
-$(DD)epswrite.dev : $(ECHOGS_XE) $(pswrite_) $(GLD)psdf.dev
+$(DD)epswrite.dev : $(DEVS_MAK) $(ECHOGS_XE) $(pswrite_) $(GLD)psdf.dev
$(SETDEV2) $(DD)epswrite $(pswrite_)
$(ADDMOD) $(DD)epswrite -include $(GLD)psdf
-$(DD)pswrite.dev : $(ECHOGS_XE) $(pswrite_) $(GLD)psdf.dev
+$(DD)pswrite.dev : $(DEVS_MAK) $(ECHOGS_XE) $(pswrite_) $(GLD)psdf.dev
$(SETDEV2) $(DD)pswrite $(pswrite_)
$(ADDMOD) $(DD)pswrite -include $(GLD)psdf
@@ -652,40 +663,45 @@ $(GLOBJ)gdevps.$(OBJ) : $(GLSRC)gdevps.c $(GDEV)\
$(gscdefs_h) $(gscspace_h) $(gsline_h) $(gsparam_h) $(gsiparam_h) $(gsmatrix_h)\
$(gxdcolor_h) $(gxpath_h)\
$(sa85x_h) $(sstring_h) $(strimpl_h)\
- $(gdevpsdf_h) $(gdevpstr_h)
+ $(gdevpsdf_h) $(spprint_h)
$(GLCC) $(GLO_)gdevps.$(OBJ) $(C_) $(GLSRC)gdevps.c
# PDF writer
# Note that gs_pdfwr.ps will only actually be loaded if the configuration
-# includes a PostScript interpreter.
-
-pdfwrite1_=$(GLOBJ)gdevpdf.$(OBJ) $(GLOBJ)gdevpdfd.$(OBJ) $(GLOBJ)gdevpdfi.$(OBJ)
-pdfwrite2_=$(GLOBJ)gdevpdfm.$(OBJ) $(GLOBJ)gdevpdfo.$(OBJ) $(GLOBJ)gdevpdfp.$(OBJ)
-pdfwrite3_=$(GLOBJ)gdevpdft.$(OBJ) $(GLOBJ)gsflip.$(OBJ) $(GLOBJ)gsparamx.$(OBJ)
-pdfwrite4_=$(GLOBJ)scantab.$(OBJ) $(GLOBJ)sfilter2.$(OBJ) $(GLOBJ)sstring.$(OBJ)
-pdfwrite_=$(pdfwrite1_) $(pdfwrite2_) $(pdfwrite3_) $(pdfwrite4_)
-$(DD)pdfwrite.dev : $(ECHOGS_XE) $(pdfwrite_)\
- $(GLD)cmyklib.dev $(GLD)cfe.dev $(GLD)dcte.dev $(GLD)lzwe.dev $(GLD)rle.dev $(GLD)szlibe.dev $(GLD)psdf.dev
+# includes a PostScript interpreter. gs_mgl_e requires gs_mro_e and should
+# always be loaded: guaranteeing this will require moving the Encodings
+# into C code.
+
+pdfwrite1_=$(GLOBJ)gdevpdf.$(OBJ) $(GLOBJ)gdevpdfd.$(OBJ)
+pdfwrite2_=$(GLOBJ)gdevpdff.$(OBJ) $(GLOBJ)gdevpdfi.$(OBJ) $(GLOBJ)gdevpdfm.$(OBJ)
+pdfwrite3_=$(GLOBJ)gdevpdfo.$(OBJ) $(GLOBJ)gdevpdfp.$(OBJ) $(GLOBJ)gdevpdfr.$(OBJ)
+pdfwrite4_=$(GLOBJ)gdevpdft.$(OBJ) $(GLOBJ)gdevpdfu.$(OBJ)
+pdfwrite5_=$(GLOBJ)gsflip.$(OBJ) $(GLOBJ)gsparamx.$(OBJ)
+pdfwrite6_=$(GLOBJ)scantab.$(OBJ) $(GLOBJ)sfilter2.$(OBJ) $(GLOBJ)sstring.$(OBJ)
+pdfwrite_=$(pdfwrite1_) $(pdfwrite2_) $(pdfwrite3_) $(pdfwrite4_) $(pdfwrite5_)
+$(DD)pdfwrite.dev : $(DEVS_MAK) $(ECHOGS_XE) $(pdfwrite_)\
+ $(GLD)cmyklib.dev $(GLD)cfe.dev $(GLD)dcte.dev $(GLD)lzwe.dev\
+ $(GLD)rle.dev $(GLD)szlibe.dev $(GLD)psdf.dev
$(SETDEV2) $(DD)pdfwrite $(pdfwrite1_)
$(ADDMOD) $(DD)pdfwrite $(pdfwrite2_)
$(ADDMOD) $(DD)pdfwrite $(pdfwrite3_)
$(ADDMOD) $(DD)pdfwrite $(pdfwrite4_)
+ $(ADDMOD) $(DD)pdfwrite $(pdfwrite5_)
+ $(ADDMOD) $(DD)pdfwrite $(pdfwrite6_)
$(ADDMOD) $(DD)pdfwrite -ps gs_pdfwr
+ $(ADDMOD) $(DD)pdfwrite -ps gs_lgo_e gs_lgx_e gs_mgl_e gs_mro_e
$(ADDMOD) $(DD)pdfwrite -include $(GLD)cmyklib $(GLD)cfe $(GLD)dcte
$(ADDMOD) $(DD)pdfwrite -include $(GLD)lzwe $(GLD)rle $(GLD)szlibe
$(ADDMOD) $(DD)pdfwrite -include $(GLD)psdf
+gdevpdfo_h=$(GLSRC)gdevpdfo.h
gdevpdfx_h=$(GLSRC)gdevpdfx.h\
- $(gsparam_h) $(gxdevice_h) $(gxline_h) $(stream_h)\
- $(gdevpsdf_h) $(gdevpstr_h)
+ $(gsparam_h) $(gsuid_h) $(gxdevice_h) $(gxfont_h) $(gxline_h)\
+ $(spprint_h) $(stream_h) $(gdevpsdf_h) $(gdevpdfo_h)
$(GLOBJ)gdevpdf.$(OBJ) : $(GLSRC)gdevpdf.c $(GDEVH)\
- $(math__h) $(memory__h) $(string__h) $(time__h)\
- $(gp_h)\
- $(gdevpdfx_h) $(gscdefs_h)\
- $(gxfixed_h) $(gxistate_h) $(gxpaint_h)\
- $(gzcpath_h) $(gzpath_h)\
- $(scanchar_h) $(scfx_h) $(slzwx_h) $(sstring_h) $(strimpl_h) $(szlibx_h)
+ $(memory__h) $(string__h)\
+ $(gscdefs_h) $(gdevpdfx_h)
$(GLCC) $(GLO_)gdevpdf.$(OBJ) $(C_) $(GLSRC)gdevpdf.c
$(GLOBJ)gdevpdfd.$(OBJ) : $(GLSRC)gdevpdfd.c $(math__h)\
@@ -694,6 +710,14 @@ $(GLOBJ)gdevpdfd.$(OBJ) : $(GLSRC)gdevpdfd.c $(math__h)\
$(gzcpath_h) $(gzpath_h)
$(GLCC) $(GLO_)gdevpdfd.$(OBJ) $(C_) $(GLSRC)gdevpdfd.c
+$(GLOBJ)gdevpdff.$(OBJ) : $(GLSRC)gdevpdff.c\
+ $(math__h) $(memory__h) $(string__h) $(gx_h)\
+ $(gdevpdfx_h)\
+ $(gserrors_h) $(gsmalloc_h) $(gsmatrix_h) $(gspath_h) $(gsutil_h)\
+ $(gxfcache_h) $(gxfixed_h) $(gxfont_h) $(gxpath_h)\
+ $(scommon_h)
+ $(GLCC) $(GLO_)gdevpdff.$(OBJ) $(C_) $(GLSRC)gdevpdff.c
+
$(GLOBJ)gdevpdfi.$(OBJ) : $(GLSRC)gdevpdfi.c\
$(math__h) $(memory__h) $(string__h) $(jpeglib__h) $(gx_h)\
$(gdevpdfx_h)\
@@ -710,7 +734,7 @@ $(GLOBJ)gdevpdfm.$(OBJ) : $(GLSRC)gdevpdfm.c\
$(GLOBJ)gdevpdfo.$(OBJ) : $(GLSRC)gdevpdfo.c $(memory__h) $(string__h)\
$(gx_h)\
- $(gdevpdfx_h) $(gserrors_h) $(gsutil_h)\
+ $(gdevpdfo_h) $(gdevpdfx_h) $(gserrors_h) $(gsutil_h)\
$(sstring_h) $(strimpl_h)
$(GLCC) $(GLO_)gdevpdfo.$(OBJ) $(C_) $(GLSRC)gdevpdfo.c
@@ -718,20 +742,36 @@ $(GLOBJ)gdevpdfp.$(OBJ) : $(GLSRC)gdevpdfp.c $(gx_h)\
$(gdevpdfx_h) $(gserrors_h) $(gsparamx_h)
$(GLCC) $(GLO_)gdevpdfp.$(OBJ) $(C_) $(GLSRC)gdevpdfp.c
+$(GLOBJ)gdevpdfr.$(OBJ) : $(GLSRC)gdevpdfr.c $(memory__h) $(string__h)\
+ $(gx_h)\
+ $(gdevpdfx_h) $(gserrors_h) $(gsutil_h)\
+ $(scanchar_h) $(sstring_h) $(strimpl_h)
+ $(GLCC) $(GLO_)gdevpdfr.$(OBJ) $(C_) $(GLSRC)gdevpdfr.c
+
$(GLOBJ)gdevpdft.$(OBJ) : $(GLSRC)gdevpdft.c\
$(math__h) $(memory__h) $(string__h) $(gx_h)\
- $(gdevpdfx_h) $(gserrors_h) $(gsutil_h)\
+ $(gdevpdfx_h) $(gserrors_h) $(gsmatrix_h) $(gsutil_h)\
+ $(gxfcache_h) $(gxfixed_h) $(gxfont_h) $(gxfont0_h) $(gxpath_h)\
$(scommon_h)
$(GLCC) $(GLO_)gdevpdft.$(OBJ) $(C_) $(GLSRC)gdevpdft.c
+$(GLOBJ)gdevpdfu.$(OBJ) : $(GLSRC)gdevpdfu.c $(GDEVH)\
+ $(math__h) $(memory__h) $(string__h) $(time__h)\
+ $(gp_h)\
+ $(gdevpdfx_h)\
+ $(gxfixed_h) $(gxistate_h) $(gxpaint_h)\
+ $(gzcpath_h) $(gzpath_h)\
+ $(scanchar_h) $(scfx_h) $(slzwx_h) $(sstring_h) $(strimpl_h) $(szlibx_h)
+ $(GLCC) $(GLO_)gdevpdfu.$(OBJ) $(C_) $(GLSRC)gdevpdfu.c
+
# High-level PCL XL writer
pxl_=$(GLOBJ)gdevpx.$(OBJ)
-$(DD)pxlmono.dev : $(pxl_) $(GDEV) $(GLD)vector.dev
+$(DD)pxlmono.dev : $(DEVS_MAK) $(pxl_) $(GDEV) $(GLD)vector.dev
$(SETDEV2) $(DD)pxlmono $(pxl_)
$(ADDMOD) $(DD)pxlmono -include $(GLD)vector
-$(DD)pxlcolor.dev : $(pxl_) $(GDEV) $(GLD)vector.dev
+$(DD)pxlcolor.dev : $(DEVS_MAK) $(pxl_) $(GDEV) $(GLD)vector.dev
$(SETDEV2) $(DD)pxlcolor $(pxl_)
$(ADDMOD) $(DD)pxlcolor -include $(GLD)vector
@@ -752,15 +792,15 @@ $(GLOBJ)gdevpx.$(OBJ) : $(GLSRC)gdevpx.c\
bit_=$(GLOBJ)gdevbit.$(OBJ) $(GLOBJ)gdevdcrd.$(OBJ)
-$(DD)bit.dev : $(bit_) $(GLD)page.dev $(GLD)cielib.dev
+$(DD)bit.dev : $(DEVS_MAK) $(bit_) $(GLD)page.dev $(GLD)cielib.dev
$(SETPDEV2) $(DD)bit $(bit_)
$(ADDMOD) $(DD)bit -include $(GLD)cielib
-$(DD)bitrgb.dev : $(bit_) $(GLD)page.dev $(GLD)cielib.dev
+$(DD)bitrgb.dev : $(DEVS_MAK) $(bit_) $(GLD)page.dev $(GLD)cielib.dev
$(SETPDEV2) $(DD)bitrgb $(bit_)
$(ADDMOD) $(DD)bitrgb -include $(GLD)cielib
-$(DD)bitcmyk.dev : $(bit_) $(GLD)page.dev $(GLD)cielib.dev
+$(DD)bitcmyk.dev : $(DEVS_MAK) $(bit_) $(GLD)page.dev $(GLD)cielib.dev
$(SETPDEV2) $(DD)bitcmyk $(bit_)
$(ADDMOD) $(DD)bitcmyk -include $(GLD)cielib
@@ -780,62 +820,64 @@ $(GLOBJ)gdevbmp.$(OBJ) : $(GLSRC)gdevbmp.c $(PDEVH) $(gdevbmp_h) $(gdevpccm_h)
$(GLOBJ)gdevbmpc.$(OBJ) : $(GLSRC)gdevbmpc.c $(PDEVH) $(gdevbmp_h)
$(GLCC) $(GLO_)gdevbmpc.$(OBJ) $(C_) $(GLSRC)gdevbmpc.c
-$(DD)bmpmono.dev : $(bmp_) $(GLD)page.dev
+$(DD)bmpmono.dev : $(DEVS_MAK) $(bmp_) $(GLD)page.dev
$(SETPDEV) $(DD)bmpmono $(bmp_)
-$(DD)bmpsep1.dev : $(bmp_) $(GLD)page.dev
+$(DD)bmpgray.dev : $(DEVS_MAK) $(bmp_) $(GLD)page.dev
+ $(SETPDEV) $(DD)bmpgray $(bmp_)
+
+$(DD)bmpsep1.dev : $(DEVS_MAK) $(bmp_) $(GLD)page.dev
$(SETPDEV) $(DD)bmpsep1 $(bmp_)
-$(DD)bmpsep8.dev : $(bmp_) $(GLD)page.dev
+$(DD)bmpsep8.dev : $(DEVS_MAK) $(bmp_) $(GLD)page.dev
$(SETPDEV) $(DD)bmpsep8 $(bmp_)
-$(DD)bmp16.dev : $(bmp_) $(GLD)page.dev
+$(DD)bmp16.dev : $(DEVS_MAK) $(bmp_) $(GLD)page.dev
$(SETPDEV) $(DD)bmp16 $(bmp_)
-$(DD)bmp256.dev : $(bmp_) $(GLD)page.dev
+$(DD)bmp256.dev : $(DEVS_MAK) $(bmp_) $(GLD)page.dev
$(SETPDEV) $(DD)bmp256 $(bmp_)
-$(DD)bmp16m.dev : $(bmp_) $(GLD)page.dev
+$(DD)bmp16m.dev : $(DEVS_MAK) $(bmp_) $(GLD)page.dev
$(SETPDEV) $(DD)bmp16m $(bmp_)
-$(DD)bmp32b.dev : $(bmp_) $(GLD)page.dev
+$(DD)bmp32b.dev : $(DEVS_MAK) $(bmp_) $(GLD)page.dev
$(SETPDEV) $(DD)bmp32b $(bmp_)
### ------------- BMP driver that serves as demo of async rendering ---- ###
-bmpa_=$(GLOBJ)gdevbmpa.$(OBJ) $(GLOBJ)gdevbmpc.$(OBJ) $(GLOBJ)gdevppla.$(OBJ) \
- $(GLOBJ)gdevpccm.$(OBJ)
+bmpa_=$(GLOBJ)gdevbmpa.$(OBJ) $(GLOBJ)gdevbmpc.$(OBJ) $(GLOBJ)gdevpccm.$(OBJ) $(GLOBJ)gdevppla.$(OBJ)
$(GLOBJ)gdevbmpa.$(OBJ) : $(GLSRC)gdevbmpa.c $(AK) $(stdio__h)\
$(gdevbmp_h) $(gdevprna_h) $(gdevpccm_h) $(gdevppla_h)\
$(gserrors_h) $(gpsync_h)
$(GLCC) $(GLO_)gdevbmpa.$(OBJ) $(C_) $(GLSRC)gdevbmpa.c
-$(DD)bmpamono.dev : $(bmpa_) $(GLD)page.dev $(GLD)async.dev
+$(DD)bmpamono.dev : $(DEVS_MAK) $(bmpa_) $(GLD)page.dev $(GLD)async.dev
$(SETPDEV) $(DD)bmpamono $(bmpa_)
$(ADDMOD) $(DD)bmpamono -include $(GLD)async
-$(DD)bmpasep1.dev : $(bmpa_) $(GLD)page.dev $(GLD)async.dev
+$(DD)bmpasep1.dev : $(DEVS_MAK) $(bmpa_) $(GLD)page.dev $(GLD)async.dev
$(SETPDEV) $(DD)bmpasep1 $(bmpa_)
$(ADDMOD) $(DD)bmpasep1 -include $(GLD)async
-$(DD)bmpasep8.dev : $(bmpa_) $(GLD)page.dev $(GLD)async.dev
+$(DD)bmpasep8.dev : $(DEVS_MAK) $(bmpa_) $(GLD)page.dev $(GLD)async.dev
$(SETPDEV) $(DD)bmpasep8 $(bmpa_)
$(ADDMOD) $(DD)bmpasep8 -include $(GLD)async
-$(DD)bmpa16.dev : $(bmpa_) $(GLD)page.dev $(GLD)async.dev
+$(DD)bmpa16.dev : $(DEVS_MAK) $(bmpa_) $(GLD)page.dev $(GLD)async.dev
$(SETPDEV) $(DD)bmpa16 $(bmpa_)
$(ADDMOD) $(DD)bmpa16 -include $(GLD)async
-$(DD)bmpa256.dev : $(bmpa_) $(GLD)page.dev $(GLD)async.dev
+$(DD)bmpa256.dev : $(DEVS_MAK) $(bmpa_) $(GLD)page.dev $(GLD)async.dev
$(SETPDEV) $(DD)bmpa256 $(bmpa_)
$(ADDMOD) $(DD)bmpa256 -include $(GLD)async
-$(DD)bmpa16m.dev : $(bmpa_) $(GLD)page.dev $(GLD)async.dev
+$(DD)bmpa16m.dev : $(DEVS_MAK) $(bmpa_) $(GLD)page.dev $(GLD)async.dev
$(SETPDEV) $(DD)bmpa16m $(bmpa_)
$(ADDMOD) $(DD)bmpa16m -include $(GLD)async
-$(DD)bmpa32b.dev : $(bmpa_) $(GLD)page.dev $(GLD)async.dev
+$(DD)bmpa32b.dev : $(DEVS_MAK) $(bmpa_) $(GLD)page.dev $(GLD)async.dev
$(SETPDEV) $(DD)bmpa32b $(bmpa_)
$(ADDMOD) $(DD)bmpa32b -include $(GLD)async
@@ -857,13 +899,13 @@ $(GLOBJ)gdevcgml.$(OBJ) : $(GLSRC)gdevcgml.c $(memory__h) $(stdio__h)\
$(gdevcgmx_h)
$(GLCC) $(GLO_)gdevcgml.$(OBJ) $(C_) $(GLSRC)gdevcgml.c
-$(DD)cgmmono.dev : $(cgm_)
+$(DD)cgmmono.dev : $(DEVS_MAK) $(cgm_)
$(SETDEV) $(DD)cgmmono $(cgm_)
-$(DD)cgm8.dev : $(cgm_)
+$(DD)cgm8.dev : $(DEVS_MAK) $(cgm_)
$(SETDEV) $(DD)cgm8 $(cgm_)
-$(DD)cgm24.dev : $(cgm_)
+$(DD)cgm24.dev : $(DEVS_MAK) $(cgm_)
$(SETDEV) $(DD)cgm24 $(cgm_)
### ------------------------- JPEG file format ------------------------- ###
@@ -871,12 +913,12 @@ $(DD)cgm24.dev : $(cgm_)
jpeg_=$(GLOBJ)gdevjpeg.$(OBJ)
# RGB output
-$(DD)jpeg.dev : $(jpeg_) $(GLD)sdcte.dev $(GLD)page.dev
+$(DD)jpeg.dev : $(DEVS_MAK) $(jpeg_) $(GLD)sdcte.dev $(GLD)page.dev
$(SETPDEV2) $(DD)jpeg $(jpeg_)
$(ADDMOD) $(DD)jpeg -include $(GLD)sdcte
# Gray output
-$(DD)jpeggray.dev : $(jpeg_) $(GLD)sdcte.dev $(GLD)page.dev
+$(DD)jpeggray.dev : $(DEVS_MAK) $(jpeg_) $(GLD)sdcte.dev $(GLD)page.dev
$(SETPDEV2) $(DD)jpeggray $(jpeg_)
$(ADDMOD) $(DD)jpeggray -include $(GLD)sdcte
@@ -891,7 +933,7 @@ $(GLOBJ)gdevjpeg.$(OBJ) : $(GLSRC)gdevjpeg.c $(PDEVH)\
miff_=$(GLOBJ)gdevmiff.$(OBJ)
-$(DD)miff24.dev : $(miff_) $(GLD)page.dev
+$(DD)miff24.dev : $(DEVS_MAK) $(miff_) $(GLD)page.dev
$(SETPDEV) $(DD)miff24 $(miff_)
$(GLOBJ)gdevmiff.$(OBJ) : $(GLSRC)gdevmiff.c $(PDEVH)
@@ -904,27 +946,27 @@ pcx_=$(GLOBJ)gdevpcx.$(OBJ) $(GLOBJ)gdevpccm.$(OBJ)
$(GLOBJ)gdevpcx.$(OBJ) : $(GLSRC)gdevpcx.c $(PDEVH) $(gdevpccm_h) $(gxlum_h)
$(GLCC) $(GLO_)gdevpcx.$(OBJ) $(C_) $(GLSRC)gdevpcx.c
-$(DD)pcxmono.dev : $(pcx_) $(GLD)page.dev
+$(DD)pcxmono.dev : $(DEVS_MAK) $(pcx_) $(GLD)page.dev
$(SETPDEV2) $(DD)pcxmono $(pcx_)
-$(DD)pcxgray.dev : $(pcx_) $(GLD)page.dev
+$(DD)pcxgray.dev : $(DEVS_MAK) $(pcx_) $(GLD)page.dev
$(SETPDEV2) $(DD)pcxgray $(pcx_)
-$(DD)pcx16.dev : $(pcx_) $(GLD)page.dev
+$(DD)pcx16.dev : $(DEVS_MAK) $(pcx_) $(GLD)page.dev
$(SETPDEV2) $(DD)pcx16 $(pcx_)
-$(DD)pcx256.dev : $(pcx_) $(GLD)page.dev
+$(DD)pcx256.dev : $(DEVS_MAK) $(pcx_) $(GLD)page.dev
$(SETPDEV2) $(DD)pcx256 $(pcx_)
-$(DD)pcx24b.dev : $(pcx_) $(GLD)page.dev
+$(DD)pcx24b.dev : $(DEVS_MAK) $(pcx_) $(GLD)page.dev
$(SETPDEV2) $(DD)pcx24b $(pcx_)
-$(DD)pcxcmyk.dev : $(pcx_) $(GLD)page.dev
+$(DD)pcxcmyk.dev : $(DEVS_MAK) $(pcx_) $(GLD)page.dev
$(SETPDEV2) $(DD)pcxcmyk $(pcx_)
# The 2-up PCX device is here only as an example, and for testing.
-$(DD)pcx2up.dev : $(LIB_MAK) $(ECHOGS_XE) $(GLOBJ)gdevp2up.$(OBJ) $(GLD)page.dev $(DD)pcx256.dev
+$(DD)pcx2up.dev : $(DEVS_MAK) $(LIB_MAK) $(ECHOGS_XE) $(GLOBJ)gdevp2up.$(OBJ) $(GLD)page.dev $(DD)pcx256.dev
$(SETPDEV) $(DD)pcx2up $(GLOBJ)gdevp2up.$(OBJ)
$(ADDMOD) $(DD)pcx2up -include $(DD)pcx256
@@ -944,63 +986,63 @@ $(GLOBJ)gdevpbm.$(OBJ) : $(GLSRC)gdevpbm.c $(PDEVH)\
### Portable Bitmap (PBM, plain or raw format, magic numbers "P1" or "P4")
-$(DD)pbm.dev : $(pxm_) $(GLD)page.dev
+$(DD)pbm.dev : $(DEVS_MAK) $(pxm_) $(GLD)page.dev
$(SETPDEV2) $(DD)pbm $(pxm_)
-$(DD)pbmraw.dev : $(pxm_) $(GLD)page.dev
+$(DD)pbmraw.dev : $(DEVS_MAK) $(pxm_) $(GLD)page.dev
$(SETPDEV2) $(DD)pbmraw $(pxm_)
### Portable Graymap (PGM, plain or raw format, magic numbers "P2" or "P5")
-$(DD)pgm.dev : $(pxm_) $(GLD)page.dev
+$(DD)pgm.dev : $(DEVS_MAK) $(pxm_) $(GLD)page.dev
$(SETPDEV2) $(DD)pgm $(pxm_)
-$(DD)pgmraw.dev : $(pxm_) $(GLD)page.dev
+$(DD)pgmraw.dev : $(DEVS_MAK) $(pxm_) $(GLD)page.dev
$(SETPDEV2) $(DD)pgmraw $(pxm_)
# PGM with automatic optimization to PBM if this is possible.
-$(DD)pgnm.dev : $(pxm_) $(GLD)page.dev
+$(DD)pgnm.dev : $(DEVS_MAK) $(pxm_) $(GLD)page.dev
$(SETPDEV2) $(DD)pgnm $(pxm_)
-$(DD)pgnmraw.dev : $(pxm_) $(GLD)page.dev
+$(DD)pgnmraw.dev : $(DEVS_MAK) $(pxm_) $(GLD)page.dev
$(SETPDEV2) $(DD)pgnmraw $(pxm_)
### Portable Pixmap (PPM, plain or raw format, magic numbers "P3" or "P6")
-$(DD)ppm.dev : $(pxm_) $(GLD)page.dev
+$(DD)ppm.dev : $(DEVS_MAK) $(pxm_) $(GLD)page.dev
$(SETPDEV2) $(DD)ppm $(pxm_)
-$(DD)ppmraw.dev : $(pxm_) $(GLD)page.dev
+$(DD)ppmraw.dev : $(DEVS_MAK) $(pxm_) $(GLD)page.dev
$(SETPDEV2) $(DD)ppmraw $(pxm_)
# PPM with automatic optimization to PGM or PBM if possible.
-$(DD)pnm.dev : $(pxm_) $(GLD)page.dev
+$(DD)pnm.dev : $(DEVS_MAK) $(pxm_) $(GLD)page.dev
$(SETPDEV2) $(DD)pnm $(pxm_)
-$(DD)pnmraw.dev : $(pxm_) $(GLD)page.dev
+$(DD)pnmraw.dev : $(DEVS_MAK) $(pxm_) $(GLD)page.dev
$(SETPDEV2) $(DD)pnmraw $(pxm_)
### Portable inKmap (CMYK internally, converted to PPM=RGB at output time)
-$(DD)pkm.dev : $(pxm_) $(GLD)page.dev
+$(DD)pkm.dev : $(DEVS_MAK) $(pxm_) $(GLD)page.dev
$(SETPDEV2) $(DD)pkm $(pxm_)
-$(DD)pkmraw.dev : $(pxm_) $(GLD)page.dev
+$(DD)pkmraw.dev : $(DEVS_MAK) $(pxm_) $(GLD)page.dev
$(SETPDEV2) $(DD)pkmraw $(pxm_)
### Portable Separated map (CMYK internally, produces 4 monobit pages)
-$(DD)pksm.dev : $(pxm_) $(GLD)page.dev
+$(DD)pksm.dev : $(DEVS_MAK) $(pxm_) $(GLD)page.dev
$(SETPDEV2) $(DD)pksm $(pxm_)
-$(DD)pksmraw.dev : $(pxm_) $(GLD)page.dev
+$(DD)pksmraw.dev : $(DEVS_MAK) $(pxm_) $(GLD)page.dev
$(SETPDEV2) $(DD)pksmraw $(pxm_)
### Plan 9 bitmap format
-$(DD)plan9bm.dev : $(pxm_) $(GLD)page.dev
+$(DD)plan9bm.dev : $(DEVS_MAK) $(pxm_) $(GLD)page.dev
$(SETPDEV2) $(DD)plan9bm $(pxm_)
### --------------- Portable Network Graphics file format --------------- ###
@@ -1017,23 +1059,23 @@ $(GLOBJ)gdevpng.$(OBJ) : $(GLSRC)gdevpng.c\
$(gdevprn_h) $(gdevpccm_h) $(gscdefs_h) $(png__h)
$(CC_) $(I_)$(GLI_) $(II)$(PI_)$(_I) $(PCF_) $(GLF_) $(GLO_)gdevpng.$(OBJ) $(C_) $(GLSRC)gdevpng.c
-$(DD)pngmono.dev : $(libpng_dev) $(png_) $(GLD)page.dev
+$(DD)pngmono.dev : $(DEVS_MAK) $(libpng_dev) $(png_) $(GLD)page.dev
$(SETPDEV2) $(DD)pngmono $(png_)
$(ADDMOD) $(DD)pngmono $(png_i_)
-$(DD)pnggray.dev : $(libpng_dev) $(png_) $(GLD)page.dev
+$(DD)pnggray.dev : $(DEVS_MAK) $(libpng_dev) $(png_) $(GLD)page.dev
$(SETPDEV2) $(DD)pnggray $(png_)
$(ADDMOD) $(DD)pnggray $(png_i_)
-$(DD)png16.dev : $(libpng_dev) $(png_) $(GLD)page.dev
+$(DD)png16.dev : $(DEVS_MAK) $(libpng_dev) $(png_) $(GLD)page.dev
$(SETPDEV2) $(DD)png16 $(png_)
$(ADDMOD) $(DD)png16 $(png_i_)
-$(DD)png256.dev : $(libpng_dev) $(png_) $(GLD)page.dev
+$(DD)png256.dev : $(DEVS_MAK) $(libpng_dev) $(png_) $(GLD)page.dev
$(SETPDEV2) $(DD)png256 $(png_)
$(ADDMOD) $(DD)png256 $(png_i_)
-$(DD)png16m.dev : $(libpng_dev) $(png_) $(GLD)page.dev
+$(DD)png16m.dev : $(DEVS_MAK) $(libpng_dev) $(png_) $(GLD)page.dev
$(SETPDEV2) $(DD)png16m $(png_)
$(ADDMOD) $(DD)png16m $(png_i_)
@@ -1050,10 +1092,10 @@ psim_=$(GLOBJ)gdevpsim.$(OBJ)
$(GLOBJ)gdevpsim.$(OBJ) : $(GLSRC)gdevpsim.c $(PDEVH)
$(GLCC) $(GLO_)gdevpsim.$(OBJ) $(C_) $(GLSRC)gdevpsim.c
-$(DD)psmono.dev : $(psim_) $(GLD)page.dev
+$(DD)psmono.dev : $(DEVS_MAK) $(psim_) $(GLD)page.dev
$(SETPDEV2) $(DD)psmono $(psim_)
-$(DD)psgray.dev : $(psim_) $(GLD)page.dev
+$(DD)psgray.dev : $(DEVS_MAK) $(psim_) $(GLD)page.dev
$(SETPDEV2) $(DD)psgray $(psim_)
# RGB, Level 2 output
@@ -1064,7 +1106,7 @@ $(GLOBJ)gdevpsci.$(OBJ) : $(GLSRC)gdevpsci.c $(PDEVH)\
$(srlx_h) $(stream_h) $(strimpl_h)
$(GLCC) $(GLO_)gdevpsci.$(OBJ) $(C_) $(GLSRC)gdevpsci.c
-$(DD)psrgb.dev : $(psci_) $(GLD)page.dev
+$(DD)psrgb.dev : $(DEVS_MAK) $(psci_) $(GLD)page.dev
$(SETPDEV2) $(DD)psrgb $(psci_)
### -------------------- Plain or TIFF fax encoding --------------------- ###
@@ -1078,32 +1120,33 @@ $(DD)psrgb.dev : $(psci_) $(GLD)page.dev
# AdjustWidth to 0 (e.g., -dAdjustWidth=0 on the command line).
gdevtifs_h=$(GLSRC)gdevtifs.h
+gdevtfax_h=$(GLSRC)gdevtfax.h
tfax_=$(GLOBJ)gdevtfax.$(OBJ)
-$(DD)tfax.dev : $(tfax_) $(GLD)cfe.dev $(GLD)lzwe.dev $(GLD)rle.dev $(DD)tiffs.dev
+$(DD)tfax.dev : $(DEVS_MAK) $(tfax_) $(GLD)cfe.dev $(GLD)lzwe.dev $(GLD)rle.dev $(DD)tiffs.dev
$(SETMOD) $(DD)tfax $(tfax_)
$(ADDMOD) $(DD)tfax -include $(GLD)cfe $(GLD)lzwe $(GLD)rle
$(ADDMOD) $(DD)tfax -include $(DD)tiffs
$(GLOBJ)gdevtfax.$(OBJ) : $(GLSRC)gdevtfax.c $(PDEVH)\
- $(gdevtifs_h) $(scfx_h) $(slzwx_h) $(srlx_h) $(strimpl_h)
+ $(gdevtifs_h) $(gdevtfax_h) $(scfx_h) $(slzwx_h) $(srlx_h) $(strimpl_h)
$(GLCC) $(GLO_)gdevtfax.$(OBJ) $(C_) $(GLSRC)gdevtfax.c
### Plain G3/G4 fax with no header
-$(DD)faxg3.dev : $(DD)tfax.dev
+$(DD)faxg3.dev : $(DEVS_MAK) $(DD)tfax.dev
$(SETDEV2) $(DD)faxg3 -include $(DD)tfax
-$(DD)faxg32d.dev : $(DD)tfax.dev
+$(DD)faxg32d.dev : $(DEVS_MAK) $(DD)tfax.dev
$(SETDEV2) $(DD)faxg32d -include $(DD)tfax
-$(DD)faxg4.dev : $(DD)tfax.dev
+$(DD)faxg4.dev : $(DEVS_MAK) $(DD)tfax.dev
$(SETDEV2) $(DD)faxg4 -include $(DD)tfax
### ---------------------------- TIFF formats --------------------------- ###
tiffs_=$(GLOBJ)gdevtifs.$(OBJ)
-$(DD)tiffs.dev : $(tiffs_) $(GLD)page.dev
+$(DD)tiffs.dev : $(DEVS_MAK) $(tiffs_) $(GLD)page.dev
$(SETMOD) $(DD)tiffs $(tiffs_)
$(ADDMOD) $(DD)tiffs -include $(GLD)page
@@ -1114,37 +1157,37 @@ $(GLOBJ)gdevtifs.$(OBJ) : $(GLSRC)gdevtifs.c $(PDEVH) $(stdio__h) $(time__h)\
# Black & white, G3/G4 fax
# NOTE: see under faxg* above regarding page width adjustment.
-$(DD)tiffcrle.dev : $(DD)tfax.dev
+$(DD)tiffcrle.dev : $(DEVS_MAK) $(DD)tfax.dev
$(SETDEV2) $(DD)tiffcrle -include $(DD)tfax
-$(DD)tiffg3.dev : $(DD)tfax.dev
+$(DD)tiffg3.dev : $(DEVS_MAK) $(DD)tfax.dev
$(SETDEV2) $(DD)tiffg3 -include $(DD)tfax
-$(DD)tiffg32d.dev : $(DD)tfax.dev
+$(DD)tiffg32d.dev : $(DEVS_MAK) $(DD)tfax.dev
$(SETDEV2) $(DD)tiffg32d -include $(DD)tfax
-$(DD)tiffg4.dev : $(DD)tfax.dev
+$(DD)tiffg4.dev : $(DEVS_MAK) $(DD)tfax.dev
$(SETDEV2) $(DD)tiffg4 -include $(DD)tfax
# Black & white, LZW compression
-$(DD)tifflzw.dev : $(DD)tfax.dev
+$(DD)tifflzw.dev : $(DEVS_MAK) $(DD)tfax.dev
$(SETDEV2) $(DD)tifflzw -include $(DD)tfax
# Black & white, PackBits compression
-$(DD)tiffpack.dev : $(DD)tfax.dev
+$(DD)tiffpack.dev : $(DEVS_MAK) $(DD)tfax.dev
$(SETDEV2) $(DD)tiffpack -include $(DD)tfax
# RGB, no compression
tiffrgb_=$(GLOBJ)gdevtfnx.$(OBJ)
-$(DD)tiff12nc.dev : $(tiffrgb_) $(DD)tiffs.dev
+$(DD)tiff12nc.dev : $(DEVS_MAK) $(tiffrgb_) $(DD)tiffs.dev
$(SETPDEV2) $(DD)tiff12nc $(tiffrgb_)
$(ADDMOD) $(DD)tiff12nc -include $(DD)tiffs
-$(DD)tiff24nc.dev : $(tiffrgb_) $(DD)tiffs.dev
+$(DD)tiff24nc.dev : $(DEVS_MAK) $(tiffrgb_) $(DD)tiffs.dev
$(SETPDEV2) $(DD)tiff24nc $(tiffrgb_)
$(ADDMOD) $(DD)tiff24nc -include $(DD)tiffs
diff --git a/gs/src/dvx-gcc.mak b/gs/src/dvx-gcc.mak
index 9445f1fb8..3fb200eba 100755
--- a/gs/src/dvx-gcc.mak
+++ b/gs/src/dvx-gcc.mak
@@ -34,7 +34,7 @@ include $(GLSRCDIR)/version.mak
# the directories also define the default search path for the
# initialization files (gs_*.ps) and the fonts.
-INSTALL = install -c
+INSTALL = $(GLSRCDIR)/instcopy -c
INSTALL_PROGRAM = $(INSTALL) -m 755
INSTALL_DATA = $(INSTALL) -m 644
@@ -229,7 +229,7 @@ SYNC=posync
# Choose the language feature(s) to include. See gs.mak for details.
-FEATURE_DEVS=$(PSD)psl3.dev $(PSD)pdf.dev $(PSD)dpsnext.dev $(PSD)ttfont.dev
+FEATURE_DEVS=$(PSD)psl3.dev $(PSD)pdf.dev $(PSD)dpsnext.dev $(PSD)ttfont.dev $(PSD)pipe.dev
# Choose whether to compile the .ps initialization files into the executable.
# See gs.mak for details.
@@ -294,6 +294,7 @@ AK=
CCFLAGS=$(GENOPT) $(CFLAGS)
CC_=$(CC) $(CCFLAGS)
CC_LEAF=$(CC_) -fomit-frame-pointer
+CC_NO_WARN=$(CC_)
# ---------------- End of platform-specific section ---------------- #
diff --git a/gs/src/dwimg.cpp b/gs/src/dwimg.cpp
index a0334467f..052c41191 100644
--- a/gs/src/dwimg.cpp
+++ b/gs/src/dwimg.cpp
@@ -36,8 +36,14 @@ char szImgName[] = "Ghostscript Image";
#if defined(_MSC_VER) && defined(__WIN32__)
#define _export
#else
-#define max(a,b) ( (a>b) ? a : b )
-#define min(a,b) ( (a<b) ? a : b )
+ /* Define min and max, but make sure to use the identical definition */
+ /* to the one that all the compilers seem to have.... */
+# ifndef min
+# define min(a, b) (((a) < (b)) ? (a) : (b))
+# endif
+# ifndef max
+# define max(a, b) (((a) > (b)) ? (a) : (b))
+# endif
#endif
// Forward references
diff --git a/gs/src/dwtext.cpp b/gs/src/dwtext.cpp
index f0645b2df..5b7a00af2 100644
--- a/gs/src/dwtext.cpp
+++ b/gs/src/dwtext.cpp
@@ -37,8 +37,14 @@
#if defined(_MSC_VER) && defined(__WIN32__)
#define _export
#else
-#define max(a,b) ( (a>b) ? a : b )
-#define min(a,b) ( (a<b) ? a : b )
+ /* Define min and max, but make sure to use the identical definition */
+ /* to the one that all the compilers seem to have.... */
+# ifndef min
+# define min(a, b) (((a) < (b)) ? (a) : (b))
+# endif
+# ifndef max
+# define max(a, b) (((a) > (b)) ? (a) : (b))
+# endif
#endif
#ifndef EOF
diff --git a/gs/src/echogs.c b/gs/src/echogs.c
index 06690d609..4eaff4e0d 100644
--- a/gs/src/echogs.c
+++ b/gs/src/echogs.c
@@ -22,7 +22,7 @@
#include <stdio.h>
/* Some brain-damaged environments (e.g. Sun) don't include */
/* prototypes for fputc/fputs in stdio.h! */
-extern int fputc(), fputs();
+extern int fputc(P2(int, FILE *)), fputs(P2(const char *, FILE *));
/* Some systems have time_t in sys/types.h rather than time.h. */
#include <sys/types.h>
@@ -78,12 +78,18 @@ extern int fputc(), fputs();
* which writes 'a b'.
*/
-static int hputc(), hputs();
+static int hputc(P2(int, FILE *)), hputs(P2(const char *, FILE *));
+int
main(int argc, char *argv[])
{
FILE *out = stdout;
- FILE *in;
+ /*
+ * The initialization in = 0 is unnecessary: in is only referenced if
+ * interact = 1, in which case in has always been initialized.
+ * We initialize in = 0 solely to pacify stupid compilers.
+ */
+ FILE *in = 0;
const char *extn = "";
char fmode[4];
#define FNSIZE 100
@@ -91,7 +97,8 @@ main(int argc, char *argv[])
char fname[FNSIZE];
int newline = 1;
int interact = 0;
- int (*eputc)() = fputc, (*eputs)() = fputs;
+ int (*eputc)(P2(int, FILE *)) = fputc;
+ int (*eputs)(P2(const char *, FILE *)) = fputs;
#define LINESIZE 1000
char line[LINESIZE];
char sw = 0, sp = 0, hexx = 0;
@@ -329,7 +336,7 @@ hputc(int ch, FILE * out)
}
static int
-hputs(char *str, FILE * out)
+hputs(const char *str, FILE * out)
{
while (*str)
hputc(*str++ & 0xff, out);
diff --git a/gs/src/files.h b/gs/src/files.h
index e1f732039..6e7b6c827 100644
--- a/gs/src/files.h
+++ b/gs/src/files.h
@@ -50,6 +50,8 @@ bool zis_stdin(P1(const stream *));
/* An invalid (closed) file. */
#define avm_invalid_file_entry avm_foreign
extern stream *const invalid_file_entry;
+/* Make an invalid file object. */
+void make_invalid_file(P1(ref *));
/*
* Macros for checking file validity.
@@ -119,20 +121,26 @@ extern const uint file_default_buffer_size;
FILE *lib_fopen(P1(const char *));
/* for imain.c */
-int lib_file_open(P6(const char *, uint, byte *, uint, uint *, ref *));
+int lib_file_open(P7(const char *, uint, byte *, uint, uint *, ref *,
+ gs_memory_t *));
- /* for iccinit.c */
-int file_read_string(P3(const byte *, uint, ref *));
+ /* for imain.c */
+#ifndef gs_ref_memory_DEFINED
+# define gs_ref_memory_DEFINED
+typedef struct gs_ref_memory_s gs_ref_memory_t;
+#endif
+int file_read_string(P4(const byte *, uint, ref *, gs_ref_memory_t *));
/* for os_open in ziodev.c */
#ifdef iodev_proc_fopen /* in gxiodev.h */
-int file_open_stream(P6(const char *, uint, const char *, uint,
- stream **, iodev_proc_fopen_t));
-
+int file_open_stream(P7(const char *, uint, const char *, uint,
+ stream **, iodev_proc_fopen_t, gs_memory_t *));
#endif
+
/* for zfilter.c */
-int filter_open(P6(const char *, uint, ref *, const stream_procs *,
- const stream_template *, const stream_state *));
+int filter_open(P7(const char *, uint, ref *, const stream_procs *,
+ const stream_template *, const stream_state *,
+ gs_memory_t *));
/* for zfileio.c */
void make_stream_file(P3(ref *, stream *, const char *));
diff --git a/gs/src/gconf.c b/gs/src/gconf.c
index dc15d299a..c0ae19f69 100644
--- a/gs/src/gconf.c
+++ b/gs/src/gconf.c
@@ -62,12 +62,12 @@
/* ---------------- Resources (devices, inits, IODevices) ---------------- */
/* Declare devices, image types, init procedures, and IODevices as extern. */
-#define device_(dev) extern far_data gx_device dev;
+#define device_(dev) extern gx_device dev;
#define device2_(dev) extern const gx_device dev;
#define halftone_(dht) extern const gx_device_halftone_resource_t *dht(P0());
#define image_class_(cls) extern iclass_proc(cls);
#define image_type_(i,type) extern const gx_image_type_t type;
-#define init_(proc) extern void proc(P1(gs_memory_t *));
+#define init_(proc) extern init_proc(proc);
#define io_device_(iodev) extern const gx_io_device iodev;
#include "gconf.h"
#undef io_device_
diff --git a/gs/src/gdevbbox.c b/gs/src/gdevbbox.c
index a454e72d0..34e0ede51 100644
--- a/gs/src/gdevbbox.c
+++ b/gs/src/gdevbbox.c
@@ -79,18 +79,22 @@ private dev_proc_text_begin(bbox_text_begin);
*/
#define MAX_COORD (max_int_in_fixed - 1000)
#define MAX_RESOLUTION 4000
-gx_device_bbox far_data gs_bbox_device =
+gx_device_bbox gs_bbox_device =
{
- std_device_std_body(gx_device_bbox, 0, "bbox",
+ /*
+ * Define the device as 8-bit gray scale to avoid computing halftones.
+ */
+ std_device_dci_body(gx_device_bbox, 0, "bbox",
MAX_COORD, MAX_COORD,
- MAX_RESOLUTION, MAX_RESOLUTION),
+ MAX_RESOLUTION, MAX_RESOLUTION,
+ 1, 8, 255, 0, 256, 1),
{bbox_open_device,
NULL, /* get_initial_matrix */
NULL, /* sync_output */
bbox_output_page,
bbox_close_device,
- gx_forward_map_rgb_color, /* (needed for remapping black/white) */
- NULL, /* map_color_rgb */
+ gx_default_gray_map_rgb_color,
+ gx_default_gray_map_color_rgb,
bbox_fill_rectangle,
NULL, /* tile_rectangle */
bbox_copy_mono,
@@ -99,10 +103,10 @@ gx_device_bbox far_data gs_bbox_device =
NULL, /* get_bits */
bbox_get_params,
bbox_put_params,
- gx_forward_map_cmyk_color, /* (needed for remapping black/white) */
+ gx_default_map_cmyk_color,
NULL, /* get_xfont_procs */
NULL, /* get_xfont_device */
- NULL, /* map_rgb_alpha_color */
+ gx_default_map_rgb_alpha_color,
gx_page_device_get_page_device,
NULL, /* get_alpha_bits */
bbox_copy_alpha,
@@ -123,7 +127,7 @@ gx_device_bbox far_data gs_bbox_device =
NULL, /* get_clipping_box */
bbox_begin_typed_image,
NULL, /* get_bits_rectangle */
- NULL, /* map_color_rgb_alpha */
+ gx_default_map_color_rgb_alpha,
bbox_create_compositor,
NULL, /* get_hardware_params */
bbox_text_begin
@@ -136,6 +140,72 @@ gx_device_bbox far_data gs_bbox_device =
#undef MAX_COORD
#undef MAX_RESOLUTION
+/* Default box procedures */
+
+bool
+bbox_default_init_box(void *pdata)
+{
+ gx_device_bbox *const bdev = (gx_device_bbox *)pdata;
+ gs_fixed_rect *const pr = &bdev->bbox;
+
+ pr->p.x = pr->p.y = max_fixed;
+ pr->q.x = pr->q.y = min_fixed;
+ return bdev->white != bdev->transparent;
+}
+#define BBOX_INIT_BOX(bdev)\
+ bdev->box_procs.init_box(bdev->box_proc_data)
+
+void
+bbox_default_get_box(const void *pdata, gs_fixed_rect *pbox)
+{
+ const gx_device_bbox *const bdev = (const gx_device_bbox *)pdata;
+
+ *pbox = bdev->bbox;
+}
+#define BBOX_GET_BOX(bdev, pbox)\
+ bdev->box_procs.get_box(bdev->box_proc_data, pbox);
+
+void
+bbox_default_add_rect(void *pdata, fixed x0, fixed y0, fixed x1, fixed y1)
+{
+ gx_device_bbox *const bdev = (gx_device_bbox *)pdata;
+ gs_fixed_rect *const pr = &bdev->bbox;
+
+ if (x0 < pr->p.x)
+ pr->p.x = x0;
+ if (y0 < pr->p.y)
+ pr->p.y = y0;
+ if (x1 > pr->q.x)
+ pr->q.x = x1;
+ if (y1 > pr->q.y)
+ pr->q.y = y1;
+}
+#define BBOX_ADD_RECT(bdev, x0, y0, x1, y1)\
+ bdev->box_procs.add_rect(bdev->box_proc_data, x0, y0, x1, y1)
+#define BBOX_ADD_INT_RECT(bdev, x0, y0, x1, y1)\
+ BBOX_ADD_RECT(bdev, int2fixed(x0), int2fixed(y0), int2fixed(x1),\
+ int2fixed(y1))
+
+bool
+bbox_default_in_rect(const void *pdata, const gs_fixed_rect *pbox)
+{
+ const gx_device_bbox *const bdev = (const gx_device_bbox *)pdata;
+
+ return rect_within(*pbox, bdev->bbox);
+}
+#define BBOX_IN_RECT(bdev, pbox)\
+ bdev->box_procs.in_rect(bdev->box_proc_data, pbox)
+
+private const gx_device_bbox_procs_t box_procs_default = {
+ bbox_default_init_box, bbox_default_get_box, bbox_default_add_rect,
+ bbox_default_in_rect
+};
+
+#define RECT_IS_PAGE(dev, x, y, w, h)\
+ (x <= 0 && y <= 0 && x + w >= dev->width && y + h >= dev->height)
+
+ /* ---------------- Open/close/page ---------------- */
+
/* Copy device parameters back from the target. */
private void
bbox_copy_params(gx_device_bbox * bdev, bool remap_colors)
@@ -147,11 +217,13 @@ bbox_copy_params(gx_device_bbox * bdev, bool remap_colors)
if (remap_colors) {
bdev->black = gx_device_black((gx_device *)bdev);
bdev->white = gx_device_white((gx_device *)bdev);
+ bdev->transparent =
+ (bdev->white_is_opaque ? gx_no_color_index : bdev->white);
}
}
-#define GX_DC_IS_WHITE(pdevc, bdev)\
- (gx_dc_is_pure(pdevc) && gx_dc_pure_color(pdevc) == (bdev)->white)
+#define GX_DC_IS_TRANSPARENT(pdevc, bdev)\
+ (gx_dc_pure_color(pdevc) == (bdev)->transparent && gx_dc_is_pure(pdevc))
private int
bbox_close_device(gx_device * dev)
@@ -159,7 +231,7 @@ bbox_close_device(gx_device * dev)
gx_device_bbox *const bdev = (gx_device_bbox *) dev;
gx_device *tdev = bdev->target;
- if ((gx_device *) bdev->box_device != dev) {
+ if (bdev->box_procs.init_box != box_procs_default.init_box) {
/*
* This device was created as a wrapper for a compositor.
* Just free the devices.
@@ -173,41 +245,6 @@ bbox_close_device(gx_device * dev)
}
}
-/* Bounding box utilities */
-
-private void
-bbox_initialize(gs_fixed_rect * pr)
-{
- pr->p.x = pr->p.y = max_fixed;
- pr->q.x = pr->q.y = min_fixed;
-}
-
-private void
-bbox_add_rect(gs_fixed_rect * pr, fixed x0, fixed y0, fixed x1, fixed y1)
-{
- if (x0 < pr->p.x)
- pr->p.x = x0;
- if (y0 < pr->p.y)
- pr->p.y = y0;
- if (x1 > pr->q.x)
- pr->q.x = x1;
- if (y1 > pr->q.y)
- pr->q.y = y1;
-}
-private void
-bbox_add_point(gs_fixed_rect * pr, fixed x, fixed y)
-{
- bbox_add_rect(pr, x, y, x, y);
-}
-#define BBOX_ADD_INT_RECT(pr, x0, y0, x1, y1)\
- bbox_add_rect(pr, int2fixed(x0), int2fixed(y0), int2fixed(x1),\
- int2fixed(y1))
-
-#define RECT_IS_PAGE(dev, x, y, w, h)\
- (x <= 0 && y <= 0 && w >= x + dev->width && h >= y + dev->height)
-
- /* ---------------- Open/close/page ---------------- */
-
/* Initialize a bounding box device. */
void
gx_device_bbox_init(gx_device_bbox * dev, gx_device * target)
@@ -215,8 +252,16 @@ gx_device_bbox_init(gx_device_bbox * dev, gx_device * target)
gx_device_init((gx_device *) dev, (const gx_device *)&gs_bbox_device,
(target ? target->memory : NULL), true);
gx_device_forward_fill_in_procs((gx_device_forward *) dev);
- gx_device_set_target((gx_device_forward *)dev, target);
- dev->box_device = dev;
+ if (target) {
+ set_dev_proc(dev, map_rgb_color, gx_forward_map_rgb_color);
+ set_dev_proc(dev, map_color_rgb, gx_forward_map_color_rgb);
+ set_dev_proc(dev, map_cmyk_color, gx_forward_map_cmyk_color);
+ set_dev_proc(dev, map_rgb_alpha_color, gx_forward_map_rgb_alpha_color);
+ set_dev_proc(dev, map_color_rgb_alpha, gx_forward_map_color_rgb_alpha);
+ gx_device_set_target((gx_device_forward *)dev, target);
+ }
+ dev->box_procs = box_procs_default;
+ dev->box_proc_data = dev;
bbox_copy_params(dev, false);
dev->free_standing = false; /* being used as a component */
}
@@ -228,6 +273,15 @@ gx_device_bbox_fwd_open_close(gx_device_bbox * dev, bool forward_open_close)
dev->forward_open_close = forward_open_close;
}
+/* Set whether a bounding box device considers white to be opaque. */
+void
+gx_device_bbox_set_white_opaque(gx_device_bbox *bdev, bool white_is_opaque)
+{
+ bdev->white_is_opaque = white_is_opaque;
+ bdev->transparent =
+ (bdev->white_is_opaque ? gx_no_color_index : bdev->white);
+}
+
/* Release a bounding box device. */
void
gx_device_bbox_release(gx_device_bbox *dev)
@@ -240,26 +294,25 @@ gx_device_bbox_release(gx_device_bbox *dev)
void
gx_device_bbox_bbox(gx_device_bbox * dev, gs_rect * pbbox)
{
- const gx_device_bbox *const bbdev = dev->box_device;
+ gs_fixed_rect bbox;
- if (bbdev->bbox.p.x > bbdev->bbox.q.x ||
- bbdev->bbox.p.y > bbdev->bbox.q.y) {
+ BBOX_GET_BOX(dev, &bbox);
+ if (bbox.p.x > bbox.q.x || bbox.p.y > bbox.q.y) {
/* Nothing has been written on this page. */
pbbox->p.x = pbbox->p.y = pbbox->q.x = pbbox->q.y = 0;
} else {
gs_rect dbox;
gs_matrix mat;
- dbox.p.x = fixed2float(bbdev->bbox.p.x);
- dbox.p.y = fixed2float(bbdev->bbox.p.y);
- dbox.q.x = fixed2float(bbdev->bbox.q.x);
- dbox.q.y = fixed2float(bbdev->bbox.q.y);
+ dbox.p.x = fixed2float(bbox.p.x);
+ dbox.p.y = fixed2float(bbox.p.y);
+ dbox.q.x = fixed2float(bbox.q.x);
+ dbox.q.y = fixed2float(bbox.q.y);
gs_deviceinitialmatrix((gx_device *)dev, &mat);
gs_bbox_transform_inverse(&dbox, &mat, pbbox);
}
}
-
private int
bbox_open_device(gx_device * dev)
{
@@ -267,10 +320,11 @@ bbox_open_device(gx_device * dev)
if (bdev->free_standing) {
gx_device_forward_fill_in_procs((gx_device_forward *) dev);
- bdev->box_device = bdev;
+ bdev->box_procs = box_procs_default;
+ bdev->box_proc_data = bdev;
}
- if (bdev->box_device == bdev)
- bbox_initialize(&bdev->bbox);
+ if (bdev->box_procs.init_box == box_procs_default.init_box)
+ BBOX_INIT_BOX(bdev);
/* gx_forward_open_device doesn't exist */
{
gx_device *tdev = bdev->target;
@@ -310,20 +364,20 @@ bbox_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
gx_color_index color)
{
gx_device_bbox *const bdev = (gx_device_bbox *) dev;
- gx_device_bbox *const bbdev = bdev->box_device;
-
- /* Check for erasing the entire page. */
- if (RECT_IS_PAGE(dev, x, y, w, h))
- bbox_initialize(&bbdev->bbox);
- else if (color != bdev->white)
- BBOX_ADD_INT_RECT(&bbdev->bbox, x, y, x + w, y + h);
+ gx_device *tdev = bdev->target;
/* gx_forward_fill_rectangle doesn't exist */
- {
- gx_device *tdev = bdev->target;
+ int code =
+ (tdev == 0 ? 0 :
+ dev_proc(tdev, fill_rectangle)(tdev, x, y, w, h, color));
- return (tdev == 0 ? 0 :
- (*dev_proc(tdev, fill_rectangle)) (tdev, x, y, w, h, color));
+ /* Check for erasing the entire page. */
+ if (RECT_IS_PAGE(dev, x, y, w, h)) {
+ if (!BBOX_INIT_BOX(bdev))
+ return code;
}
+ if (color != bdev->transparent)
+ BBOX_ADD_INT_RECT(bdev, x, y, x + w, y + h);
+ return code;
}
private int
@@ -332,20 +386,18 @@ bbox_copy_mono(gx_device * dev, const byte * data,
gx_color_index zero, gx_color_index one)
{
gx_device_bbox *const bdev = (gx_device_bbox *) dev;
- gx_device_bbox *const bbdev = bdev->box_device;
-
- if ((one != gx_no_color_index && one != bdev->white) ||
- (zero != gx_no_color_index && zero != bdev->white)
- )
- BBOX_ADD_INT_RECT(&bbdev->bbox, x, y, x + w, y + h);
/* gx_forward_copy_mono doesn't exist */
- {
- gx_device *tdev = bdev->target;
+ gx_device *tdev = bdev->target;
+ int code =
+ (tdev == 0 ? 0 :
+ dev_proc(tdev, copy_mono)
+ (tdev, data, dx, raster, id, x, y, w, h, zero, one));
- return (tdev == 0 ? 0 :
- (*dev_proc(tdev, copy_mono))
- (tdev, data, dx, raster, id, x, y, w, h, zero, one));
- }
+ if ((one != gx_no_color_index && one != bdev->transparent) ||
+ (zero != gx_no_color_index && zero != bdev->transparent)
+ )
+ BBOX_ADD_INT_RECT(bdev, x, y, x + w, y + h);
+ return code;
}
private int
@@ -353,17 +405,15 @@ bbox_copy_color(gx_device * dev, const byte * data,
int dx, int raster, gx_bitmap_id id, int x, int y, int w, int h)
{
gx_device_bbox *const bdev = (gx_device_bbox *) dev;
- gx_device_bbox *const bbdev = bdev->box_device;
-
- BBOX_ADD_INT_RECT(&bbdev->bbox, x, y, x + w, y + h);
/* gx_forward_copy_color doesn't exist */
- {
- gx_device *tdev = bdev->target;
+ gx_device *tdev = bdev->target;
+ int code =
+ (tdev == 0 ? 0 :
+ dev_proc(tdev, copy_color)
+ (tdev, data, dx, raster, id, x, y, w, h));
- return (tdev == 0 ? 0 :
- (*dev_proc(tdev, copy_color))
- (tdev, data, dx, raster, id, x, y, w, h));
- }
+ BBOX_ADD_INT_RECT(bdev, x, y, x + w, y + h);
+ return code;
}
private int
@@ -372,17 +422,15 @@ bbox_copy_alpha(gx_device * dev, const byte * data, int data_x,
gx_color_index color, int depth)
{
gx_device_bbox *const bdev = (gx_device_bbox *) dev;
- gx_device_bbox *const bbdev = bdev->box_device;
-
- BBOX_ADD_INT_RECT(&bbdev->bbox, x, y, x + w, y + h);
/* gx_forward_copy_alpha doesn't exist */
- {
- gx_device *tdev = bdev->target;
+ gx_device *tdev = bdev->target;
+ int code =
+ (tdev == 0 ? 0 :
+ dev_proc(tdev, copy_alpha)
+ (tdev, data, data_x, raster, id, x, y, w, h, color, depth));
- return (tdev == 0 ? 0 :
- (*dev_proc(tdev, copy_alpha))
- (tdev, data, data_x, raster, id, x, y, w, h, color, depth));
- }
+ BBOX_ADD_INT_RECT(bdev, x, y, x + w, y + h);
+ return code;
}
private int
@@ -391,20 +439,19 @@ bbox_strip_tile_rectangle(gx_device * dev, const gx_strip_bitmap * tiles,
int px, int py)
{
gx_device_bbox *const bdev = (gx_device_bbox *) dev;
- gx_device_bbox *const bbdev = bdev->box_device;
-
- if (RECT_IS_PAGE(dev, x, y, w, h))
- bbox_initialize(&bbdev->bbox);
- else
- BBOX_ADD_INT_RECT(&bbdev->bbox, x, y, x + w, y + h);
/* Skip the call if there is no target. */
- {
- gx_device *tdev = bdev->target;
+ gx_device *tdev = bdev->target;
+ int code =
+ (tdev == 0 ? 0 :
+ dev_proc(tdev, strip_tile_rectangle)
+ (tdev, tiles, x, y, w, h, color0, color1, px, py));
- return (tdev == 0 ? 0 :
- (*dev_proc(tdev, strip_tile_rectangle))
- (tdev, tiles, x, y, w, h, color0, color1, px, py));
+ if (RECT_IS_PAGE(dev, x, y, w, h)) {
+ if (!BBOX_INIT_BOX(bdev))
+ return code;
}
+ BBOX_ADD_INT_RECT(bdev, x, y, x + w, y + h);
+ return code;
}
private int
@@ -418,18 +465,16 @@ bbox_strip_copy_rop(gx_device * dev,
int phase_x, int phase_y, gs_logical_operation_t lop)
{
gx_device_bbox *const bdev = (gx_device_bbox *) dev;
- gx_device_bbox *const bbdev = bdev->box_device;
-
- BBOX_ADD_INT_RECT(&bbdev->bbox, x, y, x + w, y + h);
/* gx_forward_strip_copy_rop doesn't exist */
- {
- gx_device *tdev = bdev->target;
+ gx_device *tdev = bdev->target;
+ int code =
+ (tdev == 0 ? 0 :
+ dev_proc(tdev, strip_copy_rop)
+ (tdev, sdata, sourcex, sraster, id, scolors,
+ textures, tcolors, x, y, w, h, phase_x, phase_y, lop));
- return (tdev == 0 ? 0 :
- (*dev_proc(tdev, strip_copy_rop))
- (tdev, sdata, sourcex, sraster, id, scolors,
- textures, tcolors, x, y, w, h, phase_x, phase_y, lop));
- }
+ BBOX_ADD_INT_RECT(bdev, x, y, x + w, y + h);
+ return code;
}
/* ---------------- Parameters ---------------- */
@@ -439,7 +484,7 @@ private int
bbox_get_params(gx_device * dev, gs_param_list * plist)
{
gx_device_bbox *const bdev = (gx_device_bbox *) dev;
- const gx_device_bbox *bbdev = bdev->box_device;
+ gs_fixed_rect fbox;
int code = gx_forward_get_params(dev, plist);
gs_param_float_array bba;
float bbox[4];
@@ -448,14 +493,16 @@ bbox_get_params(gx_device * dev, gs_param_list * plist)
return code;
/*
* We might be calling get_params before the device has been
- * initialized: in this case, bbdev = 0.
+ * initialized: in this case, box_proc_data = 0.
*/
- if (bbdev == 0)
- bbdev = (const gx_device_bbox *)dev;
- bbox[0] = fixed2float(bbdev->bbox.p.x);
- bbox[1] = fixed2float(bbdev->bbox.p.y);
- bbox[2] = fixed2float(bbdev->bbox.q.x);
- bbox[3] = fixed2float(bbdev->bbox.q.y);
+ if (bdev->box_proc_data == 0)
+ fbox = bdev->bbox;
+ else
+ BBOX_GET_BOX(bdev, &fbox);
+ bbox[0] = fixed2float(fbox.p.x);
+ bbox[1] = fixed2float(fbox.p.y);
+ bbox[2] = fixed2float(fbox.q.x);
+ bbox[3] = fixed2float(fbox.q.y);
bba.data = bbox, bba.size = 4, bba.persistent = false;
return param_write_float_array(plist, "PageBoundingBox", &bba);
}
@@ -492,12 +539,9 @@ bbox_put_params(gx_device * dev, gs_param_list * plist)
if (ecode < 0)
code = ecode;
if (code >= 0 && bba.data != 0) {
- gx_device_bbox *const bbdev = bdev->box_device;
-
- bbdev->bbox.p.x = float2fixed(bba.data[0]);
- bbdev->bbox.p.y = float2fixed(bba.data[1]);
- bbdev->bbox.q.x = float2fixed(bba.data[2]);
- bbdev->bbox.q.y = float2fixed(bba.data[3]);
+ BBOX_INIT_BOX(bdev);
+ BBOX_ADD_RECT(bdev, float2fixed(bba.data[0]), float2fixed(bba.data[1]),
+ float2fixed(bba.data[2]), float2fixed(bba.data[3]));
}
bbox_copy_params(bdev, true);
return code;
@@ -516,41 +560,39 @@ private int
bbox_fill_trapezoid(gx_device * dev,
const gs_fixed_edge * left, const gs_fixed_edge * right,
fixed ybot, fixed ytop, bool swap_axes,
- const gx_device_color * pdevc, gs_logical_operation_t lop)
+ const gx_device_color * pdevc, gs_logical_operation_t lop)
{
gx_device_bbox *const bdev = (gx_device_bbox *) dev;
+ /* Skip the call if there is no target. */
+ gx_device *tdev = bdev->target;
+ int code =
+ (tdev == 0 ? 0 :
+ dev_proc(tdev, fill_trapezoid)
+ (tdev, left, right, ybot, ytop, swap_axes, pdevc, lop));
- if (!GX_DC_IS_WHITE(pdevc, bdev)) {
- gx_device_bbox *const bbdev = bdev->box_device;
+ if (!GX_DC_IS_TRANSPARENT(pdevc, bdev)) {
fixed x0l =
- (left->start.y == ybot ? left->start.x :
- edge_x_at_y(left, ybot));
+ (left->start.y == ybot ? left->start.x :
+ edge_x_at_y(left, ybot));
fixed x1l =
- (left->end.y == ytop ? left->end.x :
- edge_x_at_y(left, ytop));
+ (left->end.y == ytop ? left->end.x :
+ edge_x_at_y(left, ytop));
fixed x0r =
- (right->start.y == ybot ? right->start.x :
- edge_x_at_y(right, ybot));
+ (right->start.y == ybot ? right->start.x :
+ edge_x_at_y(right, ybot));
fixed x1r =
- (right->end.y == ytop ? right->end.x :
- edge_x_at_y(right, ytop));
+ (right->end.y == ytop ? right->end.x :
+ edge_x_at_y(right, ytop));
fixed xminl = min(x0l, x1l), xmaxl = max(x0l, x1l);
fixed xminr = min(x0r, x1r), xmaxr = max(x0r, x1r);
fixed x0 = min(xminl, xminr), x1 = max(xmaxl, xmaxr);
if (swap_axes)
- bbox_add_rect(&bbdev->bbox, ybot, x0, ytop, x1);
+ BBOX_ADD_RECT(bdev, ybot, x0, ytop, x1);
else
- bbox_add_rect(&bbdev->bbox, x0, ybot, x1, ytop);
- }
- /* Skip the call if there is no target. */
- {
- gx_device *tdev = bdev->target;
-
- return (tdev == 0 ? 0 :
- (*dev_proc(tdev, fill_trapezoid))
- (tdev, left, right, ybot, ytop, swap_axes, pdevc, lop));
+ BBOX_ADD_RECT(bdev, x0, ybot, x1, ytop);
}
+ return code;
}
private int
@@ -560,67 +602,104 @@ bbox_fill_parallelogram(gx_device * dev,
gs_logical_operation_t lop)
{
gx_device_bbox *const bdev = (gx_device_bbox *) dev;
-
- if (!GX_DC_IS_WHITE(pdevc, bdev)) {
- gx_device_bbox *const bbdev = bdev->box_device;
- fixed pax = px + ax, pay = py + ay;
-
- bbox_add_rect(&bbdev->bbox, px, py, px + bx, py + by);
- bbox_add_rect(&bbdev->bbox, pax, pay, pax + bx, pay + by);
- }
/* Skip the call if there is no target. */
- {
- gx_device *tdev = bdev->target;
-
- return (tdev == 0 ? 0 :
- (*dev_proc(tdev, fill_parallelogram))
- (tdev, px, py, ax, ay, bx, by, pdevc, lop));
+ gx_device *tdev = bdev->target;
+ int code =
+ (tdev == 0 ? 0 :
+ dev_proc(tdev, fill_parallelogram)
+ (tdev, px, py, ax, ay, bx, by, pdevc, lop));
+
+ if (!GX_DC_IS_TRANSPARENT(pdevc, bdev)) {
+ fixed xmin, ymin, xmax, ymax;
+
+ /* bbox_add_rect requires points in correct order. */
+#define SET_MIN_MAX(vmin, vmax, av, bv)\
+ BEGIN\
+ if (av <= 0) {\
+ if (bv <= 0)\
+ vmin = av + bv, vmax = 0;\
+ else\
+ vmin = av, vmax = bv;\
+ } else if (bv <= 0)\
+ vmin = bv, vmax = av;\
+ else\
+ vmin = 0, vmax = av + bv;\
+ END
+ SET_MIN_MAX(xmin, xmax, ax, bx);
+ SET_MIN_MAX(ymin, ymax, ay, by);
+#undef SET_MIN_MAX
+ BBOX_ADD_RECT(bdev, px + xmin, py + ymin, px + xmax, py + ymax);
}
+ return code;
}
private int
bbox_fill_triangle(gx_device * dev,
- fixed px, fixed py, fixed ax, fixed ay, fixed bx, fixed by,
+ fixed px, fixed py, fixed ax, fixed ay, fixed bx, fixed by,
const gx_device_color * pdevc, gs_logical_operation_t lop)
{
gx_device_bbox *const bdev = (gx_device_bbox *) dev;
-
- if (!GX_DC_IS_WHITE(pdevc, bdev)) {
- gx_device_bbox *const bbdev = bdev->box_device;
-
- bbox_add_rect(&bbdev->bbox, px, py, px + bx, py + by);
- bbox_add_point(&bbdev->bbox, px + ax, py + ay);
- }
/* Skip the call if there is no target. */
- {
- gx_device *tdev = bdev->target;
-
- return (tdev == 0 ? 0 :
- (*dev_proc(tdev, fill_triangle))
- (tdev, px, py, ax, ay, bx, by, pdevc, lop));
+ gx_device *tdev = bdev->target;
+ int code =
+ (tdev == 0 ? 0 :
+ dev_proc(tdev, fill_triangle)
+ (tdev, px, py, ax, ay, bx, by, pdevc, lop));
+
+ if (!GX_DC_IS_TRANSPARENT(pdevc, bdev)) {
+ fixed xmin, ymin, xmax, ymax;
+
+ /* bbox_add_rect requires points in correct order. */
+#define SET_MIN_MAX(vmin, vmax, av, bv)\
+ BEGIN\
+ if (av <= 0) {\
+ if (bv <= 0)\
+ vmin = min(av, bv), vmax = 0;\
+ else\
+ vmin = av, vmax = bv;\
+ } else if (bv <= 0)\
+ vmin = bv, vmax = av;\
+ else\
+ vmin = 0, vmax = max(av, bv);\
+ END
+ SET_MIN_MAX(xmin, xmax, ax, bx);
+ SET_MIN_MAX(ymin, ymax, ay, by);
+#undef SET_MIN_MAX
+ BBOX_ADD_RECT(bdev, px + xmin, py + ymin, px + xmax, py + ymax);
}
+ return code;
}
private int
bbox_draw_thin_line(gx_device * dev,
fixed fx0, fixed fy0, fixed fx1, fixed fy1,
- const gx_device_color * pdevc, gs_logical_operation_t lop)
+ const gx_device_color * pdevc, gs_logical_operation_t lop)
{
gx_device_bbox *const bdev = (gx_device_bbox *) dev;
-
- if (!GX_DC_IS_WHITE(pdevc, bdev)) {
- gx_device_bbox *const bbdev = bdev->box_device;
-
- bbox_add_rect(&bbdev->bbox, fx0, fy0, fx1, fy1);
- }
/* Skip the call if there is no target. */
- {
- gx_device *tdev = bdev->target;
-
- return (tdev == 0 ? 0 :
- (*dev_proc(tdev, draw_thin_line))
- (tdev, fx0, fy0, fx1, fy0, pdevc, lop));
+ gx_device *tdev = bdev->target;
+ int code =
+ (tdev == 0 ? 0 :
+ dev_proc(tdev, draw_thin_line)
+ (tdev, fx0, fy0, fx1, fy0, pdevc, lop));
+
+ if (!GX_DC_IS_TRANSPARENT(pdevc, bdev)) {
+ fixed xmin, ymin, xmax, ymax;
+
+ /* bbox_add_rect requires points in correct order. */
+#define SET_MIN_MAX(vmin, vmax, av, bv)\
+ BEGIN\
+ if (av < bv)\
+ vmin = av, vmax = bv;\
+ else\
+ vmin = bv, vmax = av;\
+ END
+ SET_MIN_MAX(xmin, xmax, fx0, fx1);
+ SET_MIN_MAX(ymin, ymax, fy0, fy1);
+#undef SET_MIN_MAX
+ BBOX_ADD_RECT(bdev, xmin, ymin, xmax, ymax);
}
+ return code;
}
/* ---------------- High-level drawing ---------------- */
@@ -636,8 +715,12 @@ bbox_fill_path(gx_device * dev, const gs_imager_state * pis, gx_path * ppath,
{
gx_device_bbox *const bdev = (gx_device_bbox *) dev;
gx_device *tdev = bdev->target;
+ dev_proc_fill_path((*fill_path)) =
+ (tdev == 0 ? dev_proc(&gs_null_device, fill_path) :
+ dev_proc(tdev, fill_path));
+ int code;
- if (!GX_DC_IS_WHITE(pdevc, bdev) && !gx_path_is_void(ppath)) {
+ if (!GX_DC_IS_TRANSPARENT(pdevc, bdev) && !gx_path_is_void(ppath)) {
gs_fixed_rect ibox;
gs_fixed_point adjust;
@@ -647,27 +730,42 @@ bbox_fill_path(gx_device * dev, const gs_imager_state * pis, gx_path * ppath,
if (params->fill_zero_width)
gx_adjust_if_empty(&ibox, &adjust);
adjust_box(&ibox, adjust);
+ /*
+ * If the path lies within the already accumulated box, just draw
+ * on the target.
+ */
+ if (BBOX_IN_RECT(bdev, &ibox))
+ return fill_path(tdev, pis, ppath, params, pdevc, pcpath);
+ /*
+ * If the target uses the default algorithm, just draw on the
+ * bbox device.
+ */
+ if (tdev != 0 && fill_path == gx_default_fill_path)
+ return fill_path(dev, pis, ppath, params, pdevc, pcpath);
+ /* Draw on the target now. */
+ code = fill_path(dev, pis, ppath, params, pdevc, pcpath);
+ if (code < 0)
+ return code;
if (pcpath != NULL &&
!gx_cpath_includes_rectangle(pcpath, ibox.p.x, ibox.p.y,
ibox.q.x, ibox.q.y)
) {
- /* Let the target do the drawing, but break down the */
- /* fill path into pieces for computing the bounding box. */
+ /*
+ * Let the target do the drawing, but break down the
+ * fill path into pieces for computing the bounding box.
+ */
gx_drawing_color devc;
color_set_pure(&devc, bdev->black); /* any non-white color will do */
bdev->target = NULL;
- gx_default_fill_path(dev, pis, ppath, params, &devc, pcpath);
+ code = gx_default_fill_path(dev, pis, ppath, params, &devc, pcpath);
bdev->target = tdev;
} else { /* Just use the path bounding box. */
- bbox_add_rect(&bdev->bbox, ibox.p.x, ibox.p.y, ibox.q.x,
- ibox.q.y);
+ BBOX_ADD_RECT(bdev, ibox.p.x, ibox.p.y, ibox.q.x, ibox.q.y);
}
- }
- /* Skip the call if there is no target. */
- return (tdev == 0 ? 0 :
- (*dev_proc(tdev, fill_path))
- (tdev, pis, ppath, params, pdevc, pcpath));
+ return code;
+ } else
+ return fill_path(tdev, pis, ppath, params, pdevc, pcpath);
}
private int
@@ -677,8 +775,12 @@ bbox_stroke_path(gx_device * dev, const gs_imager_state * pis, gx_path * ppath,
{
gx_device_bbox *const bdev = (gx_device_bbox *) dev;
gx_device *tdev = bdev->target;
+ /* Skip the call if there is no target. */
+ int code =
+ (tdev == 0 ? 0 :
+ dev_proc(tdev, stroke_path)(tdev, pis, ppath, params, pdevc, pcpath));
- if (!GX_DC_IS_WHITE(pdevc, bdev)) {
+ if (!GX_DC_IS_TRANSPARENT(pdevc, bdev)) {
gs_fixed_rect ibox;
gs_fixed_point expand;
@@ -696,7 +798,7 @@ bbox_stroke_path(gx_device * dev, const gs_imager_state * pis, gx_path * ppath,
int code = 0;
if (spath)
- code = gx_stroke_add(ppath, spath, pis);
+ code = gx_imager_stroke_add(ppath, spath, dev, pis);
else
code = -1;
if (code >= 0)
@@ -722,16 +824,10 @@ bbox_stroke_path(gx_device * dev, const gs_imager_state * pis, gx_path * ppath,
bdev->target = tdev;
} else {
/* Just use the path bounding box. */
- gx_device_bbox *const bbdev = bdev->box_device;
-
- bbox_add_rect(&bbdev->bbox, ibox.p.x, ibox.p.y, ibox.q.x,
- ibox.q.y);
+ BBOX_ADD_RECT(bdev, ibox.p.x, ibox.p.y, ibox.q.x, ibox.q.y);
}
}
- /* Skip the call if there is no target. */
- return (tdev == 0 ? 0 :
- (*dev_proc(tdev, stroke_path))
- (tdev, pis, ppath, params, pdevc, pcpath));
+ return code;
}
private int
@@ -743,6 +839,12 @@ bbox_fill_mask(gx_device * dev,
{
gx_device_bbox *const bdev = (gx_device_bbox *) dev;
gx_device *tdev = bdev->target;
+ /* Skip the call if there is no target. */
+ int code =
+ (tdev == 0 ? 0 :
+ dev_proc(tdev, fill_mask)
+ (tdev, data, dx, raster, id, x, y, w, h,
+ pdcolor, depth, lop, pcpath));
if (pcpath != NULL &&
!gx_cpath_includes_rectangle(pcpath, int2fixed(x), int2fixed(y),
@@ -757,15 +859,9 @@ bbox_fill_mask(gx_device * dev,
bdev->target = tdev;
} else {
/* Just use the mask bounding box. */
- gx_device_bbox *const bbdev = bdev->box_device;
-
- BBOX_ADD_INT_RECT(&bbdev->bbox, x, y, x + w, y + h);
+ BBOX_ADD_INT_RECT(bdev, x, y, x + w, y + h);
}
- /* Skip the call if there is no target. */
- return (tdev == 0 ? 0 :
- (*dev_proc(tdev, fill_mask))
- (tdev, data, dx, raster, id, x, y, w, h,
- pdcolor, depth, lop, pcpath));
+ return code;
}
/* ------ Bitmap imaging ------ */
@@ -776,18 +872,23 @@ typedef struct bbox_image_enum_s {
gs_matrix matrix; /* map from image space to device space */
const gx_clip_path *pcpath;
gx_image_enum_common_t *target_info;
+ bool params_are_const;
int x0, x1;
int y, height;
} bbox_image_enum;
-gs_private_st_ptrs2(st_bbox_image_enum, bbox_image_enum, "bbox_image_enum",
-bbox_image_enum_enum_ptrs, bbox_image_enum_reloc_ptrs, pcpath, target_info);
+extern_st(st_gx_image_enum_common);
+gs_private_st_suffix_add2(st_bbox_image_enum, bbox_image_enum,
+ "bbox_image_enum", bbox_image_enum_enum_ptrs, bbox_image_enum_reloc_ptrs,
+ st_gx_image_enum_common, pcpath, target_info);
private image_enum_proc_plane_data(bbox_image_plane_data);
private image_enum_proc_end_image(bbox_image_end_image);
-private const gx_image_enum_procs_t bbox_image_enum_procs =
-{
- bbox_image_plane_data, bbox_image_end_image
+private image_enum_proc_flush(bbox_image_flush);
+private image_enum_proc_planes_wanted(bbox_image_planes_wanted);
+private const gx_image_enum_procs_t bbox_image_enum_procs = {
+ bbox_image_plane_data, bbox_image_end_image,
+ bbox_image_flush, bbox_image_planes_wanted
};
private int
@@ -814,6 +915,7 @@ bbox_image_begin(const gs_imager_state * pis, const gs_matrix * pmat,
pbe->matrix = mat;
pbe->pcpath = pcpath;
pbe->target_info = 0; /* in case no target */
+ pbe->params_are_const = false; /* check the first time */
if (prect) {
pbe->x0 = prect->p.x, pbe->x1 = prect->q.x;
pbe->y = prect->p.y, pbe->height = prect->q.y - prect->p.y;
@@ -833,7 +935,7 @@ bbox_image_begin(const gs_imager_state * pis, const gs_matrix * pmat,
}
private void
-bbox_image_copy_target_info(bbox_image_enum * pbe, gx_device_bbox * dev)
+bbox_image_copy_target_info(bbox_image_enum * pbe)
{
const gx_image_enum_common_t *target_info = pbe->target_info;
@@ -842,10 +944,6 @@ bbox_image_copy_target_info(bbox_image_enum * pbe, gx_device_bbox * dev)
pbe->num_planes * sizeof(pbe->plane_depths[0]));
memcpy(pbe->plane_widths, target_info->plane_widths,
pbe->num_planes * sizeof(pbe->plane_widths[0]));
- if (dev->target == 0) {
- gx_image_end(pbe->target_info, false);
- pbe->target_info = 0;
- }
}
private int
@@ -869,8 +967,8 @@ bbox_begin_typed_image(gx_device * dev,
{
gx_device_bbox *const bdev = (gx_device_bbox *) dev;
gx_device *tdev = bdev->target;
-
dev_proc_begin_typed_image((*begin_typed_image));
+ byte wanted[GS_IMAGE_MAX_PLANES];
if (tdev == 0) {
tdev = dev;
@@ -896,7 +994,9 @@ bbox_begin_typed_image(gx_device * dev,
0, gs_image_format_chunky);
if (code < 0)
return code;
- bbox_image_copy_target_info(pbe, bdev);
+ bbox_image_copy_target_info(pbe);
+ pbe->params_are_const =
+ gx_image_planes_wanted(pbe->target_info, wanted);
}
*pinfo = (gx_image_enum_common_t *) pbe;
return 0;
@@ -912,11 +1012,15 @@ bbox_image_plane_data(gx_image_enum_common_t * info,
gx_device *tdev = bdev->target;
bbox_image_enum *pbe = (bbox_image_enum *) info;
const gx_clip_path *pcpath = pbe->pcpath;
- int y_orig = pbe->y;
gs_rect sbox, dbox;
gs_point corners[4];
gs_fixed_rect ibox;
+ int code;
+ code = gx_image_plane_data_rows(pbe->target_info, planes, height,
+ rows_used);
+ if (code != 1 && !pbe->params_are_const)
+ bbox_image_copy_target_info(pbe);
sbox.p.x = pbe->x0;
sbox.p.y = pbe->y;
sbox.q.x = pbe->x1;
@@ -954,37 +1058,75 @@ bbox_image_plane_data(gx_image_enum_common_t * info,
bdev->target = tdev;
} else {
/* Just use the bounding box. */
- gx_device_bbox *const bbdev = bdev->box_device;
-
- bbox_add_rect(&bbdev->bbox, ibox.p.x, ibox.p.y, ibox.q.x, ibox.q.y);
+ BBOX_ADD_RECT(bdev, ibox.p.x, ibox.p.y, ibox.q.x, ibox.q.y);
}
- /* Skip the call if there is no target. */
- if (tdev == 0) {
- *rows_used = pbe->y - y_orig;
- return pbe->y >= pbe->height;
- }
- else
- return gx_image_plane_data_rows(pbe->target_info, planes, height,
- rows_used);
+ return code;
}
private int
bbox_image_end_image(gx_image_enum_common_t * info, bool draw_last)
{
- gx_device_bbox *const bdev = (gx_device_bbox *)info->dev;
bbox_image_enum *pbe = (bbox_image_enum *) info;
- void *target_info = pbe->target_info;
-
- /* Skip the call if there is no target. */
- gx_device *tdev = bdev->target;
- int code =
- (tdev == 0 ? 0 : gx_image_end(target_info, draw_last));
+ int code = gx_image_end(pbe->target_info, draw_last);
gs_free_object(pbe->memory, pbe, "bbox_end_image");
return code;
}
private int
+bbox_image_flush(gx_image_enum_common_t * info)
+{
+ bbox_image_enum *pbe = (bbox_image_enum *) info;
+ gx_image_enum_common_t *target_info = pbe->target_info;
+
+ return (target_info ? gx_image_flush(target_info) : 0);
+}
+
+private bool
+bbox_image_planes_wanted(const gx_image_enum_common_t * info, byte *wanted)
+{
+ /* This is only used if target_info != 0. */
+ const bbox_image_enum *pbe = (const bbox_image_enum *)info;
+
+ return gx_image_planes_wanted(pbe->target_info, wanted);
+}
+
+/* Compositing */
+
+private bool
+bbox_forward_init_box(void *pdata)
+{
+ gx_device_bbox *const bdev = (gx_device_bbox *)pdata;
+
+ return BBOX_INIT_BOX(bdev);
+}
+private void
+bbox_forward_get_box(const void *pdata, gs_fixed_rect *pbox)
+{
+ const gx_device_bbox *const bdev = (const gx_device_bbox *)pdata;
+
+ BBOX_GET_BOX(bdev, pbox);
+}
+private void
+bbox_forward_add_rect(void *pdata, fixed x0, fixed y0, fixed x1, fixed y1)
+{
+ gx_device_bbox *const bdev = (gx_device_bbox *)pdata;
+
+ BBOX_ADD_RECT(bdev, x0, y0, x1, y1);
+}
+private bool
+bbox_forward_in_rect(const void *pdata, const gs_fixed_rect *pbox)
+{
+ const gx_device_bbox *const bdev = (const gx_device_bbox *)pdata;
+
+ return BBOX_IN_RECT(bdev, pbox);
+}
+private const gx_device_bbox_procs_t box_procs_forward = {
+ bbox_forward_init_box, bbox_forward_get_box, bbox_forward_add_rect,
+ bbox_forward_in_rect
+};
+
+private int
bbox_create_compositor(gx_device * dev,
gx_device ** pcdev, const gs_composite_t * pcte,
const gs_imager_state * pis, gs_memory_t * memory)
@@ -1009,7 +1151,7 @@ bbox_create_compositor(gx_device * dev,
gx_device *cdev;
gx_device_bbox *bbcdev;
int code = (*dev_proc(target, create_compositor))
- (target, &cdev, pcte, pis, memory);
+ (target, &cdev, pcte, pis, memory);
if (code < 0)
return code;
@@ -1022,7 +1164,8 @@ bbox_create_compositor(gx_device * dev,
}
gx_device_bbox_init(bbcdev, target);
gx_device_set_target((gx_device_forward *)bbcdev, cdev);
- bbcdev->box_device = bdev;
+ bbcdev->box_procs = box_procs_forward;
+ bbcdev->box_proc_data = bdev;
*pcdev = (gx_device *) bbcdev;
return 0;
}
@@ -1041,19 +1184,38 @@ gs_private_st_suffix_add1(st_bbox_text_enum, bbox_text_enum, "bbox_text_enum",
bbox_text_enum_enum_ptrs, bbox_text_enum_reloc_ptrs,
st_gs_text_enum, target_info);
+private text_enum_proc_resync(bbox_text_resync);
private text_enum_proc_process(bbox_text_process);
+private text_enum_proc_is_width_only(bbox_text_is_width_only);
+private text_enum_proc_current_width(bbox_text_current_width);
private text_enum_proc_set_cache(bbox_text_set_cache);
+private text_enum_proc_retry(bbox_text_retry);
+private text_enum_proc_release(bbox_text_release);
private rc_free_proc(bbox_text_free);
private const gs_text_enum_procs_t bbox_text_procs =
{
- bbox_text_process, bbox_text_set_cache
+ bbox_text_resync, bbox_text_process, bbox_text_is_width_only,
+ bbox_text_current_width, bbox_text_set_cache, bbox_text_retry,
+ bbox_text_release
};
+private void
+bbox_text_enum_copy(bbox_text_enum *pbte)
+{
+ rc_header rc_save;
+
+ rc_save = pbte->rc;
+ *(gs_text_enum_t *)pbte = *pbte->target_info; /* copy common info */
+ pbte->rc = rc_save;
+ pbte->procs = &bbox_text_procs;
+}
+
private int
bbox_text_begin(gx_device * dev, gs_imager_state * pis,
- const gs_text_params_t * text, const gs_font * font,
-gx_path * path, const gx_device_color * pdcolor, const gx_clip_path * pcpath,
+ const gs_text_params_t * text, gs_font * font,
+ gx_path * path, const gx_device_color * pdcolor,
+ const gx_clip_path * pcpath,
gs_memory_t * memory, gs_text_enum_t ** ppenum)
{
gx_device_bbox *const bdev = (gx_device_bbox *) dev;
@@ -1076,32 +1238,55 @@ gx_path * path, const gx_device_color * pdcolor, const gx_clip_path * pcpath,
gs_free_object(memory, pbte, "bbox_text_begin");
return code;
}
- *(gs_text_enum_t *) pbte = *pbte->target_info; /* copy common info */
- pbte->procs = &bbox_text_procs;
+ bbox_text_enum_copy(pbte);
*ppenum = (gs_text_enum_t *) pbte;
return code;
}
private int
+bbox_text_resync(gs_text_enum_t *pte, const gs_text_enum_t *pfrom)
+{
+ bbox_text_enum *const pbte = (bbox_text_enum *) pte;
+ int code = gs_text_resync(pbte->target_info, pfrom);
+
+ if (code >= 0)
+ bbox_text_enum_copy(pbte);
+ return code;
+}
+
+private int
bbox_text_process(gs_text_enum_t * pte)
{
bbox_text_enum *const pbte = (bbox_text_enum *) pte;
int code = gs_text_process(pbte->target_info);
- if (code < 0)
- return code;
- /* Copy back the dynamic information for the client. */
- pte->index = pbte->target_info->index;
+ gs_text_enum_copy_dynamic(pte, pbte->target_info, true);
return code;
}
+private bool
+bbox_text_is_width_only(const gs_text_enum_t *pte)
+{
+ const bbox_text_enum *const pbte = (const bbox_text_enum *)pte;
+
+ return gs_text_is_width_only(pbte->target_info);
+}
+
+private int
+bbox_text_current_width(const gs_text_enum_t *pte, gs_point *pwidth)
+{
+ const bbox_text_enum *const pbte = (const bbox_text_enum *)pte;
+
+ return gs_text_current_width(pbte->target_info, pwidth);
+}
+
private int
bbox_text_set_cache(gs_text_enum_t * pte, const double *values,
gs_text_cache_control_t control)
{
bbox_text_enum *const pbte = (bbox_text_enum *) pte;
gs_text_enum_t *tpte = pbte->target_info;
- int code = tpte->procs->set_cache(tpte, values, control);
+ int code = gs_text_set_cache(tpte, values, control);
if (code < 0)
return code;
@@ -1110,11 +1295,25 @@ bbox_text_set_cache(gs_text_enum_t * pte, const double *values,
return code;
}
+private int
+bbox_text_retry(gs_text_enum_t *pte)
+{
+ bbox_text_enum *const pbte = (bbox_text_enum *) pte;
+
+ return gs_text_retry(pbte->target_info);
+}
+
private void
-bbox_text_free(gs_memory_t * memory, void *vpte, client_name_t cname)
+bbox_text_release(gs_text_enum_t *pte, client_name_t cname)
{
- bbox_text_enum *const pbte = (bbox_text_enum *) vpte;
+ bbox_text_enum *const pbte = (bbox_text_enum *)pte;
gs_text_release(pbte->target_info, cname);
+}
+
+private void
+bbox_text_free(gs_memory_t * memory, void *vpte, client_name_t cname)
+{
+ bbox_text_release((gs_text_enum_t *)vpte, cname);
rc_free_struct_only(memory, vpte, cname);
}
diff --git a/gs/src/gdevbbox.h b/gs/src/gdevbbox.h
index 79c61be15..35cffa706 100644
--- a/gs/src/gdevbbox.h
+++ b/gs/src/gdevbbox.h
@@ -70,17 +70,51 @@
* calls to their target. By default, they do propagate these calls:
* use gx_device_bbox_fwd_open_close to change this if you want.
*/
+/*
+ * Define virtual procedures for managing the accumulated bounding box.
+ * These may be redefined by subclasses, and are also used for compositors.
+ */
+typedef struct gx_device_bbox_procs_s {
+
+#define dev_bbox_proc_init_box(proc)\
+ bool proc(P1(void *proc_data))
+ dev_bbox_proc_init_box((*init_box));
+
+#define dev_bbox_proc_get_box(proc)\
+ void proc(P2(const void *proc_data, gs_fixed_rect *pbox))
+ dev_bbox_proc_get_box((*get_box));
+
+#define dev_bbox_proc_add_rect(proc)\
+ void proc(P5(void *proc_data, fixed x0, fixed y0, fixed x1, fixed y1))
+ dev_bbox_proc_add_rect((*add_rect));
+
+#define dev_bbox_proc_in_rect(proc)\
+ bool proc(P2(const void *proc_data, const gs_fixed_rect *pbox))
+ dev_bbox_proc_in_rect((*in_rect));
+
+} gx_device_bbox_procs_t;
+/* Default implementations */
+dev_bbox_proc_init_box(bbox_default_init_box);
+dev_bbox_proc_get_box(bbox_default_get_box);
+dev_bbox_proc_add_rect(bbox_default_add_rect);
+dev_bbox_proc_in_rect(bbox_default_in_rect);
+
#define gx_device_bbox_common\
gx_device_forward_common;\
bool free_standing;\
bool forward_open_close;\
- /* In order to handle compositors, we provide a separate pointer */\
- /* to the bbox device instance that holds the actual box. */\
- gx_device_bbox *box_device;\
+ gx_device_bbox_procs_t box_procs;\
+ void *box_proc_data;\
+ bool white_is_opaque;\
/* The following are updated dynamically. */\
gs_fixed_rect bbox;\
- gx_color_index black, white
+ gx_color_index black, white;\
+ gx_color_index transparent /* white or gx_no_color_index */
typedef struct gx_device_bbox_s gx_device_bbox;
+#define gx_device_bbox_common_initial(fs, foc, wio)\
+ 0 /* target */,\
+ fs, foc, {0}, 0, wio,\
+ {{0, 0}, {0, 0}}, gx_no_color_index, gx_no_color_index, gx_no_color_index
struct gx_device_bbox_s {
gx_device_bbox_common;
};
@@ -89,7 +123,7 @@ extern_st(st_device_bbox);
#define public_st_device_bbox() /* in gdevbbox.c */\
gs_public_st_suffix_add1_final(st_device_bbox, gx_device_bbox,\
"gx_device_bbox", device_bbox_enum_ptrs, device_bbox_reloc_ptrs,\
- gx_device_finalize, st_device_forward, box_device)
+ gx_device_finalize, st_device_forward, box_proc_data)
/* Initialize a bounding box device. */
void gx_device_bbox_init(P2(gx_device_bbox * dev, gx_device * target));
@@ -98,6 +132,10 @@ void gx_device_bbox_init(P2(gx_device_bbox * dev, gx_device * target));
void gx_device_bbox_fwd_open_close(P2(gx_device_bbox * dev,
bool forward_open_close));
+/* Set whether a bounding box device considers white to be opaque. */
+void gx_device_bbox_set_white_opaque(P2(gx_device_bbox *dev,
+ bool white_is_opaque));
+
/* Read back the bounding box in 1/72" units. */
void gx_device_bbox_bbox(P2(gx_device_bbox * dev, gs_rect * pbbox));
diff --git a/gs/src/gdevbit.c b/gs/src/gdevbit.c
index beb3d3c95..dd529398d 100644
--- a/gs/src/gdevbit.c
+++ b/gs/src/gdevbit.c
@@ -354,7 +354,7 @@ bit_print_page(gx_device_printer * pdev, FILE * prn_stream)
{ /* Just dump the bits on the file. */
/* If the file is 'nul', don't even do the writes. */
int line_size = gdev_mem_bytes_per_scan_line((gx_device *) pdev);
- byte *in = (byte *) gs_malloc(line_size, 1, "bit_print_page(in)");
+ byte *in = gs_alloc_bytes(pdev->memory, line_size, "bit_print_page(in)");
byte *data;
int nul = !strcmp(pdev->fname, "nul");
int lnum = 0, bottom = pdev->height;
@@ -366,6 +366,6 @@ bit_print_page(gx_device_printer * pdev, FILE * prn_stream)
if (!nul)
fwrite(data, 1, line_size, prn_stream);
}
- gs_free((char *)in, line_size, 1, "bit_print_page(in)");
+ gs_free_object(pdev->memory, in, "bit_print_page(in)");
return 0;
}
diff --git a/gs/src/gdevbmp.c b/gs/src/gdevbmp.c
index 88bf208fa..4aebc2ccc 100644
--- a/gs/src/gdevbmp.c
+++ b/gs/src/gdevbmp.c
@@ -29,13 +29,26 @@ private dev_proc_print_page(bmp_cmyk_print_page);
/* Monochrome. */
-gx_device_printer far_data gs_bmpmono_device =
+gx_device_printer gs_bmpmono_device =
prn_device(prn_std_procs, "bmpmono",
DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
X_DPI, Y_DPI,
0, 0, 0, 0, /* margins */
1, bmp_print_page);
+/* 8-bit (SuperVGA-style) grayscale . */
+/* (Uses a fixed palette of 256 gray levels.) */
+
+private const gx_device_procs bmpgray_procs =
+prn_color_procs(gdev_prn_open, gdev_prn_output_page, gdev_prn_close,
+ gx_default_gray_map_rgb_color, gx_default_gray_map_color_rgb);
+gx_device_printer gs_bmpgray_device =
+prn_device(bmpgray_procs, "bmpgray",
+ DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
+ X_DPI, Y_DPI,
+ 0, 0, 0, 0, /* margins */
+ 8, bmp_print_page);
+
/* 1-bit-per-plane separated CMYK color. */
#define bmp_cmyk_procs(p_map_color_rgb, p_map_cmyk_color)\
@@ -47,7 +60,7 @@ prn_device(prn_std_procs, "bmpmono",
private gx_device_procs bmpsep1_procs = {
bmp_cmyk_procs(cmyk_1bit_map_color_rgb, cmyk_1bit_map_cmyk_color)
};
-gx_device_printer far_data gs_bmpsep1_device = {
+gx_device_printer gs_bmpsep1_device = {
prn_device_body(gx_device_printer, bmpsep1_procs, "bmpsep1",
DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
X_DPI, Y_DPI,
@@ -60,7 +73,7 @@ gx_device_printer far_data gs_bmpsep1_device = {
private gx_device_procs bmpsep8_procs = {
bmp_cmyk_procs(cmyk_8bit_map_color_rgb, cmyk_8bit_map_cmyk_color)
};
-gx_device_printer far_data gs_bmpsep8_device = {
+gx_device_printer gs_bmpsep8_device = {
prn_device_body(gx_device_printer, bmpsep8_procs, "bmpsep8",
DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
X_DPI, Y_DPI,
@@ -73,7 +86,7 @@ gx_device_printer far_data gs_bmpsep8_device = {
private const gx_device_procs bmp16_procs =
prn_color_procs(gdev_prn_open, gdev_prn_output_page, gdev_prn_close,
pc_4bit_map_rgb_color, pc_4bit_map_color_rgb);
-gx_device_printer far_data gs_bmp16_device =
+gx_device_printer gs_bmp16_device =
prn_device(bmp16_procs, "bmp16",
DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
X_DPI, Y_DPI,
@@ -86,7 +99,7 @@ prn_device(bmp16_procs, "bmp16",
private const gx_device_procs bmp256_procs =
prn_color_procs(gdev_prn_open, gdev_prn_output_page, gdev_prn_close,
pc_8bit_map_rgb_color, pc_8bit_map_color_rgb);
-gx_device_printer far_data gs_bmp256_device =
+gx_device_printer gs_bmp256_device =
prn_device(bmp256_procs, "bmp256",
DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
X_DPI, Y_DPI,
@@ -98,7 +111,7 @@ prn_device(bmp256_procs, "bmp256",
private const gx_device_procs bmp16m_procs =
prn_color_procs(gdev_prn_open, gdev_prn_output_page, gdev_prn_close,
bmp_map_16m_rgb_color, bmp_map_16m_color_rgb);
-gx_device_printer far_data gs_bmp16m_device =
+gx_device_printer gs_bmp16m_device =
prn_device(bmp16m_procs, "bmp16m",
DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
X_DPI, Y_DPI,
@@ -110,7 +123,7 @@ prn_device(bmp16m_procs, "bmp16m",
private const gx_device_procs bmp32b_procs = {
bmp_cmyk_procs(cmyk_8bit_map_color_rgb, gx_default_cmyk_map_cmyk_color)
};
-gx_device_printer far_data gs_bmp32b_device =
+gx_device_printer gs_bmp32b_device =
prn_device(bmp32b_procs, "bmp32b",
DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
X_DPI, Y_DPI,
@@ -127,7 +140,7 @@ bmp_print_page(gx_device_printer * pdev, FILE * file)
uint raster = gdev_prn_raster(pdev);
/* BMP scan lines are padded to 32 bits. */
uint bmp_raster = raster + (-raster & 3);
- byte *row = (byte *)gs_malloc(bmp_raster, 1, "bmp file buffer");
+ byte *row = gs_alloc_bytes(pdev->memory, bmp_raster, "bmp file buffer");
int y;
int code; /* return code */
@@ -149,7 +162,7 @@ bmp_print_page(gx_device_printer * pdev, FILE * file)
}
done:
- gs_free((char *)row, bmp_raster, 1, "bmp file buffer");
+ gs_free_object(pdev->memory, row, "bmp file buffer");
return code;
}
@@ -163,7 +176,7 @@ bmp_cmyk_print_page(gx_device_printer * pdev, FILE * file)
uint raster = bitmap_raster(pdev->width * plane_depth);
/* BMP scan lines are padded to 32 bits. */
uint bmp_raster = raster + (-raster & 3);
- byte *row = (byte *)gs_malloc(bmp_raster, 1, "bmp file buffer");
+ byte *row = gs_alloc_bytes(pdev->memory, bmp_raster, "bmp file buffer");
int y;
int code = 0; /* return code */
int plane;
@@ -198,7 +211,7 @@ bmp_cmyk_print_page(gx_device_printer * pdev, FILE * file)
}
done:
- gs_free((char *)row, bmp_raster, 1, "bmp file buffer");
+ gs_free_object(pdev->memory, row, "bmp file buffer");
return code;
}
diff --git a/gs/src/gdevbmpa.c b/gs/src/gdevbmpa.c
index 6f18bc856..c84bd59c9 100644
--- a/gs/src/gdevbmpa.c
+++ b/gs/src/gdevbmpa.c
@@ -86,7 +86,7 @@ private prn_dev_proc_get_space_params(bmpa_get_space_params);
private gx_device_procs bmpamono_procs =
prn_procs(bmpa_writer_open, gdev_prn_output_page, gdev_prn_close);
-gx_device_async far_data gs_bmpamono_device =
+gx_device_async gs_bmpamono_device =
async_device(bmpamono_procs, "bmpamono",
DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
X_DPI, Y_DPI,
@@ -105,7 +105,7 @@ private gx_device_procs bmpasep1_procs = {
bmpa_cmyk_procs(bmpa_cmyk_writer_open, cmyk_1bit_map_color_rgb,
cmyk_1bit_map_cmyk_color)
};
-gx_device_async far_data gs_bmpasep1_device = {
+gx_device_async gs_bmpasep1_device = {
prn_device_body(gx_device_async, bmpasep1_procs, "bmpasep1",
DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
X_DPI, Y_DPI,
@@ -119,8 +119,8 @@ private gx_device_procs bmpasep8_procs = {
bmpa_cmyk_procs(bmpa_cmyk_writer_open, cmyk_8bit_map_color_rgb,
cmyk_8bit_map_cmyk_color)
};
-gx_device_printer far_data gs_bmpasep8_device = {
- prn_device_body(gx_device_printer, bmpasep8_procs, "bmpasep8",
+gx_device_async gs_bmpasep8_device = {
+ prn_device_body(gx_device_async, bmpasep8_procs, "bmpasep8",
DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
X_DPI, Y_DPI,
0,0,0,0, /* margins */
@@ -132,7 +132,7 @@ gx_device_printer far_data gs_bmpasep8_device = {
private gx_device_procs bmpa16_procs =
prn_color_procs(bmpa_writer_open, gdev_prn_output_page, gdev_prn_close,
pc_4bit_map_rgb_color, pc_4bit_map_color_rgb);
-gx_device_async far_data gs_bmpa16_device =
+gx_device_async gs_bmpa16_device =
async_device(bmpa16_procs, "bmpa16",
DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
X_DPI, Y_DPI,
@@ -145,7 +145,7 @@ gx_device_async far_data gs_bmpa16_device =
private gx_device_procs bmpa256_procs =
prn_color_procs(bmpa_writer_open, gdev_prn_output_page, gdev_prn_close,
pc_8bit_map_rgb_color, pc_8bit_map_color_rgb);
-gx_device_async far_data gs_bmpa256_device =
+gx_device_async gs_bmpa256_device =
async_device(bmpa256_procs, "bmpa256",
DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
X_DPI, Y_DPI,
@@ -157,7 +157,7 @@ gx_device_async far_data gs_bmpa256_device =
private gx_device_procs bmpa16m_procs =
prn_color_procs(bmpa_writer_open, gdev_prn_output_page, gdev_prn_close,
bmp_map_16m_rgb_color, bmp_map_16m_color_rgb);
-gx_device_async far_data gs_bmpa16m_device =
+gx_device_async gs_bmpa16m_device =
async_device(bmpa16m_procs, "bmpa16m",
DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
X_DPI, Y_DPI,
@@ -170,7 +170,7 @@ private const gx_device_procs bmpa32b_procs = {
bmpa_cmyk_procs(bmpa_writer_open, gx_default_map_color_rgb,
gx_default_cmyk_map_cmyk_color)
};
-gx_device_async far_data gs_bmpa32b_device =
+gx_device_async gs_bmpa32b_device =
async_device(bmpa32b_procs, "bmpa32b",
DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
X_DPI, Y_DPI,
@@ -326,7 +326,7 @@ bmpa_reader_print_planes(gx_device_printer *pdev, FILE *prn_stream,
goto done;
}
- row = (byte *)gs_malloc(bmp_raster, 1, "bmp file buffer");
+ row = gs_alloc_bytes(pdev->memory, bmp_raster, "bmp file buffer");
if (row == 0) /* can't allocate row buffer */
return_error(gs_error_VMerror);
@@ -369,7 +369,7 @@ bmpa_reader_print_planes(gx_device_printer *pdev, FILE *prn_stream,
}
}
done:
- gs_free((char *)row, bmp_raster, 1, "bmp file buffer");
+ gs_free_object(pdev->memory, row, "bmp file buffer");
#ifdef SINGLE_PAGE
if (code >= 0 && prdev->copies_printed > 0)
prdev->copies_printed = num_copies;
diff --git a/gs/src/gdevbmpc.c b/gs/src/gdevbmpc.c
index 3633d1649..e674ed4cb 100644
--- a/gs/src/gdevbmpc.c
+++ b/gs/src/gdevbmpc.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -137,12 +137,17 @@ write_bmp_depth_header(gx_device_printer *pdev, FILE *file, int depth,
BMP_ASSIGN_WORD(ihdr.bitCount, depth);
BMP_ASSIGN_DWORD(ihdr.compression, 0);
BMP_ASSIGN_DWORD(ihdr.sizeImage, bmp_raster * height);
- /* Even though we could compute the resolution correctly, */
- /* the convention seems to be to leave it unspecified. */
- BMP_ASSIGN_DWORD(ihdr.xPelsPerMeter, 0);
- /*(dword)(pdev->x_pixels_per_inch * (1000.0 / 30.48))); */
- BMP_ASSIGN_DWORD(ihdr.yPelsPerMeter, 0);
- /*(dword)(pdev->y_pixels_per_inch * (1000.0 / 30.48))); */
+ /*
+ * Earlier versions of this driver set the PelsPerMeter values
+ * to zero. At a user's request, we now set them correctly,
+ * but we suspect this will cause problems other places.
+ */
+#define INCHES_PER_METER (100 /*cm/meter*/ / 2.54 /*cm/inch*/)
+ BMP_ASSIGN_DWORD(ihdr.xPelsPerMeter,
+ (dword)(pdev->x_pixels_per_inch * INCHES_PER_METER));
+ BMP_ASSIGN_DWORD(ihdr.yPelsPerMeter,
+ (dword)(pdev->y_pixels_per_inch * INCHES_PER_METER));
+#undef INCHES_PER_METER
BMP_ASSIGN_DWORD(ihdr.clrUsed, 0);
BMP_ASSIGN_DWORD(ihdr.clrImportant, 0);
if (fwrite((const char *)&ihdr, 1, sizeof(ihdr), file) != sizeof(ihdr))
diff --git a/gs/src/gdevcd8.c b/gs/src/gdevcd8.c
index 14377be65..2a600c33b 100644
--- a/gs/src/gdevcd8.c
+++ b/gs/src/gdevcd8.c
@@ -14,7 +14,7 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 U.S.A.
This program may also be distributed as part of Aladdin Ghostscript,
under the terms of the Aladdin Free Public License (the "License").
diff --git a/gs/src/gdevcgm.c b/gs/src/gdevcgm.c
index 124c12e07..16c7493ed 100644
--- a/gs/src/gdevcgm.c
+++ b/gs/src/gdevcgm.c
@@ -92,15 +92,15 @@ private dev_proc_put_params(cgm_put_params);
0 /*false*/ /* in_picture */\
}
-gx_device_cgm far_data gs_cgmmono_device =
+gx_device_cgm gs_cgmmono_device =
cgm_device("cgmmono", 1, 1, 2,
gx_default_map_rgb_color, gx_default_w_b_map_color_rgb);
-gx_device_cgm far_data gs_cgm8_device =
+gx_device_cgm gs_cgm8_device =
cgm_device("cgm8", 8, 6, 7,
pc_8bit_map_rgb_color, pc_8bit_map_color_rgb);
-gx_device_cgm far_data gs_cgm24_device =
+gx_device_cgm gs_cgm24_device =
cgm_device("cgm24", 24, 255, 255,
gx_default_rgb_map_rgb_color, gx_default_rgb_map_color_rgb);
@@ -109,19 +109,15 @@ private void *
cgm_gs_alloc(void *private_data, uint size)
{
gx_device_cgm *cdev = private_data;
- gs_memory_t *mem =
- (cdev->memory == 0 ? &gs_memory_default : cdev->memory);
- return gs_alloc_bytes(mem, size, "cgm_gs_alloc");
+ return gs_alloc_bytes(cdev->memory, size, "cgm_gs_alloc");
}
private void
cgm_gs_free(void *private_data, void *obj)
{
gx_device_cgm *cdev = private_data;
- gs_memory_t *mem =
- (cdev->memory == 0 ? &gs_memory_default : cdev->memory);
- gs_free_object(mem, obj, "cgm_gs_free");
+ gs_free_object(cdev->memory, obj, "cgm_gs_free");
}
/* ---------------- Utilities ---------------- */
diff --git a/gs/src/gdevclj.c b/gs/src/gdevclj.c
index 7c8f2ddc3..8451082ee 100644
--- a/gs/src/gdevclj.c
+++ b/gs/src/gdevclj.c
@@ -311,8 +311,7 @@ clj_put_params(
pf_array.size = 2;
pf_array.persistent = false;
- gs_c_param_list_write(&alist, (pdev->memory) ? pdev->memory :
- &gs_memory_default);
+ gs_c_param_list_write(&alist, pdev->memory);
code = param_write_float_array((gs_param_list *)&alist, ".MediaSize", &pf_array);
gs_c_param_list_read(&alist);
@@ -440,6 +439,7 @@ clj_print_page(
FILE * prn_stream
)
{
+ gs_memory_t *mem = pdev->memory;
bool rotate;
const clj_paper_size * psize = get_paper_size(pdev->MediaSize, &rotate);
int lsize = pdev->width;
@@ -457,10 +457,10 @@ clj_print_page(
return_error(gs_error_unregistered);
/* allocate memory for the raw and compressed data */
- if ((data = gs_malloc(lsize, 1, "clj_print_page(data)")) == 0)
+ if ((data = gs_alloc_bytes(mem, lsize, "clj_print_page(data)")) == 0)
return_error(gs_error_VMerror);
- if ((cdata[0] = gs_malloc(3 *clsize, 1, "clj_print_page(cdata)")) == 0) {
- gs_free((char *)data, lsize, 1, "clj_print_page(data)");
+ if ((cdata[0] = gs_alloc_bytes(mem, 3 * clsize, "clj_print_page(cdata)")) == 0) {
+ gs_free_object(mem, data, "clj_print_page(data)");
return_error(gs_error_VMerror);
}
cdata[1] = cdata[0] + clsize;
@@ -529,8 +529,8 @@ clj_print_page(
fputs("\033*rC\f", prn_stream);
/* free the buffers used */
- gs_free((char *)cdata[0], 3 * clsize, 1, "clj_print_page(cdata)");
- gs_free((char *)data, lsize, 1, "clj_print_page(data)");
+ gs_free_object(mem, cdata[0], "clj_print_page(cdata)");
+ gs_free_object(mem, data, "clj_print_page(data)");
return 0;
}
diff --git a/gs/src/gdevcljc.c b/gs/src/gdevcljc.c
index ec4555adb..45a1ec8f5 100644
--- a/gs/src/gdevcljc.c
+++ b/gs/src/gdevcljc.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -35,6 +35,7 @@
private int
cljc_print_page(gx_device_printer * pdev, FILE * prn_stream)
{
+ gs_memory_t *mem = pdev->memory;
uint raster = gx_device_raster(pdev, false);
int i;
int worst_case_comp_size = raster + (raster / 8) + 1;
@@ -44,9 +45,9 @@ cljc_print_page(gx_device_printer * pdev, FILE * prn_stream)
int code = 0;
/* allocate memory for the raw data and compressed data. */
- if (((data = gs_malloc(raster, 1, "cljc_print_page(data)")) == 0) ||
- ((cdata = gs_malloc(worst_case_comp_size, 1, "cljc_print_page(cdata)")) == 0) ||
- ((prow = gs_malloc(worst_case_comp_size, 1, "cljc_print_page(prow)")) == 0)) {
+ if (((data = gs_alloc_bytes(mem, raster, "cljc_print_page(data)")) == 0) ||
+ ((cdata = gs_alloc_bytes(mem, worst_case_comp_size, "cljc_print_page(cdata)")) == 0) ||
+ ((prow = gs_alloc_bytes(mem, worst_case_comp_size, "cljc_print_page(prow)")) == 0)) {
code = gs_note_error(gs_error_VMerror);
goto out;
}
@@ -79,9 +80,9 @@ cljc_print_page(gx_device_printer * pdev, FILE * prn_stream)
/* PCL will take care of blank lines at the end */
fputs("\033*rC\f", prn_stream);
out:
- gs_free((char *)data, raster, 1, "cljc_print_page(data)");
- gs_free((char *)cdata, worst_case_comp_size, 1, "cljc_print_page(cdata)");
- gs_free((char *)prow, worst_case_comp_size, 1, "cljc_print_page(prow)");
+ gs_free_object(mem, prow, "cljc_print_page(prow)");
+ gs_free_object(mem, cdata, "cljc_print_page(cdata)");
+ gs_free_object(mem, data, "cljc_print_page(data)");
return code;
}
diff --git a/gs/src/gdevddrw.c b/gs/src/gdevddrw.c
index cec212eec..5058e470d 100644
--- a/gs/src/gdevddrw.c
+++ b/gs/src/gdevddrw.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1989, 1995, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1989, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -31,6 +31,9 @@
#include "gxiparam.h"
#include "gxistate.h"
+#define SWAP(a, b, t)\
+ (t = a, a = b, b = t)
+
/* ---------------- Polygon and line drawing ---------------- */
/* Define the 'remainder' analogue of fixed_mult_quo. */
@@ -334,10 +337,9 @@ gx_default_fill_parallelogram(gx_device * dev,
if (by < 0)
px += bx, py += by, bx = -bx, by = -by;
qx = px + ax + bx;
-#define swap(r, s) (t = r, r = s, s = t)
if ((ax ^ bx) < 0) { /* In this case, the test ax <= bx is sufficient. */
if (ax > bx)
- swap(ax, bx), swap(ay, by);
+ SWAP(ax, bx, t), SWAP(ay, by, t);
} else { /*
* Compare the slopes. We know that ay >= 0, by >= 0,
* and ax and bx have the same sign; the lines are in the
@@ -348,7 +350,7 @@ gx_default_fill_parallelogram(gx_device * dev,
* without using floating point.
*/
if ((double)ay * bx < (double)by * ax)
- swap(ax, bx), swap(ay, by);
+ SWAP(ax, bx, t), SWAP(ay, by, t);
}
fill_trapezoid = dev_proc(dev, fill_trapezoid);
qy = py + ay + by;
@@ -358,10 +360,10 @@ gx_default_fill_parallelogram(gx_device * dev,
left.end.y = py + ay;
right.end.x = px + bx;
right.end.y = py + by;
-#define rounded_same(p1, p2)\
+#define ROUNDED_SAME(p1, p2)\
(fixed_pixround(p1) == fixed_pixround(p2))
if (ay < by) {
- if (!rounded_same(py, left.end.y)) {
+ if (!ROUNDED_SAME(py, left.end.y)) {
code = (*fill_trapezoid) (dev, &left, &right, py, left.end.y,
false, pdevc, lop);
if (code < 0)
@@ -370,7 +372,7 @@ gx_default_fill_parallelogram(gx_device * dev,
left.start = left.end;
left.end.x = qx, left.end.y = qy;
ym = right.end.y;
- if (!rounded_same(left.start.y, ym)) {
+ if (!ROUNDED_SAME(left.start.y, ym)) {
code = (*fill_trapezoid) (dev, &left, &right, left.start.y, ym,
false, pdevc, lop);
if (code < 0)
@@ -379,7 +381,7 @@ gx_default_fill_parallelogram(gx_device * dev,
right.start = right.end;
right.end.x = qx, right.end.y = qy;
} else {
- if (!rounded_same(py, right.end.y)) {
+ if (!ROUNDED_SAME(py, right.end.y)) {
code = (*fill_trapezoid) (dev, &left, &right, py, right.end.y,
false, pdevc, lop);
if (code < 0)
@@ -388,7 +390,7 @@ gx_default_fill_parallelogram(gx_device * dev,
right.start = right.end;
right.end.x = qx, right.end.y = qy;
ym = left.end.y;
- if (!rounded_same(right.start.y, ym)) {
+ if (!ROUNDED_SAME(right.start.y, ym)) {
code = (*fill_trapezoid) (dev, &left, &right, right.start.y, ym,
false, pdevc, lop);
if (code < 0)
@@ -397,13 +399,12 @@ gx_default_fill_parallelogram(gx_device * dev,
left.start = left.end;
left.end.x = qx, left.end.y = qy;
}
- if (!rounded_same(ym, qy))
+ if (!ROUNDED_SAME(ym, qy))
return (*fill_trapezoid) (dev, &left, &right, ym, qy,
false, pdevc, lop);
else
return 0;
-#undef rounded_same
-#undef swap
+#undef ROUNDED_SAME
}
/* Fill a triangle whose points are p, p+a, and p+b. */
@@ -427,10 +428,8 @@ gx_default_fill_triangle(gx_device * dev,
if (by < 0)
px += bx, py += by, ax -= bx, ay -= by, bx = -bx, by = -by;
/* Ensure ay <= by. */
-#define swap(r, s) (t = r, r = s, s = t)
if (ay > by)
- swap(ax, bx), swap(ay, by);
-#undef swap
+ SWAP(ax, bx, t), SWAP(ay, by, t);
/*
* Make a special check for a flat bottom or top,
* which we can handle with a single call on fill_trapezoid.
@@ -514,10 +513,9 @@ gx_default_draw_thin_line(gx_device * dev,
bool swap_axes;
gs_fixed_edge left, right;
-#define fswap(a, b) tf = a, a = b, b = tf
if ((w < 0 ? -w : w) <= (h < 0 ? -h : h)) {
if (h < 0)
- fswap(fx0, fx1), fswap(fy0, fy1),
+ SWAP(fx0, fx1, tf), SWAP(fy0, fy1, tf),
h = -h;
right.start.x = (left.start.x = fx0 - fixed_half) + fixed_1;
right.end.x = (left.end.x = fx1 - fixed_half) + fixed_1;
@@ -526,7 +524,7 @@ gx_default_draw_thin_line(gx_device * dev,
swap_axes = false;
} else {
if (w < 0)
- fswap(fx0, fx1), fswap(fy0, fy1),
+ SWAP(fx0, fx1, tf), SWAP(fy0, fy1, tf),
w = -w;
right.start.x = (left.start.x = fy0 - fixed_half) + fixed_1;
right.end.x = (left.end.x = fy1 - fixed_half) + fixed_1;
@@ -537,7 +535,6 @@ gx_default_draw_thin_line(gx_device * dev,
return (*dev_proc(dev, fill_trapezoid)) (dev, &left, &right,
left.start.y, left.end.y,
swap_axes, pdevc, lop);
-#undef fswap
}
}
@@ -554,23 +551,18 @@ gx_default_draw_line(gx_device * dev,
/* GC structures for image enumerator */
public_st_gx_image_enum_common();
-#define eptr ((gx_image_enum_common_t *)vptr)
-
private
-ENUM_PTRS_BEGIN(image_enum_common_enum_ptrs) return 0;
-
-case 0:
-return ENUM_OBJ(gx_device_enum_ptr(eptr->dev));
+ENUM_PTRS_WITH(image_enum_common_enum_ptrs, gx_image_enum_common_t *eptr)
+ return 0;
+case 0: return ENUM_OBJ(gx_device_enum_ptr(eptr->dev));
ENUM_PTRS_END
-private RELOC_PTRS_BEGIN(image_enum_common_reloc_ptrs)
+private RELOC_PTRS_WITH(image_enum_common_reloc_ptrs, gx_image_enum_common_t *eptr)
{
eptr->dev = gx_device_reloc_ptr(eptr->dev, gcst);
}
RELOC_PTRS_END
-#undef eptr
-
/*
* gx_default_begin_image is only invoked for ImageType 1 images. However,
* the argument types are different, and if the device provides a
diff --git a/gs/src/gdevdfax.c b/gs/src/gdevdfax.c
index 993db1d50..6759f1d76 100644
--- a/gs/src/gdevdfax.c
+++ b/gs/src/gdevdfax.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1994, 1995 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1994, 1995, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -25,11 +25,7 @@
#include "gdevprn.h"
#include "strimpl.h"
#include "scfx.h"
-
-/* Import the key routines from gdevtfax.c. */
-int gdev_fax_open(P1(gx_device *));
-void gdev_fax_init_state(P2(stream_CFE_state *, const gx_device_printer *));
-int gdev_fax_print_page(P3(gx_device_printer *, FILE *, stream_CFE_state *));
+#include "gdevtfax.h"
/* Define the device parameters. */
#define X_DPI 204
diff --git a/gs/src/gdevdjet.c b/gs/src/gdevdjet.c
index 3e21a9423..6e155461f 100644
--- a/gs/src/gdevdjet.c
+++ b/gs/src/gdevdjet.c
@@ -438,9 +438,9 @@ hpjet_print_page(gx_device_printer * pdev, FILE * prn_stream, int ptype,
int line_size = gdev_mem_bytes_per_scan_line((gx_device *) pdev);
int line_size_words = (line_size + W - 1) / W;
uint storage_size_words = line_size_words * 8; /* data, out_row, out_row_alt, prev_row */
- word *storage = (ulong *) gs_malloc(storage_size_words, W,
- "hpjet_print_page");
-
+ word *storage =
+ (ulong *)gs_alloc_byte_array(pdev->memory, storage_size_words, W,
+ "hpjet_print_page");
word
* data_words,
*out_row_words,
@@ -652,7 +652,7 @@ hpjet_print_page(gx_device_printer * pdev, FILE * prn_stream, int ptype,
fputs("\033*rB\f", prn_stream);
/* free temporary storage */
- gs_free((char *)storage, storage_size_words, W, "hpjet_print_page");
+ gs_free_object(pdev->memory, storage, "hpjet_print_page");
return code;
}
diff --git a/gs/src/gdevdrop.c b/gs/src/gdevdrop.c
index c17283981..39a478a2f 100644
--- a/gs/src/gdevdrop.c
+++ b/gs/src/gdevdrop.c
@@ -29,6 +29,7 @@
#include "gxdevmem.h"
#include "gxdevrop.h"
#include "gxgetbit.h"
+#include "gdevmem.h" /* for mem_default_strip_copy_rop prototype */
#include "gdevmrop.h"
/*
@@ -103,7 +104,7 @@ gx_default_strip_copy_rop(gx_device * dev,
gs_logical_operation_t lop)
{
int depth = dev->color_info.depth;
- gs_memory_t *mem = (dev->memory ? dev->memory : &gs_memory_default);
+ gs_memory_t *mem = dev->memory;
const gx_device_memory *mdproto = gdev_mem_device_for_bits(depth);
gx_device_memory mdev;
uint draster;
@@ -363,7 +364,7 @@ mem_default_strip_copy_rop(gx_device * dev,
GB_ALPHA_NONE | GB_DEPTH_8 |
GB_PACKING_CHUNKY | GB_RETURN_COPY | GB_ALIGN_STANDARD |
GB_OFFSET_0 | GB_RASTER_STANDARD;
- gs_memory_t *mem = (dev->memory ? dev->memory : &gs_memory_default);
+ gs_memory_t *mem = dev->memory;
const gx_device_memory *mdproto = gdev_mem_device_for_bits(rop_depth);
gx_device_memory mdev;
union { long l; void *p; } mdev_storage[20];
diff --git a/gs/src/gdevlj56.c b/gs/src/gdevlj56.c
index c36cab761..0df723419 100644
--- a/gs/src/gdevlj56.c
+++ b/gs/src/gdevlj56.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1997 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1997, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -46,7 +46,7 @@ private dev_proc_print_page(ljet5_print_page);
private const gx_device_procs ljet5_procs =
prn_procs(ljet5_open, gdev_prn_output_page, ljet5_close);
-gx_device_printer far_data gs_lj5mono_device =
+gx_device_printer gs_lj5mono_device =
prn_device(ljet5_procs, "lj5mono",
DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
X_DPI, Y_DPI,
@@ -58,8 +58,7 @@ prn_color_procs(ljet5_open, gdev_prn_output_page, ljet5_close,
gx_default_gray_map_rgb_color,
gx_default_gray_map_color_rgb);
-gx_device_printer far_data gs_lj5gray_device =
-{
+gx_device_printer gs_lj5gray_device = {
prn_device_body(gx_device_printer, lj5gray_procs, "lj5gray",
DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
X_DPI, Y_DPI,
@@ -67,8 +66,6 @@ gx_device_printer far_data gs_lj5gray_device =
1, 8, 255, 0, 256, 1, ljet5_print_page)
};
-#define ppdev ((gx_device_printer *)pdev)
-
/* Write a 'canned' data sequence. */
#define fwrite_bytes(bytes, strm) fwrite(bytes, 1, sizeof(bytes), strm)
@@ -104,13 +101,6 @@ put_usp(uint ix, uint iy, FILE * prn_stream)
put_s(ix, prn_stream);
put_s(iy, prn_stream);
}
-#define dss(i) pxt_sint16, ds(i)
-private void
-put_ss(int i, FILE * prn_stream)
-{
- fputc(pxt_sint16, prn_stream);
- put_s((uint) i, prn_stream);
-}
#define dl(l) ds(l), ds((l) >> 16)
private void
put_l(ulong l, FILE * prn_stream)
@@ -131,9 +121,9 @@ ljet5_open(gx_device * pdev)
if (code < 0)
return code;
{
+ gx_device_printer *const ppdev = (gx_device_printer *)pdev;
FILE *prn_stream = ppdev->file;
- static const byte stream_header[] =
- {
+ static const byte stream_header[] = {
da(pxaUnitsPerMeasure),
dub(0), da(pxaMeasure),
dub(eErrorPage), da(pxaErrorReport),
@@ -161,9 +151,9 @@ ljet5_close(gx_device * pdev)
if (code < 0)
return code;
{
+ gx_device_printer *const ppdev = (gx_device_printer *)pdev;
FILE *prn_stream = ppdev->file;
- static const byte stream_trailer[] =
- {
+ static const byte stream_trailer[] = {
pxtCloseDataSource,
pxtEndSession,
033, '%', '-', '1', '2', '3', '4', '5', 'X'
@@ -178,11 +168,12 @@ ljet5_close(gx_device * pdev)
private int
ljet5_print_page(gx_device_printer * pdev, FILE * prn_stream)
{
+ gs_memory_t *mem = pdev->memory;
uint line_size = gdev_mem_bytes_per_scan_line((gx_device *) pdev);
uint line_size_words = (line_size + W - 1) / W;
uint out_size = line_size + (line_size / 127) + 1;
- word *line = (word *) gs_malloc(line_size_words, W, "ljet5(line)");
- byte *out = gs_malloc(out_size, 1, "ljet5(out)");
+ word *line = (word *)gs_alloc_byte_array(mem, line_size_words, W, "ljet5(line)");
+ byte *out = gs_alloc_bytes(mem, out_size, "ljet5(out)");
int code = 0;
int lnum;
@@ -192,8 +183,7 @@ ljet5_print_page(gx_device_printer * pdev, FILE * prn_stream)
}
/* Write the page header. */
{
- static const byte page_header[] =
- {
+ static const byte page_header[] = {
dub(ePortraitOrientation), da(pxaOrientation),
dub(eLetterPaper), da(pxaMediaSize),
dub(eAutoSelect), da(pxaMediaSource),
@@ -201,15 +191,13 @@ ljet5_print_page(gx_device_printer * pdev, FILE * prn_stream)
dusp(0, 0), da(pxaPoint),
pxtSetCursor
};
- static const byte mono_header[] =
- {
+ static const byte mono_header[] = {
dub(eGray), da(pxaColorSpace),
dub(e8Bit), da(pxaPaletteDepth),
pxt_ubyte_array, pxt_ubyte, 2, 0xff, 0x00, da(pxaPaletteData),
pxtSetColorSpace
};
- static const byte gray_header[] =
- {
+ static const byte gray_header[] = {
dub(eGray), da(pxaColorSpace),
pxtSetColorSpace
};
@@ -223,15 +211,13 @@ ljet5_print_page(gx_device_printer * pdev, FILE * prn_stream)
/* Write the image header. */
{
- static const byte mono_image_header[] =
- {
+ static const byte mono_image_header[] = {
da(pxaDestinationSize),
dub(eIndexedPixel), da(pxaColorMapping),
dub(e1Bit), da(pxaColorDepth),
pxtBeginImage
};
- static const byte gray_image_header[] =
- {
+ static const byte gray_image_header[] = {
da(pxaDestinationSize),
dub(eDirectPixel), da(pxaColorMapping),
dub(e8Bit), da(pxaColorDepth),
@@ -252,8 +238,7 @@ ljet5_print_page(gx_device_printer * pdev, FILE * prn_stream)
/* Write the image data, compressing each line. */
for (lnum = 0; lnum < pdev->height; ++lnum) {
int ncompr;
- static const byte line_header[] =
- {
+ static const byte line_header[] = {
da(pxaStartLine),
dus(1), da(pxaBlockHeight),
dub(eRLECompression), da(pxaCompressMode),
@@ -282,9 +267,7 @@ ljet5_print_page(gx_device_printer * pdev, FILE * prn_stream)
fputc(pxtEndImage, prn_stream);
fputc(pxtEndPage, prn_stream);
done:
- if (out)
- gs_free(out, out_size, 1, "ljet5(out)");
- if (line)
- gs_free(line, line_size_words, W, "ljet5(out)");
+ gs_free_object(mem, out, "ljet5(out)");
+ gs_free_object(mem, line, "ljet5(line)");
return code;
}
diff --git a/gs/src/gdevm1.c b/gs/src/gdevm1.c
index 06c53d9a7..eed078c60 100644
--- a/gs/src/gdevm1.c
+++ b/gs/src/gdevm1.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1989, 1995, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1989, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -24,8 +24,6 @@
#include "gxdevmem.h" /* semi-public definitions */
#include "gdevmem.h" /* private definitions */
-extern dev_proc_strip_copy_rop(mem_mono_strip_copy_rop);
-
/* Optionally, use the slow RasterOp implementations for testing. */
/*#define USE_COPY_ROP */
@@ -35,24 +33,13 @@ extern dev_proc_strip_copy_rop(mem_mono_strip_copy_rop);
/* ================ Standard (byte-oriented) device ================ */
-/* We went to a lot of trouble to optimize mem_mono_tile_rectangle. */
-/* It has a substantial effect on the total time at high resolutions. */
-/* However, it takes quite a lot of code, so we omit it on 16-bit systems. */
-#define OPTIMIZE_TILE (arch_sizeof_int > 2)
-
/* Procedures */
private dev_proc_map_rgb_color(mem_mono_map_rgb_color);
private dev_proc_map_color_rgb(mem_mono_map_color_rgb);
private dev_proc_copy_mono(mem_mono_copy_mono);
private dev_proc_fill_rectangle(mem_mono_fill_rectangle);
-
-#if OPTIMIZE_TILE
private dev_proc_strip_tile_rectangle(mem_mono_strip_tile_rectangle);
-#else
-# define mem_mono_strip_tile_rectangle gx_default_strip_tile_rectangle
-#endif
-
/* The device descriptor. */
/* The instance is public. */
const gx_device_memory mem_mono_device =
@@ -471,8 +458,6 @@ mem_mono_copy_mono(gx_device * dev,
#endif /* !USE_COPY_ROP */
}
-#if OPTIMIZE_TILE /**************** *************** */
-
/* Strip-tile with a monochrome halftone. */
/* This is a performance bottleneck for monochrome devices, */
/* so we re-implement it, even though it takes a lot of code. */
@@ -695,8 +680,6 @@ int tx, int y, int tw, int th, gx_color_index color0, gx_color_index color1,
#endif /* !USE_COPY_ROP */
}
-#endif /**************** *************** */
-
/* ================ "Word"-oriented device ================ */
/* Note that on a big-endian machine, this is the same as the */
diff --git a/gs/src/gdevm16.c b/gs/src/gdevm16.c
index 84bc16bb5..2233a627c 100644
--- a/gs/src/gdevm16.c
+++ b/gs/src/gdevm16.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1994, 1996, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1994, 1996, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -85,16 +85,32 @@ mem_true16_fill_rectangle(gx_device * dev,
const ushort color16 = (ushort)((color << 8) | (color >> 8));
#endif
declare_scan_ptr(dest);
+
fit_fill(dev, x, y, w, h);
setup_rect(dest);
- while (h-- > 0) {
- ushort *pptr = (ushort *) dest;
- int cnt = w;
-
- do {
- *pptr++ = color16;
- } while (--cnt > 0);
- inc_ptr(dest, draster);
+ if (w == 1) {
+ while (h-- > 0) {
+ *(ushort *)dest = color16;
+ inc_ptr(dest, draster);
+ }
+ } else if ((color16 >> 8) == (color16 & 0xff)) {
+ bytes_fill_rectangle(scan_line_base(mdev, y) + (x << 1), draster,
+ (byte)color, w << 1, h);
+ } else {
+ while (h-- > 0) {
+ ushort *pptr = (ushort *) dest;
+ int cnt = w;
+
+ for (; cnt >= 4; pptr += 4, cnt -= 4)
+ pptr[3] = pptr[2] = pptr[1] = pptr[0] = color16;
+ switch (cnt) {
+ case 3: pptr[2] = color16;
+ case 2: pptr[1] = color16;
+ case 1: pptr[0] = color16;
+ case 0: DO_NOTHING;
+ }
+ inc_ptr(dest, draster);
+ }
}
return 0;
}
diff --git a/gs/src/gdevm2.c b/gs/src/gdevm2.c
index 08fbe793f..56ba80b7f 100644
--- a/gs/src/gdevm2.c
+++ b/gs/src/gdevm2.c
@@ -24,8 +24,6 @@
#include "gxdevmem.h" /* semi-public definitions */
#include "gdevmem.h" /* private definitions */
-extern dev_proc_strip_copy_rop(mem_gray_strip_copy_rop);
-
/* ================ Standard (byte-oriented) device ================ */
#undef chunk
diff --git a/gs/src/gdevm24.c b/gs/src/gdevm24.c
index f1b0f9bfd..fd5802d27 100644
--- a/gs/src/gdevm24.c
+++ b/gs/src/gdevm24.c
@@ -24,7 +24,6 @@
#include "gxdevmem.h" /* semi-public definitions */
#include "gdevmem.h" /* private definitions */
-extern dev_proc_strip_copy_rop(mem_gray8_rgb24_strip_copy_rop);
#define mem_true24_strip_copy_rop mem_gray8_rgb24_strip_copy_rop
/*
@@ -162,7 +161,7 @@ mem_true24_fill_rectangle(gx_device * dev,
((bits32 *) pptr)[1] = cword;
pptr += 8;
}
- switch (pptr - limit) {
+ switch ((int)(pptr - limit)) {
case 0:
pptr[6] = (byte) cword;
case 1:
diff --git a/gs/src/gdevm4.c b/gs/src/gdevm4.c
index 66207f107..3bd753c43 100644
--- a/gs/src/gdevm4.c
+++ b/gs/src/gdevm4.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1992, 1995, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1992, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -24,8 +24,6 @@
#include "gxdevmem.h" /* semi-public definitions */
#include "gdevmem.h" /* private definitions */
-extern dev_proc_strip_copy_rop(mem_gray_strip_copy_rop);
-
/* ================ Standard (byte-oriented) device ================ */
#undef chunk
diff --git a/gs/src/gdevm8.c b/gs/src/gdevm8.c
index de9f956df..f9422adc3 100644
--- a/gs/src/gdevm8.c
+++ b/gs/src/gdevm8.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1994, 1995, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -24,8 +24,6 @@
#include "gxdevmem.h" /* semi-public definitions */
#include "gdevmem.h" /* private definitions */
-extern dev_proc_strip_copy_rop(mem_gray8_rgb24_strip_copy_rop);
-
#define mem_gray8_strip_copy_rop mem_gray8_rgb24_strip_copy_rop
/* ================ Standard (byte-oriented) device ================ */
diff --git a/gs/src/gdevmem.h b/gs/src/gdevmem.h
index 3b349387e..9d68987da 100644
--- a/gs/src/gdevmem.h
+++ b/gs/src/gdevmem.h
@@ -211,6 +211,13 @@ extern const gx_device_memory mem_true16_device;
extern const gx_device_memory mem_true24_device;
extern const gx_device_memory mem_true32_device;
extern const gx_device_memory mem_planar_device;
+/*
+ * We declare the RasterOp implementation procedures here because they are
+ * referenced in several implementation modules.
+ */
+dev_proc_strip_copy_rop(mem_mono_strip_copy_rop);
+dev_proc_strip_copy_rop(mem_gray_strip_copy_rop);
+dev_proc_strip_copy_rop(mem_gray8_rgb24_strip_copy_rop);
#if arch_is_big_endian
# define mem_mono_word_device mem_mono_device
diff --git a/gs/src/gdevmiff.c b/gs/src/gdevmiff.c
index 1d22a5450..e3fdd78fd 100644
--- a/gs/src/gdevmiff.c
+++ b/gs/src/gdevmiff.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996, 1997 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1996, 1997, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -33,7 +33,7 @@ private dev_proc_print_page(miff24_print_page);
private const gx_device_procs miff24_procs =
prn_color_procs(gdev_prn_open, gdev_prn_output_page, gdev_prn_close,
gx_default_rgb_map_rgb_color, gx_default_rgb_map_color_rgb);
-gx_device_printer far_data gs_miff24_device =
+gx_device_printer gs_miff24_device =
prn_device(miff24_procs, "miff24",
DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
X_DPI, Y_DPI,
@@ -45,7 +45,7 @@ private int
miff24_print_page(gx_device_printer * pdev, FILE * file)
{
int raster = gx_device_raster((gx_device *) pdev, true);
- byte *line = (byte *) gs_malloc(raster, 1, "miff line buffer");
+ byte *line = gs_alloc_bytes(pdev->memory, raster, "miff line buffer");
int y;
int code = 0; /* return code */
@@ -80,7 +80,7 @@ miff24_print_page(gx_device_printer * pdev, FILE * file)
row += 3;
}
}
- gs_free((char *)line, lsize, 1, "miff line buffer");
+ gs_free_object(pdev->memory, line, "miff line buffer");
return code;
}
diff --git a/gs/src/gdevmr1.c b/gs/src/gdevmr1.c
index 34c194b02..ec8ac77a4 100644
--- a/gs/src/gdevmr1.c
+++ b/gs/src/gdevmr1.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
diff --git a/gs/src/gdevmr2n.c b/gs/src/gdevmr2n.c
index aee1eef40..4652c4d50 100644
--- a/gs/src/gdevmr2n.c
+++ b/gs/src/gdevmr2n.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -31,8 +31,6 @@
#include "gdevmem.h"
#include "gdevmrop.h"
-extern dev_proc_strip_copy_rop(mem_mono_strip_copy_rop);
-
/* Calculate the X offset for a given Y value, */
/* taking shift into account if necessary. */
#define x_offset(px, ty, textures)\
diff --git a/gs/src/gdevnfwd.c b/gs/src/gdevnfwd.c
index f12a9c9da..ed82a0f04 100644
--- a/gs/src/gdevnfwd.c
+++ b/gs/src/gdevnfwd.c
@@ -30,7 +30,8 @@ gx_device_forward_finalize(gx_device *dev)
{
gx_device *target = ((gx_device_forward *)dev)->target;
- rc_decrement(target, "gx_device_forward_finalize");
+ ((gx_device_forward *)dev)->target = 0;
+ rc_decrement_only(target, "gx_device_forward_finalize");
}
/* Set the target of a forwarding device. */
@@ -572,7 +573,7 @@ gx_forward_get_hardware_params(gx_device * dev, gs_param_list * plist)
int
gx_forward_text_begin(gx_device * dev, gs_imager_state * pis,
- const gs_text_params_t * text, const gs_font * font,
+ const gs_text_params_t * text, gs_font * font,
gx_path * path, const gx_device_color * pdcolor,
const gx_clip_path * pcpath, gs_memory_t * memory,
gs_text_enum_t ** ppenum)
diff --git a/gs/src/gdevp2up.c b/gs/src/gdevp2up.c
index b58e96ce6..20dd4a639 100644
--- a/gs/src/gdevp2up.c
+++ b/gs/src/gdevp2up.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1997, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -52,7 +52,7 @@ typedef struct gx_device_2up_s {
private const gx_device_procs pcx2up_procs =
prn_color_procs(pcx2up_open, gdev_prn_output_page, gdev_prn_close,
pc_8bit_map_rgb_color, pc_8bit_map_color_rgb);
-gx_device_2up far_data gs_pcx2up_device =
+gx_device_2up gs_pcx2up_device =
{prn_device_body(gx_device_2up, pcx2up_procs, "pcx2up",
DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
X_DPI, Y_DPI,
diff --git a/gs/src/gdevpbm.c b/gs/src/gdevpbm.c
index f8df447de..885bf1288 100644
--- a/gs/src/gdevpbm.c
+++ b/gs/src/gdevpbm.c
@@ -467,7 +467,7 @@ pbm_print_page_loop(gx_device_printer * pdev, char magic, FILE * pstream,
{
gx_device_pbm * const bdev = (gx_device_pbm *)pdev;
uint raster = gdev_prn_raster(pdev);
- byte *data = (byte *) gs_malloc(raster, 1, "pbm_print_page_loop");
+ byte *data = gs_alloc_bytes(pdev->memory, raster, "pbm_print_page_loop");
int lnum = 0;
int code = 0;
@@ -504,7 +504,7 @@ pbm_print_page_loop(gx_device_printer * pdev, char magic, FILE * pstream,
if (code < 0)
break;
}
- gs_free((char *)data, raster, 1, "pbm_print_page_loop");
+ gs_free_object(pdev->memory, data, "pbm_print_page_loop");
return (code < 0 ? code : 0);
}
@@ -868,7 +868,7 @@ psm_print_page(gx_device_printer * pdev, FILE * pstream)
* component will have 1/N of the bits.)
*/
uint max_raster = bitmap_raster(pdev->width * pdev->color_info.depth);
- byte *data = (byte *)gs_malloc(max_raster, 1, "pksm_print_page");
+ byte *data = gs_alloc_bytes(pdev->memory, max_raster, "pksm_print_page");
int code = 0;
int plane;
@@ -945,6 +945,6 @@ psm_print_page(gx_device_printer * pdev, FILE * pstream)
break;
}
}
- gs_free((char *)data, max_raster, 1, "pksm_print_page");
+ gs_free_object(pdev->memory, data, "pksm_print_page");
return (code < 0 ? code : 0);
}
diff --git a/gs/src/gdevpcx.c b/gs/src/gdevpcx.c
index 6c8f1cbc6..ab8de1e09 100644
--- a/gs/src/gdevpcx.c
+++ b/gs/src/gdevpcx.c
@@ -325,7 +325,7 @@ pcx_write_page(gx_device_printer * pdev, FILE * file, pcx_header * phdr,
int height = pdev->height;
int depth = pdev->color_info.depth;
uint lsize = raster + rsize;
- byte *line = (byte *) gs_malloc(lsize, 1, "pcx file buffer");
+ byte *line = gs_alloc_bytes(pdev->memory, lsize, "pcx file buffer");
byte *plane = line + raster;
int y;
int code = 0; /* return code */
@@ -417,7 +417,7 @@ pcx_write_page(gx_device_printer * pdev, FILE * file, pcx_header * phdr,
}
pcx_done:
- gs_free((char *)line, lsize, 1, "pcx file buffer");
+ gs_free_object(pdev->memory, line, "pcx file buffer");
return code;
}
diff --git a/gs/src/gdevpdf.c b/gs/src/gdevpdf.c
index 90342c3e3..056b7baa3 100644
--- a/gs/src/gdevpdf.c
+++ b/gs/src/gdevpdf.c
@@ -18,95 +18,55 @@
/* PDF-writing driver */
-#include "math_.h"
#include "memory_.h"
#include "string_.h"
-#include "time_.h"
#include "gx.h"
-#include "gp.h"
-#include "gscdefs.h"
#include "gserrors.h"
+#include "gscdefs.h"
#include "gxdevice.h"
-#include "gxfixed.h"
-#include "gxistate.h"
-#include "gxpaint.h"
-#include "gzpath.h"
-#include "gzcpath.h"
#include "gdevpdfx.h"
-#include "scanchar.h"
-#include "strimpl.h" /* for short-sighted compilers */
-#include "scfx.h" /* s_CFE_template is default */
-#include "sstring.h"
-#include "szlibx.h"
-
-/*
- ****** DISABLE GC because we still allocate all temporary data
- ****** on the C heap.
- */
-#define DISABLE_GC
-
-/* Optionally substitute other filters for FlateEncode for debugging. */
-#if 1
-# define compression_filter_name "FlateDecode"
-# define compression_filter_template s_zlibE_template
-# define compression_filter_state stream_zlib_state
-#else
-# include "slzwx.h"
-# define compression_filter_name "LZWDecode"
-# define compression_filter_template s_LZWE_template
-# define compression_filter_state stream_LZW_state
-#endif
-/* Define the size of the internal stream buffer. */
+/* Define the names of the resource types. */
+private const char *const resource_type_names[] = {
+ pdf_resource_type_names
+};
+
+/* Define the size of internal stream buffers. */
/* (This is not a limitation, it only affects performance.) */
#define sbuf_size 512
-/*
- * Define the offset that indicates that a file position is in the
- * resource file (rfile) rather than the main (contents) file.
- * Must be a power of 2, and larger than the largest possible output file.
- */
-#define rfile_base_position min_long
-
/* GC descriptors */
+private_st_pdf_page();
+gs_private_st_element(st_pdf_page_element, pdf_page_t, "pdf_page_t[]",
+ pdf_page_elt_enum_ptrs, pdf_page_elt_reloc_ptrs,
+ st_pdf_page);
private_st_device_pdfwrite();
-private_st_pdf_resource();
-private_st_pdf_font();
-private_st_pdf_char_proc();
/* GC procedures */
-#define pdev ((gx_device_pdf *)vptr)
private
-ENUM_PTRS_BEGIN(device_pdfwrite_enum_ptrs)
+ENUM_PTRS_WITH(device_pdfwrite_enum_ptrs, gx_device_pdf *pdev)
{
-#ifdef DISABLE_GC /* **************** */
- return 0;
-#else /* **************** */
index -= gx_device_pdf_num_ptrs + gx_device_pdf_num_strings;
- if (index < num_resource_types * num_resource_chains)
- ENUM_RETURN(pdev->resources[index / num_resource_chains].chains[index % num_resource_chains]);
- index -= num_resource_types;
- if (index < pdev->outline_depth)
- ENUM_RETURN_STRING_PTR(gx_device_pdf, outline_levels[index].first.action_string);
- index -= pdev->outline_depth;
- if (index < pdev->outline_depth)
- ENUM_RETURN_STRING_PTR(gx_device_pdf, outline_levels[index].last.action_string);
- index -= pdev->outline_depth;
+ if (index < NUM_RESOURCE_TYPES * NUM_RESOURCE_CHAINS)
+ ENUM_RETURN(pdev->resources[index / NUM_RESOURCE_CHAINS].chains[index % NUM_RESOURCE_CHAINS]);
+ index -= NUM_RESOURCE_TYPES * NUM_RESOURCE_CHAINS;
+ if (index <= pdev->outline_depth)
+ ENUM_RETURN(pdev->outline_levels[index].first.action);
+ index -= pdev->outline_depth + 1;
+ if (index <= pdev->outline_depth)
+ ENUM_RETURN(pdev->outline_levels[index].last.action);
+ index -= pdev->outline_depth + 1;
ENUM_PREFIX(st_device_psdf, 0);
-#endif /* **************** */
}
-#ifndef DISABLE_GC /* **************** */
#define e1(i,elt) ENUM_PTR(i, gx_device_pdf, elt);
gx_device_pdf_do_ptrs(e1)
#undef e1
#define e1(i,elt) ENUM_STRING_PTR(i + gx_device_pdf_num_ptrs, gx_device_pdf, elt);
gx_device_pdf_do_strings(e1)
#undef e1
-#endif /* **************** */
ENUM_PTRS_END
-private RELOC_PTRS_BEGIN(device_pdfwrite_reloc_ptrs)
+private RELOC_PTRS_WITH(device_pdfwrite_reloc_ptrs, gx_device_pdf *pdev)
{
-#ifndef DISABLE_GC /* **************** */
RELOC_PREFIX(st_device_psdf);
#define r1(i,elt) RELOC_PTR(gx_device_pdf,elt);
gx_device_pdf_do_ptrs(r1)
@@ -117,18 +77,16 @@ private RELOC_PTRS_BEGIN(device_pdfwrite_reloc_ptrs)
{
int i, j;
- for (i = 0; i < num_resource_types; ++i)
- for (j = 0; j < num_resource_chains; ++j)
+ for (i = 0; i < NUM_RESOURCE_TYPES; ++i)
+ for (j = 0; j < NUM_RESOURCE_CHAINS; ++j)
RELOC_PTR(gx_device_pdf, resources[i].chains[j]);
- for (i = 0; i < pdev->outline_depth; ++i) {
- RELOC_STRING_PTR(gx_device_pdf, outline_levels[i].first.action_string);
- RELOC_STRING_PTR(gx_device_pdf, outline_levels[i].last.action_string);
+ for (i = 0; i <= pdev->outline_depth; ++i) {
+ RELOC_PTR(gx_device_pdf, outline_levels[i].first.action);
+ RELOC_PTR(gx_device_pdf, outline_levels[i].last.action);
}
}
-#endif /* **************** */
}
RELOC_PTRS_END
-#undef pdev
/* Even though device_pdfwrite_finalize is the same as gx_device_finalize, */
/* we need to implement it separately because st_composite_final */
/* declares all 3 procedures as private. */
@@ -138,20 +96,11 @@ device_pdfwrite_finalize(void *vpdev)
gx_device_finalize(vpdev);
}
-/* Device procedures */
+/* Driver procedures */
private dev_proc_open_device(pdf_open);
private dev_proc_output_page(pdf_output_page);
private dev_proc_close_device(pdf_close);
-extern dev_proc_fill_rectangle(gdev_pdf_fill_rectangle); /* in gdevpdfd.c */
-extern dev_proc_copy_mono(gdev_pdf_copy_mono); /* in gdevpdfi.c */
-extern dev_proc_copy_color(gdev_pdf_copy_color); /* in gdevpdfi.c */
-extern dev_proc_get_params(gdev_pdf_get_params); /* in gdevpdfp.c */
-extern dev_proc_put_params(gdev_pdf_put_params); /* in gdevpdfp.c */
-extern dev_proc_fill_path(gdev_pdf_fill_path); /* in gdevpdfd.c */
-extern dev_proc_stroke_path(gdev_pdf_stroke_path); /* in gdevpdfd.c */
-extern dev_proc_fill_mask(gdev_pdf_fill_mask); /* in gdevpdfi.c */
-extern dev_proc_begin_image(gdev_pdf_begin_image); /* in gdevpdfi.c */
-extern dev_proc_strip_tile_rectangle(gdev_pdf_strip_tile_rectangle); /* in gdevpdfi.c */
+/* Driver procedures defined in other files are declared in gdevpdfx.h. */
#ifndef X_DPI
# define X_DPI 720
@@ -200,31 +149,36 @@ const gx_device_pdf gs_pdfwrite_device =
gdev_pdf_begin_image,
NULL, /* image_data */
NULL, /* end_image */
- gdev_pdf_strip_tile_rectangle
+ gdev_pdf_strip_tile_rectangle,
+ NULL, /* strip_copy_rop */
+ NULL, /* get_clipping_box */
+ NULL, /* begin_typed_image */
+ NULL, /* get_bits_rectangle */
+ NULL, /* map_color_rgb_alpha */
+ NULL, /* create_compositor */
+ NULL, /* get_hardware_params */
+ gdev_pdf_text_begin
},
- psdf_initial_values(psdf_version_level2, 0 /*false */ ), /* (!ASCII85EncodePages) */
- 1.2, /* CompatibilityLevel */
+ psdf_initial_values(psdf_version_ll3, 0 /*false */ ), /* (!ASCII85EncodePages) */
+ 1.3, /* CompatibilityLevel */
1 /*true */ , /* ReAssignCharacters */
1 /*true */ , /* ReEncodeCharacters */
1, /* FirstObjectNumber */
pdf_compress_none, /* compression */
- {0}, /* tfname */
- 0, /* tfile */
- {0}, /* rfname */
- 0, /* rfile */
- 0, /* rstrm */
- 0, /* rstrmbuf */
- 0, /* rsave_strm */
+ {{0}}, /* xref */
+ {{0}}, /* asides */
+ {{0}}, /* streams */
+ {{0}}, /* pictures */
0, /* open_font */
0, /* embedded_encoding_id */
0, /* next_id */
- 0, /* root_id */
- 0, /* info_id */
- 0, /* pages_id */
+ 0, /* Catalog */
+ 0, /* Info */
+ 0, /* Pages */
0, /* outlines_id */
0, /* next_page */
0, /* contents_id */
- pdf_in_none, /* context */
+ PDF_IN_NONE, /* context */
0, /* contents_length_id */
0, /* contents_pos */
NoMarks, /* procsets */
@@ -232,18 +186,13 @@ const gx_device_pdf gs_pdfwrite_device =
{gx_line_params_initial}, /* line_params */
{pdf_text_state_default}, /* text */
{0}, /* space_char_ids */
- 0, /* page_ids */
- 0, /* num_page_ids */
- 0, /* pages_referenced */
+ 0, /* pages */
+ 0, /* num_pages */
{
{
{0}}}, /* resources */
- 0 /*false*/, /* have_patterns */
- 0, /* annots */
+ 0, /* cs_Pattern */
0, /* last_resource */
- {0, 0}, /* catalog_string */
- {0, 0}, /* pages_string */
- {0, 0}, /* page_string */
{
{
{0}}}, /* outline_levels */
@@ -251,923 +200,373 @@ const gx_device_pdf gs_pdfwrite_device =
0, /* closed_outline_depth */
0, /* outlines_open */
0, /* articles */
- 0, /* named_dests */
+ 0, /* Dests */
0, /* named_objects */
0 /* open_graphics */
};
-/* ---------------- Utilities ---------------- */
-
-/* ------ Document ------ */
-
-/* Initialize the IDs allocated at startup. */
-void
-pdf_initialize_ids(gx_device_pdf * pdev)
-{
- pdev->next_id = pdev->FirstObjectNumber;
- pdev->root_id = pdf_obj_ref(pdev);
- pdev->pages_id = pdf_obj_ref(pdev);
-}
-
-/* Open the document if necessary. */
-void
-pdf_open_document(gx_device_pdf * pdev)
-{
- if (!is_in_document(pdev) && pdf_stell(pdev) == 0) {
- stream *s = pdev->strm;
-
- pprintd1(s, "%%PDF-1.%d\n",
- (pdev->CompatibilityLevel >= 1.2 ? 2 : 1));
- pdev->binary_ok = !pdev->params.ASCII85EncodePages;
- if (pdev->binary_ok)
- pputs(s, "%\307\354\217\242\n");
- }
- /*
- * Determine the compression method. Currently this does nothing.
- * It also isn't clear whether the compression method can now be
- * changed in the course of the document.
- *
- * The following algorithm is per an update to TN # 5151 by
- * Adobe Developer Support.
- */
- if (!pdev->params.CompressPages)
- pdev->compression = pdf_compress_none;
- else if (pdev->CompatibilityLevel < 1.2)
- pdev->compression = pdf_compress_LZW;
- else if (pdev->params.UseFlateCompression)
- pdev->compression = pdf_compress_Flate;
- else
- pdev->compression = pdf_compress_LZW;
-}
-
-/* ------ Objects ------ */
-
-/* Allocate an object ID. */
-private long
-pdf_next_id(gx_device_pdf * pdev)
-{
- return (pdev->next_id)++;
-}
-
-/* Return the current position in the output. */
-/* Note that this may be in either the main file or the resource file. */
-long
-pdf_stell(gx_device_pdf * pdev)
-{
- stream *s = pdev->strm;
- long pos = stell(s);
-
- if (s == pdev->rstrm)
- pos += rfile_base_position;
- return pos;
-}
-
-/* Allocate an ID for a future object. */
-long
-pdf_obj_ref(gx_device_pdf * pdev)
-{
- long id = pdf_next_id(pdev);
- long pos = pdf_stell(pdev);
-
- fwrite(&pos, sizeof(pos), 1, pdev->tfile);
- return id;
-}
-
-/* Begin an object, optionally allocating an ID. */
-long
-pdf_open_obj(gx_device_pdf * pdev, long id)
-{
- stream *s = pdev->strm;
+/* ---------------- Device open/close ---------------- */
- if (id <= 0) {
- id = pdf_obj_ref(pdev);
+/* Close and remove temporary files. */
+private void
+pdf_close_temp_file(gx_device_pdf *pdev, pdf_temp_file_t *ptf)
+{
+ if (ptf->strm) {
+ gs_free_object(pdev->pdf_memory, ptf->strm_buf,
+ "pdf_close_temp_file(strm_buf)");
+ ptf->strm_buf = 0;
+ gs_free_object(pdev->pdf_memory, ptf->strm,
+ "pdf_close_temp_file(strm)");
+ ptf->strm = 0;
+ /* Closing strm also closes file. */
} else {
- long pos = pdf_stell(pdev);
- FILE *tfile = pdev->tfile;
- long tpos = ftell(tfile);
-
- fseek(tfile, (id - pdev->FirstObjectNumber) * sizeof(pos),
- SEEK_SET);
- fwrite(&pos, sizeof(pos), 1, tfile);
- fseek(tfile, tpos, SEEK_SET);
+ if (ptf->file)
+ fclose(ptf->file);
+ }
+ if (ptf->file) {
+ unlink(ptf->file_name);
+ ptf->file = 0;
}
- pprintld1(s, "%ld 0 obj\n", id);
- return id;
+ ptf->save_strm = 0;
}
-
-/* End an object. */
-int
-pdf_end_obj(gx_device_pdf * pdev)
+private void
+pdf_close_files(gx_device_pdf * pdev)
{
- pputs(pdev->strm, "endobj\n");
- return 0;
+ pdf_close_temp_file(pdev, &pdev->pictures);
+ pdf_close_temp_file(pdev, &pdev->streams);
+ pdf_close_temp_file(pdev, &pdev->asides);
+ pdf_close_temp_file(pdev, &pdev->xref);
}
-/* ------ Graphics ------ */
-
-/* Reset the graphics state parameters to initial values. */
-void
-pdf_reset_graphics(gx_device_pdf * pdev)
+/* Reset the state of the current page. */
+private void
+pdf_reset_page(gx_device_pdf * pdev)
{
- color_set_pure(&pdev->fill_color, 0); /* black */
- color_set_pure(&pdev->stroke_color, 0); /* ditto */
- pdev->flatness = -1;
+ pdev->contents_id = 0;
+ pdf_reset_graphics(pdev);
+ pdev->procsets = NoMarks;
+ pdev->cs_Pattern = 0; /* simplest to create one for each page */
{
- static const gx_line_params lp_initial =
- {gx_line_params_initial};
+ static const pdf_text_state_t text_default = {
+ pdf_text_state_default
+ };
- pdev->line_params = lp_initial;
+ pdev->text = text_default;
}
}
-/* Set the fill or stroke color. */
-int
-pdf_set_color(gx_device_pdf * pdev, gx_color_index color,
- gx_drawing_color * pdcolor, const char *rgs)
+/* Open a temporary file, with or without a stream. */
+private int
+pdf_open_temp_file(gx_device_pdf *pdev, pdf_temp_file_t *ptf)
{
- if (gx_dc_pure_color(pdcolor) != color) {
- int code;
+ char fmode[4];
- /*
- * In principle, we can set colors in either stream or text
- * context. However, since we currently enclose all text
- * strings inside a gsave/grestore, this causes us to lose
- * track of the color when we leave text context. Therefore,
- * we require stream context for setting colors.
- */
-#if 0
- switch (pdev->context) {
- case pdf_in_stream:
- case pdf_in_text:
- break;
- case pdf_in_none:
- code = pdf_open_page(pdev, pdf_in_stream);
- goto open;
- case pdf_in_string:
- code = pdf_open_page(pdev, pdf_in_text);
- open:if (code < 0)
- return code;
- }
-#else
- code = pdf_open_page(pdev, pdf_in_stream);
- if (code < 0)
- return code;
-#endif
- color_set_pure(pdcolor, color);
- psdf_set_color((gx_device_vector *) pdev, pdcolor, rgs);
- }
+ strcpy(fmode, "w+");
+ strcat(fmode, gp_fmode_binary_suffix);
+ ptf->file =
+ gp_open_scratch_file(gp_scratch_file_name_prefix,
+ ptf->file_name, fmode);
+ if (ptf->file == 0)
+ return_error(gs_error_invalidfileaccess);
return 0;
}
-
-/* Write matrix values. */
-void
-pdf_put_matrix(gx_device_pdf * pdev, const char *before,
- const gs_matrix * pmat, const char *after)
+private int
+pdf_open_temp_stream(gx_device_pdf *pdev, pdf_temp_file_t *ptf)
{
- stream *s = pdev->strm;
-
- if (before)
- pputs(s, before);
- pprintg6(s, "%g %g %g %g %g %g ",
- pmat->xx, pmat->xy, pmat->yx, pmat->yy, pmat->tx, pmat->ty);
- if (after)
- pputs(s, after);
-}
+ int code = pdf_open_temp_file(pdev, ptf);
-/*
- * Write a name, with escapes for unusual characters. In PDF 1.1, we have
- * no choice but to replace these characters with '?'; in PDF 1.2, we can
- * use an escape sequence for anything except a null <00>.
- */
-void
-pdf_put_name(const gx_device_pdf * pdev, const byte * nstr, uint size)
-{
- stream *s = pdev->strm;
- uint i;
- bool escape = pdev->CompatibilityLevel >= 1.2;
- char hex[4];
-
- pputc(s, '/');
- for (i = 0; i < size; ++i) {
- uint c = nstr[i];
-
- switch (c) {
- case '%':
- case '(':
- case ')':
- case '<':
- case '>':
- case '[':
- case ']':
- case '{':
- case '}':
- /* These characters are invalid in both 1.1 and 1.2, */
- /* but can be escaped in 1.2. */
- if (escape) {
- sprintf(hex, "#%02x", c);
- pputs(s, hex);
- break;
- }
- /* falls through */
- case 0:
- /* This is invalid in 1.1 and 1.2, and cannot be escaped. */
- pputc(s, '?');
- break;
- case '/':
- case '#':
- /* These are valid in 1.1, but must be escaped in 1.2. */
- if (escape) {
- sprintf(hex, "#%02x", c);
- pputs(s, hex);
- break;
- }
- /* falls through */
- default:
- pputc(s, c);
- }
+ if (code < 0)
+ return code;
+ ptf->strm = s_alloc(pdev->pdf_memory, "pdf_open_temp_stream(strm)");
+ if (ptf->strm == 0)
+ return_error(gs_error_VMerror);
+ ptf->strm_buf = gs_alloc_bytes(pdev->pdf_memory, sbuf_size,
+ "pdf_open_temp_stream(strm_buf)");
+ if (ptf->strm_buf == 0) {
+ gs_free_object(pdev->pdf_memory, ptf->strm,
+ "pdf_open_temp_stream(strm)");
+ ptf->strm = 0;
+ return_error(gs_error_VMerror);
}
+ swrite_file(ptf->strm, ptf->file, ptf->strm_buf, sbuf_size);
+ return 0;
}
-/*
- * Write a string in its shortest form ( () or <> ). Note that
- * this form is different depending on whether binary data are allowed.
- * We wish PDF supported ASCII85 strings ( <~ ~> ), but it doesn't.
- */
-void
-pdf_put_string(const gx_device_pdf * pdev, const byte * str, uint size)
-{
- psdf_write_string(pdev->strm, str, size,
- (pdev->binary_ok ? print_binary_ok : 0));
-}
-
-/* Write a value, treating names specially. */
+/* Initialize the IDs allocated at startup. */
void
-pdf_put_value(const gx_device_pdf * pdev, const byte * vstr, uint size)
-{
- if (vstr[0] == '/')
- pdf_put_name(pdev, vstr + 1, size - 1);
- else
- pwrite(pdev->strm, vstr, size);
-}
-
-/* ------ Page contents ------ */
-
-/* Handle transitions between contexts. */
-private int
- none_to_stream(P1(gx_device_pdf *)), stream_to_text(P1(gx_device_pdf *)),
- string_to_text(P1(gx_device_pdf *)), text_to_stream(P1(gx_device_pdf *)),
- stream_to_none(P1(gx_device_pdf *));
-typedef int (*context_proc) (P1(gx_device_pdf *));
-private const context_proc context_procs[4][4] =
-{
- {0, none_to_stream, none_to_stream, none_to_stream},
- {stream_to_none, 0, stream_to_text, stream_to_text},
- {text_to_stream, text_to_stream, 0, 0},
- {string_to_text, string_to_text, string_to_text, 0}
-};
-
-/* Enter stream context. */
-private int
-none_to_stream(gx_device_pdf * pdev)
-{
- stream *s;
-
- if (pdev->contents_id != 0)
- return_error(gs_error_Fatal); /* only 1 contents per page */
- pdev->contents_id = pdf_begin_obj(pdev);
- pdev->contents_length_id = pdf_obj_ref(pdev);
- s = pdev->strm;
- pprintld1(s, "<</Length %ld 0 R", pdev->contents_length_id);
- if (pdev->compression == pdf_compress_Flate)
- pprints1(s, "/Filter /%s", compression_filter_name);
- pputs(s, ">>\nstream\n");
- pdev->contents_pos = pdf_stell(pdev);
- if (pdev->compression == pdf_compress_Flate) { /* Set up the Flate filter. */
- const stream_template *template = &compression_filter_template;
- stream *es = s_alloc(pdev->pdf_memory, "PDF compression stream");
- byte *buf = gs_alloc_bytes(pdev->pdf_memory, sbuf_size,
- "PDF compression buffer");
- compression_filter_state *st =
- gs_alloc_struct(pdev->pdf_memory, compression_filter_state,
- template->stype, "PDF compression state");
-
- if (es == 0 || st == 0 || buf == 0)
- return_error(gs_error_VMerror);
- s_std_init(es, buf, sbuf_size, &s_filter_write_procs,
- s_mode_write);
- st->memory = pdev->pdf_memory;
- st->template = template;
- es->state = (stream_state *) st;
- es->procs.process = template->process;
- es->strm = s;
- (*template->set_defaults) ((stream_state *) st);
- (*template->init) ((stream_state *) st);
- pdev->strm = s = es;
- }
- /* Scale the coordinate system. */
- pprintg2(s, "%g 0 0 %g 0 0 cm\n",
- 72.0 / pdev->HWResolution[0], 72.0 / pdev->HWResolution[1]);
- /* Do a level of gsave for the clipping path. */
- pputs(s, "q\n");
- return pdf_in_stream;
-}
-/* Enter text context from stream context. */
-private int
-stream_to_text(gx_device_pdf * pdev)
-{ /*
- * Bizarrely enough, Acrobat Reader cares how the final font size is
- * obtained -- the CTM (cm), text matrix (Tm), and font size (Tf)
- * are *not* all equivalent. In particular, it seems to use the
- * product of the text matrix and font size to decide how to
- * anti-alias characters. Therefore, we have to temporarily patch
- * the CTM so that the scale factors are unity. What a nuisance!
- */
- pprintg2(pdev->strm, "q %g 0 0 %g 0 0 cm BT\n",
- pdev->HWResolution[0] / 72.0, pdev->HWResolution[1] / 72.0);
- pdev->procsets |= Text;
- gs_make_identity(&pdev->text.matrix);
- pdev->text.line_start.x = pdev->text.line_start.y = 0;
- pdev->text.buffer_count = 0;
- return pdf_in_text;
-}
-/* Exit string context to text context. */
-private int
-string_to_text(gx_device_pdf * pdev)
-{
- pdf_put_string(pdev, pdev->text.buffer, pdev->text.buffer_count);
- pputs(pdev->strm, "Tj\n");
- pdev->text.buffer_count = 0;
- return pdf_in_text;
-}
-/* Exit text context to stream context. */
-private int
-text_to_stream(gx_device_pdf * pdev)
-{
- pputs(pdev->strm, "ET Q\n");
- pdev->text.font = 0; /* because of Q */
- return pdf_in_stream;
-}
-/* Exit stream context. */
-private int
-stream_to_none(gx_device_pdf * pdev)
+pdf_initialize_ids(gx_device_pdf * pdev)
{
- stream *s = pdev->strm;
- long length;
+ gs_param_string nstr;
+ char buf[200];
- if (pdev->compression == pdf_compress_Flate) { /* Terminate the Flate filter. */
- stream *fs = s->strm;
-
- sclose(s);
- gs_free_object(pdev->pdf_memory, s->cbuf, "zlib buffer");
- gs_free_object(pdev->pdf_memory, s, "zlib stream");
- pdev->strm = s = fs;
- }
- length = pdf_stell(pdev) - pdev->contents_pos;
- pputs(s, "endstream\n");
- pdf_end_obj(pdev);
- pdf_open_obj(pdev, pdev->contents_length_id);
- pprintld1(s, "%ld\n", length);
- pdf_end_obj(pdev);
- return pdf_in_none;
-}
+ pdev->next_id = pdev->FirstObjectNumber;
-/* Begin a page contents part. */
-int
-pdf_open_contents(gx_device_pdf * pdev, pdf_context context)
-{
- int (*proc) (P1(gx_device_pdf *));
+ /* Initialize the Catalog. */
- while ((proc = context_procs[pdev->context][context]) != 0) {
- int code = (*proc) (pdev);
+ param_string_from_string(nstr, "{Catalog}");
+ pdf_create_named_dict(pdev, &nstr, &pdev->Catalog, 0L);
- if (code < 0)
- return code;
- pdev->context = (pdf_context) code;
- }
- pdev->context = context;
- return 0;
-}
+ /* Initialize the Info dictionary. */
-/* Close the current contents part if we are in one. */
-int
-pdf_close_contents(gx_device_pdf * pdev, bool last)
-{
- if (pdev->context == pdf_in_none)
- return 0;
- if (last) { /* Exit from the clipping path gsave. */
- pdf_open_contents(pdev, pdf_in_stream);
- pputs(pdev->strm, "Q\n");
- pdev->text.font = 0;
- }
- return pdf_open_contents(pdev, pdf_in_none);
-}
+ param_string_from_string(nstr, "{DocInfo}");
+ pdf_create_named_dict(pdev, &nstr, &pdev->Info, 0L);
+ sprintf(buf, "(%s %1.2f)", gs_product, gs_revision / 100.0);
+ cos_dict_put_c_strings(pdev->Info, pdev, "/Producer", buf);
-/* ------ Resources et al ------ */
+ /* Allocate the root of the pages tree. */
-/* Define the names of the resource types. */
-private const char *const resource_names[] =
-{pdf_resource_type_names};
-
-/* Define the allocator descriptors for the resource types. */
-extern const gs_memory_struct_type_t st_pdf_named_object; /* in gdevpdfo.c */
-private const gs_memory_struct_type_t *const resource_structs[] =
-{pdf_resource_type_structs};
-
-/* Find a resource of a given type by gs_id. */
-pdf_resource *
-pdf_find_resource_by_gs_id(gx_device_pdf * pdev, pdf_resource_type type,
- gs_id rid)
-{
- pdf_resource **pchain =
- &pdev->resources[type].chains[gs_id_hash(rid) % num_resource_chains];
- pdf_resource **pprev = pchain;
- pdf_resource *pres;
-
- for (; (pres = *pprev) != 0; pprev = &pres->next)
- if (pres->rid == rid) {
- if (pprev != pchain) {
- *pprev = pres->next;
- pres->next = *pchain;
- *pchain = pres;
- }
- return pres;
- }
- return 0;
+ pdf_create_named_dict(pdev, NULL, &pdev->Pages, 0L);
}
-/* Begin an object logically separate from the contents. */
-long
-pdf_open_separate(gx_device_pdf * pdev, long id)
-{
- pdf_open_document(pdev);
- pdev->rsave_strm = pdev->strm;
- pdev->strm = pdev->rstrm;
- return pdf_open_obj(pdev, id);
-}
-
-/* Begin an aside (resource, annotation, ...). */
+/* Open the device. */
private int
-pdf_alloc_aside(gx_device_pdf * pdev, pdf_resource ** plist,
- const gs_memory_struct_type_t * pst, pdf_resource ** ppres)
-{
- pdf_resource *pres;
-
- if (pst == NULL)
- pst = &st_pdf_resource;
- pres =
- gs_alloc_struct(pdev->pdf_memory, pdf_resource, pst, "begin_aside");
- if (pres == 0)
- return_error(gs_error_VMerror);
- pres->next = *plist;
- *plist = pres;
- pres->prev = pdev->last_resource;
- pdev->last_resource = pres;
- *ppres = pres;
- return 0;
-}
-int
-pdf_begin_aside(gx_device_pdf * pdev, pdf_resource ** plist,
- const gs_memory_struct_type_t * pst, pdf_resource ** ppres)
+pdf_open(gx_device * dev)
{
- long id = pdf_begin_separate(pdev);
+ gx_device_pdf *const pdev = (gx_device_pdf *) dev;
+ gs_memory_t *mem = pdev->pdf_memory = gs_memory_stable(pdev->memory);
int code;
- if (id < 0)
- return id;
- code = pdf_alloc_aside(pdev, plist, pst, ppres);
+ if ((code = pdf_open_temp_file(pdev, &pdev->xref)) < 0 ||
+ (code = pdf_open_temp_stream(pdev, &pdev->asides)) < 0 ||
+ (code = pdf_open_temp_stream(pdev, &pdev->streams)) < 0 ||
+ (code = pdf_open_temp_stream(pdev, &pdev->pictures)) < 0
+ )
+ goto fail;
+ code = gdev_vector_open_file((gx_device_vector *) pdev, sbuf_size);
if (code < 0)
- return code;
- (*ppres)->id = id;
- return 0;
-}
-
-/* Begin a resource of a given type. */
-int
-pdf_begin_resource_body(gx_device_pdf * pdev, pdf_resource_type type,
- gs_id rid, pdf_resource ** ppres)
-{
- return pdf_begin_aside(pdev,
- &pdev->resources[type].chains[gs_id_hash(rid) % num_resource_chains],
- resource_structs[type], ppres);
-}
-int
-pdf_begin_resource(gx_device_pdf * pdev, pdf_resource_type type, gs_id rid,
- pdf_resource ** ppres)
-{
- int code = pdf_begin_resource_body(pdev, type, rid, ppres);
-
- if (code >= 0 && resource_names[type] != 0) {
- stream *s = pdev->strm;
-
- pprints1(s, "<</Type/%s", resource_names[type]);
- pprintld1(s, "/Name/R%ld", (*ppres)->id);
+ goto fail;
+ gdev_vector_init((gx_device_vector *) pdev);
+ /* Set in_page so the vector routines won't try to call */
+ /* any vector implementation procedures. */
+ pdev->in_page = true;
+ /*
+ * pdf_initialize_ids allocates some named objects, so we must
+ * initialize the named objects list now.
+ */
+ pdev->named_objects = cos_dict_alloc(mem, "pdf_open(named_objects)");
+ pdf_initialize_ids(pdev);
+ pdev->outlines_id = 0;
+ pdev->next_page = 0;
+ memset(pdev->space_char_ids, 0, sizeof(pdev->space_char_ids));
+ pdev->pages =
+ gs_alloc_struct_array(mem, initial_num_pages, pdf_page_t,
+ &st_pdf_page_element, "pdf_open(pages)");
+ if (pdev->pages == 0) {
+ code = gs_error_VMerror;
+ goto fail;
}
- return code;
-}
-
-/* Allocate a resource, but don't open the stream. */
-int
-pdf_alloc_resource(gx_device_pdf * pdev, pdf_resource_type type, gs_id rid,
- pdf_resource ** ppres)
-{
- int code = pdf_alloc_aside(pdev,
- &pdev->resources[type].chains[gs_id_hash(rid) % num_resource_chains],
- resource_structs[type], ppres);
-
- if (code < 0)
- return code;
- (*ppres)->id = pdf_obj_ref(pdev);
- return 0;
-}
-
-/* End an aside or other separate object. */
-int
-pdf_end_aside(gx_device_pdf * pdev)
-{
- int code = pdf_end_obj(pdev);
-
- pdev->strm = pdev->rsave_strm;
- return code;
-}
-/* End a resource. */
-int
-pdf_end_resource(gx_device_pdf * pdev)
-{
- return pdf_end_aside(pdev);
-}
-
-/* ------ Pages ------ */
-
-/* Reset the state of the current page. */
-void
-pdf_reset_page(gx_device_pdf * pdev, bool first_page)
-{
- pdev->contents_id = 0;
- pdf_reset_graphics(pdev);
- pdev->procsets = NoMarks;
+ memset(pdev->pages, 0, initial_num_pages * sizeof(pdf_page_t));
+ pdev->num_pages = initial_num_pages;
{
int i, j;
- for (i = 0; i < num_resource_types; ++i)
- if (first_page ||
- !(i == resourceFont || resource_names[i] == 0)
- )
- for (j = 0; j < num_resource_chains; ++j)
- pdev->resources[i].chains[j] = 0;
- }
- pdev->cs_Pattern = 0; /* simplest to create one for each page */
- pdev->page_string.data = 0;
- {
- static const pdf_text_state text_default =
- {pdf_text_state_default};
-
- pdev->text = text_default;
- }
-}
-
-/* Get or assign the ID for a page. */
-/* Returns 0 if the page number is out of range. */
-long
-pdf_page_id(gx_device_pdf * pdev, int page_num)
-{
- long page_id;
-
- if (page_num >= pdev->num_page_ids) { /* Grow the page_ids array. */
- uint new_num_ids =
- max(page_num + 10, pdev->num_page_ids << 1);
-
- /* resize_object for a byte array takes a new object size */
- /* in bytes. This is a quirk of the API that we probably */
- /* won't ever be able to fix.... */
- long *new_ids = gs_resize_object(pdev->pdf_memory, pdev->page_ids,
- new_num_ids * sizeof(long),
- "pdf_page_id(resize page_ids)");
-
- if (new_ids == 0)
- return 0;
- pdev->page_ids = new_ids;
- pdev->num_page_ids = new_num_ids;
+ for (i = 0; i < NUM_RESOURCE_TYPES; ++i)
+ for (j = 0; j < NUM_RESOURCE_CHAINS; ++j)
+ pdev->resources[i].chains[j] = 0;
}
- if (page_num < 1)
- return 0;
- while (page_num > pdev->pages_referenced)
- pdev->page_ids[pdev->pages_referenced++] = 0;
- if ((page_id = pdev->page_ids[page_num - 1]) == 0)
- pdev->page_ids[page_num - 1] = page_id = pdf_obj_ref(pdev);
- return page_id;
-}
+ pdev->outline_levels[0].first.id = 0;
+ pdev->outline_levels[0].left = max_int;
+ pdev->outline_levels[0].first.action = 0;
+ pdev->outline_levels[0].last.action = 0;
+ pdev->outline_depth = 0;
+ pdev->closed_outline_depth = 0;
+ pdev->outlines_open = 0;
+ pdev->articles = 0;
+ pdev->Dests = 0;
+ /* named_objects was initialized above */
+ pdev->open_graphics = 0;
+ pdf_reset_page(pdev);
-/* Write saved page- or document-level information. */
-int
-pdf_write_saved_string(gx_device_pdf * pdev, gs_string * pstr)
-{
- if (pstr->data != 0) {
- pwrite(pdev->strm, pstr->data, pstr->size);
- gs_free_string(pdev->pdf_memory, pstr->data, pstr->size,
- "pdf_write_saved_string");
- pstr->data = 0;
- }
return 0;
-}
-
-/* Open a page for writing. */
-int
-pdf_open_page(gx_device_pdf * pdev, pdf_context context)
-{
- if (!is_in_page(pdev)) {
- if (pdf_page_id(pdev, pdev->next_page + 1) == 0)
- return_error(gs_error_VMerror);
- pdf_open_document(pdev);
- }
- /* Note that context may be pdf_in_none here. */
- return pdf_open_contents(pdev, context);
+ fail:
+ pdf_close_files(pdev);
+ return code;
}
/* Close the current page. */
private int
pdf_close_page(gx_device_pdf * pdev)
{
- stream *s;
int page_num = ++(pdev->next_page);
- long page_id;
+ pdf_page_t *page;
- /* If the very first page is blank, we need to open the document */
- /* before doing anything else. */
+ /*
+ * If the very first page is blank, we need to open the document
+ * before doing anything else.
+ */
pdf_open_document(pdev);
pdf_close_contents(pdev, true);
- page_id = pdf_page_id(pdev, page_num);
- pdf_open_obj(pdev, page_id);
- s = pdev->strm;
- pprintd2(s, "<<\n/Type /Page\n/MediaBox [0 0 %d %d]\n",
- (int)(pdev->MediaSize[0]), (int)(pdev->MediaSize[1]));
- pprintld1(s, "/Parent %ld 0 R\n", pdev->pages_id);
- pputs(s, "/Resources << /ProcSet [/PDF");
- if (pdev->procsets & ImageB)
- pputs(s, " /ImageB");
- if (pdev->procsets & ImageC)
- pputs(s, " /ImageC");
- if (pdev->procsets & ImageI)
- pputs(s, " /ImageI");
- if (pdev->procsets & Text)
- pputs(s, " /Text");
- pputs(s, "]\n");
+ /*
+ * We can't write the page object or the annotations array yet, because
+ * later pdfmarks might add elements to them. Write the other objects
+ * that the page references, and record what we'll need later.
+ *
+ * Start by making sure the pages array element exists.
+ */
+ pdf_page_id(pdev, page_num);
+ page = &pdev->pages[page_num - 1];
+ page->MediaBox.x = (int)(pdev->MediaSize[0]);
+ page->MediaBox.y = (int)(pdev->MediaSize[1]);
+ page->procsets = pdev->procsets;
+ page->contents_id = pdev->contents_id;
+ /* Write out any resource dictionaries. */
{
int i;
- for (i = 0; i < num_resource_types; ++i)
- if (!(i == resourceFont || resource_names[i] == 0)) {
- bool first = true;
- int j;
- const pdf_resource *pres;
-
- for (j = 0; j < num_resource_chains; ++j) {
- for (pres = pdev->resources[i].chains[j];
- pres != 0; pres = pres->next
- ) {
- if (first)
- pprints1(s, "/%s<<", resource_names[i]), first = false;
- pprintld2(s, "/R%ld\n%ld 0 R", pres->id, pres->id);
+ for (i = 0; i < resourceFont; ++i) {
+ bool any = false;
+ stream *s;
+ int j;
+
+ for (j = 0; j < NUM_RESOURCE_CHAINS; ++j) {
+ pdf_resource_t **prev = &pdev->resources[i].chains[j];
+ pdf_resource_t *pres;
+
+ while ((pres = *prev) != 0) {
+ if (pres->used_on_page) {
+ long id = pres->object->id;
+
+ if (!any) {
+ page->resource_ids[i] = pdf_begin_obj(pdev);
+ s = pdev->strm;
+ pputs(s, "<<");
+ any = true;
+ }
+ pprintld2(s, "/R%ld\n%ld 0 R", id, id);
}
- pdev->resources[i].chains[j] = 0;
+ if (pres->named) {
+ /* Named resource, might be used again. */
+ prev = &pres->next;
+ } else
+ *prev = pres->next;
}
- if (!first)
- pputs(s, ">>\n");
}
+ if (any) {
+ pputs(s, ">>\n");
+ pdf_end_obj(pdev);
+ }
+ }
}
- /* Put out references to just those fonts used on this page. */
+ /* Record references to just those fonts used on this page. */
{
- bool first = true;
+ bool any = false;
+ stream *s;
int j;
- pdf_font *font;
- for (j = 0; j < num_resource_chains; ++j)
- for (font = (pdf_font *) pdev->resources[resourceFont].chains[j];
- font != 0; font = font->next
- )
+ for (j = 0; j < NUM_RESOURCE_CHAINS; ++j) {
+ pdf_font_t **prev =
+ (pdf_font_t **)&pdev->resources[resourceFont].chains[j];
+ pdf_font_t *font;
+
+ while ((font = *prev) != 0) {
if (font->used_on_page) {
- if (first)
- pputs(s, "/Font <<\n"), first = false;
- if (font->frname[0])
- pprints1(s, "/%s", font->frname);
- else
- pprintld1(s, "/R%ld", font->id);
- pprintld1(s, " %ld 0 R\n", font->id);
+ if (!any) {
+ page->fonts_id = pdf_begin_obj(pdev);
+ s = pdev->strm;
+ pputs(s, "<<");
+ any = true;
+ }
+ pprints1(s, "/%s", font->frname);
+ pprintld1(s, "\n%ld 0 R", font->object->id);
font->used_on_page = false;
}
- if (!first)
- pputs(s, ">>\n");
- }
- pputs(s, ">>\n");
- if (pdev->contents_id == 0)
- pputs(s, "/Contents []\n");
- else
- pprintld1(s, "/Contents %ld 0 R\n", pdev->contents_id);
- pdf_write_saved_string(pdev, &pdev->page_string);
- {
- const pdf_resource *pres = pdev->annots;
- bool any = false;
-
- for (; pres != 0; pres = pres->next)
- if (pres->rid == page_num - 1) {
- if (!any) {
- pputs(s, "/Annots [\n");
- any = true;
- }
- pprintld1(s, "%ld 0 R\n", pres->id);
+ if (font->skip) {
+ /* The font was already written and freed. */
+ *prev = font->next;
+ } else
+ prev = &font->next;
}
- if (any)
- pputs(s, "]\n");
+ }
+ if (any) {
+ pputs(s, ">>\n");
+ pdf_end_obj(pdev);
+ }
}
- pputs(s, ">>\n");
- pdf_end_obj(pdev);
- pdf_reset_page(pdev, false);
+ pdf_reset_page(pdev);
return 0;
}
-/* Write the default entries of the Info dictionary. */
-int
-pdf_write_default_info(gx_device_pdf * pdev)
+/* Write the page object. */
+private int
+pdf_write_page(gx_device_pdf *pdev, int page_num)
{
- stream *s = pdev->strm;
-
- /* Reading the time without using time_t is a challenge.... */
- long t[2]; /* time_t can't be longer than 2 longs. */
- struct tm ltime;
- char buf[20];
-
- time((void *)t);
- ltime = *localtime((void *)t);
- sprintf(buf, "%04d%02d%02d%02d%02d%02d",
- ltime.tm_year + 1900, ltime.tm_mon + 1, ltime.tm_mday,
- ltime.tm_hour, ltime.tm_min, ltime.tm_sec);
- pprints1(s, "/CreationDate (D:%s)\n", buf);
- sprintf(buf, "%1.2f", gs_revision / 100.0);
- pprints2(s, "/Producer (%s %s)\n", gs_product, buf);
- return 0;
-}
+ long page_id = pdf_page_id(pdev, page_num);
+ pdf_page_t *page = &pdev->pages[page_num - 1];
+ gs_memory_t *mem = pdev->pdf_memory;
+ stream *s;
-/* ---------------- Device open/close ---------------- */
+ pdf_open_obj(pdev, page_id);
+ s = pdev->strm;
+ pprintd2(s, "<</Type/Page/MediaBox [0 0 %d %d]\n",
+ page->MediaBox.x, page->MediaBox.y);
+ pprintld1(s, "/Parent %ld 0 R\n", pdev->Pages->id);
+ pputs(s, "/Resources<</ProcSet[/PDF");
+ if (page->procsets & ImageB)
+ pputs(s, " /ImageB");
+ if (page->procsets & ImageC)
+ pputs(s, " /ImageC");
+ if (page->procsets & ImageI)
+ pputs(s, " /ImageI");
+ if (page->procsets & Text)
+ pputs(s, " /Text");
+ pputs(s, "]\n");
+ {
+ int i;
-/* Close and remove temporary files. */
-private void
-pdf_close_files(gx_device_pdf * pdev)
-{
- gs_free_object(pdev->pdf_memory, pdev->rstrmbuf,
- "pdf_close_files(rstrmbuf)");
- pdev->rstrmbuf = 0;
- gs_free_object(pdev->pdf_memory, pdev->rstrm,
- "pdf_close_files(rstrm)");
- pdev->rstrm = 0;
- if (pdev->rfile != 0) {
- fclose(pdev->rfile);
- pdev->rfile = 0;
- unlink(pdev->rfname);
- }
- if (pdev->tfile != 0) {
- fclose(pdev->tfile);
- pdev->tfile = 0;
- unlink(pdev->tfname);
+ for (i = 0; i < resourceFont; ++i)
+ if (page->resource_ids[i]) {
+ pprints1(s, "/%s ", resource_type_names[i]);
+ pprintld1(s, "%ld 0 R\n", page->resource_ids[i]);
+ }
}
-}
+ if (page->fonts_id)
+ pprintld1(s, "/Font %ld 0 R\n", page->fonts_id);
+ pputs(s, ">>\n");
-/* Open the device. */
-private int
-pdf_open(gx_device * dev)
-{
- gx_device_pdf *pdev = (gx_device_pdf *) dev;
- char fmode[4];
- int code;
+ /* Write out the annotations array if any. */
- pdev->pdf_memory = &gs_memory_default; /* as good as any */
- strcpy(fmode, "w+");
- strcat(fmode, gp_fmode_binary_suffix);
- pdev->tfile =
- gp_open_scratch_file(gp_scratch_file_name_prefix,
- pdev->tfname, fmode);
- if (pdev->tfile == 0)
- return_error(gs_error_invalidfileaccess);
- pdev->rfile =
- gp_open_scratch_file(gp_scratch_file_name_prefix,
- pdev->rfname, fmode);
- if (pdev->rfile == 0) {
- code = gs_note_error(gs_error_invalidfileaccess);
- goto fail;
- }
- pdev->rstrm = s_alloc(pdev->pdf_memory, "pdf_open(rstrm)");
- pdev->rstrmbuf = gs_alloc_bytes(pdev->pdf_memory, sbuf_size,
- "pdf_open(rstrmbuf)");
- if (pdev->rstrm == 0 || pdev->rstrmbuf == 0) {
- code = gs_note_error(gs_error_VMerror);
- goto fail;
- }
- swrite_file(pdev->rstrm, pdev->rfile, pdev->rstrmbuf, sbuf_size);
- code = gdev_vector_open_file((gx_device_vector *) pdev, sbuf_size);
- if (code < 0)
- goto fail;
- gdev_vector_init((gx_device_vector *) pdev);
- /* Set in_page so the vector routines won't try to call */
- /* any vector implementation procedures. */
- pdev->in_page = true;
- pdf_initialize_ids(pdev);
- pdev->outlines_id = 0;
- pdev->next_page = 0;
- memset(pdev->space_char_ids, 0, sizeof(pdev->space_char_ids));
- pdev->page_ids = (void *)
- gs_alloc_byte_array(pdev->pdf_memory, initial_num_page_ids,
- sizeof(*pdev->page_ids), "pdf_open(page_ids)");
- if (pdev->page_ids == 0) {
- code = gs_error_VMerror;
- goto fail;
+ if (page->Annots) {
+ pputs(s, "/Annots");
+ COS_WRITE(page->Annots, pdev);
+ COS_FREE(page->Annots, mem, "pdf_write_page(Annots)");
+ page->Annots = 0;
}
- pdev->num_page_ids = initial_num_page_ids;
- pdev->pages_referenced = 0;
- pdev->catalog_string.data = 0;
- pdev->pages_string.data = 0;
- pdev->outline_levels[0].first.id = 0;
- pdev->outline_levels[0].left = max_int;
- pdev->outline_depth = 0;
- pdev->closed_outline_depth = 0;
- pdev->outlines_open = 0;
- pdev->articles = 0;
- pdev->named_dests = 0;
- pdev->named_objects = 0;
- pdev->open_graphics = 0;
- pdf_reset_page(pdev, true);
+ if (page->contents_id == 0)
+ pputs(s, "/Contents []\n");
+ else
+ pprintld1(s, "/Contents %ld 0 R\n", page->contents_id);
+
+ /* Write any elements stored by pdfmarks. */
+
+ cos_dict_elements_write(page->Page, pdev);
+ pputs(s, ">>\n");
+ pdf_end_obj(pdev);
return 0;
- fail:
- pdf_close_files(pdev);
- return code;
}
/* Wrap up ("output") a page. */
private int
pdf_output_page(gx_device * dev, int num_copies, int flush)
{
- gx_device_pdf *pdev = (gx_device_pdf *) dev;
+ gx_device_pdf *const pdev = (gx_device_pdf *) dev;
int code = pdf_close_page(pdev);
return (code < 0 ? code : gx_finish_output_page(dev, num_copies, flush));
}
-/* Write out the CharProcs for an embedded font. */
-/* We thought that Acrobat 2.x required this to be an indirect object, */
-/* but we were wrong. */
-private int
-pdf_write_char_procs(gx_device_pdf * pdev, const pdf_font * pef,
- gs_int_rect * pbbox, int widths[256])
-{
- stream *s = pdev->strm;
- const pdf_char_proc *pcp;
- int w;
-
- pputs(s, "<<");
- /* Write real characters. */
- for (pcp = pef->char_procs; pcp; pcp = pcp->char_next) {
- pbbox->p.y = min(pbbox->p.y, pcp->y_offset);
- pbbox->q.x = max(pbbox->q.x, pcp->width);
- pbbox->q.y = max(pbbox->q.y, pcp->height + pcp->y_offset);
- widths[pcp->char_code] = pcp->x_width;
- pprintld2(s, "/a%ld\n%ld 0 R", (long)pcp->char_code, pcp->id);
- }
- /* Write space characters. */
- for (w = 0; w < countof(pef->spaces); ++w) {
- byte ch = pef->spaces[w];
-
- if (ch) {
- pprintld2(s, "/a%ld\n%ld 0 R", (long)ch,
- pdev->space_char_ids[w]);
- widths[ch] = w + x_space_min;
- }
- }
- pputs(s, ">>");
- return 0;
-}
-
-/* Write out the Widths for an embedded font similarly. */
-private int
-pdf_write_widths(gx_device_pdf * pdev, const pdf_font * pef, int widths[256])
-{
- stream *s = pdev->strm;
- int i;
-
- pputs(s, "[");
- for (i = 0; i < pef->num_chars; ++i)
- pprintd1(s, (i & 15 ? " %d" : ("\n%d")), widths[i]);
- pputs(s, "]");
- return 0;
-}
-
/* Close the device. */
private int
pdf_close(gx_device * dev)
{
- gx_device_pdf *pdev = (gx_device_pdf *) dev;
+ gx_device_pdf *const pdev = (gx_device_pdf *) dev;
+ gs_memory_t *mem = pdev->pdf_memory;
stream *s;
- FILE *tfile = pdev->tfile;
+ FILE *tfile = pdev->xref.file;
long xref;
- long named_dests_id = 0;
long resource_pos;
+ long Catalog_id = pdev->Catalog->id, Info_id = pdev->Info->id,
+ Pages_id = pdev->Pages->id;
/*
* If this is an EPS file, or if the file has produced no marks
@@ -1181,79 +580,38 @@ pdf_close(gx_device * dev)
pdf_close_page(pdev);
}
}
- /*
- * Write out fonts. For base fonts, write the encoding
- * differences.
- */
+
+ /* Write the page objects. */
{
- int j;
- const pdf_font *pef;
-
- s = pdev->strm;
- for (j = 0; j < num_resource_chains; ++j)
- for (pef = (const pdf_font *)pdev->resources[resourceFont].chains[j];
- pef != 0; pef = pef->next
- ) {
- pdf_open_obj(pdev, pef->id);
- if (font_is_embedded(pef)) {
- gs_int_rect bbox;
- int widths[256];
-
- memset(&bbox, 0, sizeof(bbox));
- memset(widths, 0, sizeof(widths));
- pprints1(s, "<</Type/Font/Name/%s/Subtype/Type3", pef->frname);
- pprintld1(s, "/Encoding %ld 0 R", pdev->embedded_encoding_id);
- pprintd1(s, "/FirstChar 0/LastChar %d/CharProcs",
- pef->num_chars - 1);
- pdf_write_char_procs(pdev, pef, &bbox, widths);
- pprintd4(s, "/FontBBox[%d %d %d %d]/FontMatrix[1 0 0 1 0 0]/Widths",
- bbox.p.x, bbox.p.y, bbox.q.x, bbox.q.y);
- pdf_write_widths(pdev, pef, widths);
- pputs(s, ">>\n");
- } else {
- pprintld1(s, "<</Type/Font/Name/R%ld/Subtype/Type1/BaseFont",
- pef->id);
- pdf_put_name(pdev, pef->fname.chars, pef->fname.size);
- if (pef->differences != 0)
- pprintld1(s, "/Encoding %ld 0 R", pef->diff_id);
- pputs(s, ">>\n");
- if (pef->differences != 0) {
- int prev = 256;
- int i;
-
- pdf_end_obj(pdev);
- pdf_open_obj(pdev, pef->diff_id);
- pputs(s, "<</Type/Encoding/Differences[");
- for (i = 0; i < 256; ++i)
- if (pef->differences[i].data != 0) {
- if (i != prev + 1)
- pprintd1(s, "\n%d", i);
- pdf_put_name(pdev, pef->differences[i].data,
- pef->differences[i].size);
- prev = i;
- }
- pputs(s, "]>>\n");
- }
- }
- pdf_end_obj(pdev);
- }
+ int i;
+
+ for (i = 1; i <= pdev->next_page; ++i)
+ pdf_write_page(pdev, i);
}
- /* Create the root (Catalog). */
+ /* Write the font resources and related resources. */
+
+ pdf_write_font_resources(pdev);
- pdf_open_obj(pdev, pdev->pages_id);
+ /* Create the Pages tree. */
+
+ pdf_open_obj(pdev, Pages_id);
+ s = pdev->strm;
pputs(s, "<< /Type /Pages /Kids [\n");
{
int i;
for (i = 0; i < pdev->next_page; ++i)
- pprintld1(s, "%ld 0 R\n", pdev->page_ids[i]);
+ pprintld1(s, "%ld 0 R\n", pdev->pages[i].Page->id);
}
pprintd1(s, "] /Count %d\n", pdev->next_page);
- pdf_write_saved_string(pdev, &pdev->pages_string);
+ cos_dict_elements_write(pdev->Pages, pdev);
pputs(s, ">>\n");
pdf_end_obj(pdev);
+
+ /* Close outlines and articles. */
+
if (pdev->outlines_id != 0) {
pdfmark_close_outline(pdev); /* depth must be zero! */
pdf_open_obj(pdev, pdev->outlines_id);
@@ -1264,83 +622,85 @@ pdf_close(gx_device * dev)
pdf_end_obj(pdev);
}
if (pdev->articles != 0) {
- pdf_article *part;
+ pdf_article_t *part;
/* Write the remaining information for each article. */
for (part = pdev->articles; part != 0; part = part->next)
pdfmark_write_article(pdev, part);
}
- if (pdev->named_dests != 0) {
- pdf_named_dest *pnd;
-
- named_dests_id = pdf_begin_obj(pdev);
- pputs(s, "<<\n");
- while ((pnd = pdev->named_dests) != 0) {
- pdev->named_dests = pnd->next;
- pdf_put_value(pdev, pnd->key.data, pnd->key.size);
- pprints1(s, " %s\n", pnd->dest);
- gs_free_string(pdev->pdf_memory, pnd->key.data, pnd->key.size,
- "pdf_close(named_dest key)");
- gs_free_object(pdev->pdf_memory, pnd, "pdf_close(named_dest)");
- }
- pputs(s, ">>\n");
- pdf_end_obj(pdev);
- }
- pdf_open_obj(pdev, pdev->root_id);
- pprintld1(s, "<< /Type /Catalog /Pages %ld 0 R\n", pdev->pages_id);
+
+ /* Write named destinations. (We can't free them yet.) */
+
+ if (pdev->Dests)
+ COS_WRITE_OBJECT(pdev->Dests, pdev);
+
+ /* Write the Catalog. */
+
+ pdf_open_obj(pdev, Catalog_id);
+ s = pdev->strm;
+ pputs(s, "<<");
+ pprintld1(s, "/Type /Catalog /Pages %ld 0 R\n", Pages_id);
if (pdev->outlines_id != 0)
pprintld1(s, "/Outlines %ld 0 R\n", pdev->outlines_id);
if (pdev->articles != 0) {
- pdf_article *part;
+ pdf_article_t *part;
pputs(s, "/Threads [ ");
while ((part = pdev->articles) != 0) {
pdev->articles = part->next;
- pprintld1(s, "%ld 0 R\n", part->id);
- gs_free_string(pdev->pdf_memory, part->title.data,
- part->title.size, "pdf_close(article title)");
- gs_free_object(pdev->pdf_memory, part, "pdf_close(article)");
+ pprintld1(s, "%ld 0 R\n", part->contents->id);
+ COS_FREE(part->contents, mem, "pdf_close(article contents)");
+ gs_free_object(mem, part, "pdf_close(article)");
}
pputs(s, "]\n");
}
- if (named_dests_id != 0)
- pprintld1(s, "/Dests %ld 0 R\n", named_dests_id);
- pdf_write_saved_string(pdev, &pdev->catalog_string);
+ if (pdev->Dests)
+ pprintld1(s, "/Dests %ld 0 R\n", pdev->Dests->id);
+ cos_dict_elements_write(pdev->Catalog, pdev);
pputs(s, ">>\n");
pdf_end_obj(pdev);
+ if (pdev->Dests) {
+ COS_FREE(pdev->Dests, mem, "pdf_close(Dests)");
+ pdev->Dests = 0;
+ }
- /* Create the Info directory. */
- /* This is supposedly optional, but some readers may require it. */
+ /* Prevent writing special named objects twice. */
+ pdev->Catalog->id = 0;
+ /*pdev->Info->id = 0;*/ /* Info should get written */
+ pdev->Pages->id = 0;
+ {
+ int i;
- if (pdev->info_id == 0) {
- pdev->info_id = pdf_begin_obj(pdev);
- pputs(s, "<< ");
- pdf_write_default_info(pdev);
- pputs(s, ">>\n");
- pdf_end_obj(pdev);
+ for (i = 0; i < pdev->num_pages; ++i)
+ if (pdev->pages[i].Page)
+ pdev->pages[i].Page->id = 0;
}
- /* Write the definitions of the named objects. */
- pdfmark_write_and_free_named(pdev, &pdev->named_objects);
+ /*
+ * Write the definitions of the named objects.
+ * Note that this includes Form XObjects created by BP/EP, named PS
+ * XObjects, and eventually images named by NI.
+ */
+
+ {
+ const cos_dict_element_t *pcde = pdev->named_objects->elements;
+
+ for (; pcde; pcde = pcde->next)
+ if (pcde->value.contents.object->id)
+ cos_write_object(pcde->value.contents.object, pdev);
+ }
/* Copy the resources into the main file. */
s = pdev->strm;
resource_pos = stell(s);
- sflush(pdev->rstrm);
+ sflush(pdev->asides.strm);
{
- FILE *rfile = pdev->rfile;
+ FILE *rfile = pdev->asides.file;
long res_end = ftell(rfile);
- byte buf[sbuf_size];
fseek(rfile, 0L, SEEK_SET);
- while (res_end > 0) {
- uint count = min(res_end, sbuf_size);
-
- fread(buf, 1, sbuf_size, rfile);
- pwrite(s, buf, count);
- res_end -= count;
- }
+ pdf_copy_data(s, rfile, res_end);
}
/* Write the cross-reference section. */
@@ -1362,8 +722,8 @@ pdf_close(gx_device * dev)
char str[21];
fread(&pos, sizeof(pos), 1, tfile);
- if (pos & rfile_base_position)
- pos += resource_pos - rfile_base_position;
+ if (pos & ASIDES_BASE_POSITION)
+ pos += resource_pos - ASIDES_BASE_POSITION;
sprintf(str, "%010ld 00000 n \n", pos);
pputs(s, str);
}
@@ -1373,26 +733,41 @@ pdf_close(gx_device * dev)
pputs(s, "trailer\n");
pprintld3(s, "<< /Size %ld /Root %ld 0 R /Info %ld 0 R\n",
- pdev->next_id, pdev->root_id, pdev->info_id);
+ pdev->next_id, Catalog_id, Info_id);
pputs(s, ">>\n");
pprintld1(s, "startxref\n%ld\n%%%%EOF\n", xref);
/* Release the resource records. */
{
- pdf_resource *pres;
- pdf_resource *prev;
+ pdf_resource_t *pres;
+ pdf_resource_t *prev;
for (prev = pdev->last_resource; (pres = prev) != 0;) {
prev = pres->prev;
- gs_free_object(pdev->pdf_memory, pres, "pdf_resource");
+ gs_free_object(mem, pres, "pdf_resource_t");
}
pdev->last_resource = 0;
}
- gs_free_object(pdev->pdf_memory, pdev->page_ids, "page_ids");
- pdev->page_ids = 0;
- pdev->num_page_ids = 0;
+ /* Free named objects. */
+
+ {
+ cos_dict_element_t *pcde = pdev->named_objects->elements;
+
+ /*
+ * Delete the objects' IDs so that freeing the dictionary will
+ * free them.
+ */
+ for (; pcde; pcde = pcde->next)
+ pcde->value.contents.object->id = 0;
+ COS_FREE(pdev->named_objects, mem, "pdf_close(named_objects)");
+ pdev->named_objects = 0;
+ }
+
+ gs_free_object(mem, pdev->pages, "pages");
+ pdev->pages = 0;
+ pdev->num_pages = 0;
gdev_vector_close_file((gx_device_vector *) pdev);
pdf_close_files(pdev);
diff --git a/gs/src/gdevpdfd.c b/gs/src/gdevpdfd.c
index 5f55d406d..143a71580 100644
--- a/gs/src/gdevpdfd.c
+++ b/gs/src/gdevpdfd.c
@@ -42,7 +42,7 @@ gdev_pdf_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
/* which shouldn't cause the page to be opened. */
if (color == 0xffffff && !is_in_page(pdev))
return 0;
- code = pdf_open_page(pdev, pdf_in_stream);
+ code = pdf_open_page(pdev, PDF_IN_STREAM);
if (code < 0)
return code;
/* Make sure we aren't being clipped. */
@@ -152,8 +152,8 @@ pdf_put_clip_path(gx_device_pdf * pdev, const gx_clip_path * pcpath)
}
}
pdev->text.font = 0;
- if (pdev->context == pdf_in_text)
- pdev->context = pdf_in_stream;
+ if (pdev->context == PDF_IN_TEXT)
+ pdev->context = PDF_IN_STREAM;
pdf_reset_graphics(pdev);
return 0;
}
@@ -199,10 +199,10 @@ gdev_pdf_fill_path(gx_device * dev, const gs_imager_state * pis, gx_path * ppath
if (gx_dc_pure_color(pdcolor) == 0xffffff && !is_in_page(pdev))
return 0;
have_path = !gx_path_is_void(ppath);
- if (have_path || pdev->context == pdf_in_none ||
+ if (have_path || pdev->context == PDF_IN_NONE ||
pdf_must_put_clip_path(pdev, pcpath)
) {
- code = pdf_open_page(pdev, pdf_in_stream);
+ code = pdf_open_page(pdev, PDF_IN_STREAM);
if (code < 0)
return code;
}
@@ -241,7 +241,7 @@ gdev_pdf_stroke_path(gx_device * dev, const gs_imager_state * pis,
return gx_default_stroke_path(dev, pis, ppath, params, pdcolor,
pcpath);
pdev->vec_procs = &pdf_vector_procs;
- code = pdf_open_page(pdev, pdf_in_stream);
+ code = pdf_open_page(pdev, PDF_IN_STREAM);
if (code < 0)
return code;
/*
diff --git a/gs/src/gdevpdff.c b/gs/src/gdevpdff.c
new file mode 100644
index 000000000..c34a8cbbf
--- /dev/null
+++ b/gs/src/gdevpdff.c
@@ -0,0 +1,1080 @@
+/* Copyright (C) 1999 Aladdin Enterprises. All rights reserved.
+
+ This file is part of Aladdin Ghostscript.
+
+ Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
+ or distributor accepts any responsibility for the consequences of using it,
+ or for whether it serves any particular purpose or works at all, unless he
+ or she says so in writing. Refer to the Aladdin Ghostscript Free Public
+ License (the "License") for full details.
+
+ Every copy of Aladdin Ghostscript must include a copy of the License,
+ normally in a plain ASCII text file named PUBLIC. The License grants you
+ the right to copy, modify and redistribute Aladdin Ghostscript, but only
+ under certain conditions described in the License. Among other things, the
+ License requires that the copyright notice and this notice be preserved on
+ all copies.
+ */
+
+
+/* Font handling for pdfwrite driver. */
+#include "math_.h"
+#include "memory_.h"
+#include "string_.h"
+#include "gx.h"
+#include "gserrors.h"
+#include "gsmalloc.h" /* for patching font memory */
+#include "gsmatrix.h"
+#include "gspath.h"
+#include "gsutil.h" /* for bytes_compare */
+#include "gxfixed.h" /* for gxfcache.h */
+#include "gxfont.h"
+#include "gxfcache.h" /* for orig_fonts list */
+#include "gxpath.h" /* for getting current point */
+#include "gdevpdfx.h"
+#include "scommon.h"
+
+/* GC descriptors */
+private_st_pdf_font_descriptor();
+private_st_pdf_encoding_element();
+private ENUM_PTRS_WITH(pdf_encoding_elt_enum_ptrs, pdf_encoding_element_t *pe) {
+ uint count = size / (uint)sizeof(*pe);
+
+ if (index >= count)
+ return 0;
+ return ENUM_CONST_STRING(&pe[index].str);
+} ENUM_PTRS_END
+private RELOC_PTRS_WITH(pdf_encoding_elt_reloc_ptrs, pdf_encoding_element_t *pe)
+ uint count = size / (uint)sizeof(*pe);
+ uint i;
+
+ for (i = 0; i < count; ++i)
+ RELOC_CONST_STRING_VAR(pe[i].str);
+RELOC_PTRS_END
+
+/* Define the 14 standard built-in fonts. */
+const pdf_standard_font_t pdf_standard_fonts[] = {
+#define m(name, enc) {name, enc},
+ pdf_do_std_fonts(m)
+#undef m
+ {0}
+};
+
+/* Return the index of a standard font name, or -1 if missing. */
+private int
+pdf_find_standard_font(const byte *str, uint size)
+{
+ const pdf_standard_font_t *ppsf;
+
+ for (ppsf = pdf_standard_fonts; ppsf->fname; ++ppsf)
+ if (strlen(ppsf->fname) == size &&
+ !strncmp(ppsf->fname, (const char *)str, size)
+ )
+ return ppsf - pdf_standard_fonts;
+ return -1;
+}
+
+/*
+ * Return the index of a standard font with the same UID as a given font,
+ * or -1 if missing.
+ */
+private int
+find_std_uid(const gx_device_pdf *pdev, const gs_font_base *bfont)
+{
+ int i;
+
+ for (i = 0; i < PDF_NUM_STD_FONTS; ++i)
+ if (uid_equal(&bfont->UID, &pdev->text.std_fonts[i].uid)) {
+ return i;
+ }
+ return -1;
+}
+
+/*
+ * Scan a font directory for standard fonts. Return true if any new ones
+ * were found.
+ */
+private bool
+scan_for_standard_fonts(gx_device_pdf *pdev, const gs_font_dir *dir)
+{
+ bool found = false;
+ const gs_font *orig = dir->orig_fonts;
+
+ for (; orig; orig = orig->next) {
+ const gs_font_base *obfont;
+
+ if (orig->FontType == ft_composite)
+ continue;
+ obfont = (const gs_font_base *)orig;
+ if (uid_is_valid(&obfont->UID)) {
+ /* Is it one of the standard fonts? */
+ int i = pdf_find_standard_font(orig->key_name.chars,
+ orig->key_name.size);
+
+ if (i >= 0 && !uid_equal(&pdev->text.std_fonts[i].uid,
+ &obfont->UID)) {
+ pdev->text.std_fonts[i].uid = obfont->UID;
+ pdev->text.std_fonts[i].orig_matrix = obfont->FontMatrix;
+ found = true;
+ }
+ }
+ }
+ return found;
+}
+
+/*
+ * Find the original (unscaled) standard font corresponding to an
+ * arbitrary font, if any.
+ */
+bool
+pdf_find_orig_font(gx_device_pdf *pdev, gs_font *font, gs_const_string *pfname,
+ gs_matrix *pfmat)
+{
+ bool scan = true;
+ int i;
+
+ if (font->FontType == ft_composite)
+ return false;
+ for (;; font = font->base) {
+ gs_font_base *bfont = (gs_font_base *)font;
+
+ if (uid_is_valid(&bfont->UID) && bfont->UID.id != 0) {
+ /* Look for a standard font with the same UID. */
+ i = find_std_uid(pdev, bfont);
+ if (i >= 0)
+ goto ret;
+ if (scan) {
+ /* Scan for fonts with any of the standard names that */
+ /* have a UID. */
+ bool found = scan_for_standard_fonts(pdev, font->dir);
+
+ scan = false;
+ if (found) {
+ i = find_std_uid(pdev, bfont);
+ if (i >= 0)
+ goto ret;
+ }
+ }
+ }
+ if (font->base == font)
+ return false;
+ }
+ ret:
+ pfname->data = (const byte *)pdf_standard_fonts[i].fname;
+ pfname->size = strlen((const char *)pfname->data);
+ *pfmat = pdev->text.std_fonts[i].orig_matrix;
+ return true;
+}
+
+/*
+ * Determine the embedding status of a font. If the font is in the base
+ * 14, store its index (0..13) in *pindex.
+ */
+private bool
+font_is_symbolic(const gs_font *font)
+{
+ if (font->FontType == ft_composite)
+ return true; /* arbitrary */
+ switch (((const gs_font_base *)font)->nearest_encoding_index) {
+ case ENCODING_INDEX_STANDARD:
+ case ENCODING_INDEX_ISOLATIN1:
+ case ENCODING_INDEX_WINANSI:
+ return false;
+ default:
+ return true;
+ }
+}
+private bool
+embed_list_includes(const gs_param_string_array *psa, const byte *chars,
+ uint size)
+{
+ uint i;
+
+ for (i = 0; i < psa->size; ++i)
+ if (!bytes_compare(psa->data[i].data, psa->data[i].size, chars, size))
+ return true;
+ return false;
+}
+pdf_font_embed_t
+pdf_font_embed_status(gx_device_pdf *pdev, gs_font *font, int *pindex)
+{
+ const byte *chars = font->font_name.chars;
+ uint size = font->font_name.size;
+ int index = pdf_find_standard_font(chars, size);
+
+ /* Check whether the font is in the base 14. */
+ if (index >= 0) {
+ *pindex = index;
+ return FONT_EMBED_BASE14;
+ }
+ /* Check the Embed lists. */
+ if ((pdev->params.EmbedAllFonts || font_is_symbolic(font) ||
+ embed_list_includes(&pdev->params.AlwaysEmbed, chars, size)) &&
+ !embed_list_includes(&pdev->params.NeverEmbed, chars, size))
+ return FONT_EMBED_YES;
+ return FONT_EMBED_NO;
+}
+
+/* Allocate a font resource. */
+int
+pdf_alloc_font(gx_device_pdf *pdev, gs_id rid, pdf_font_t **ppfres,
+ bool with_descriptor)
+{
+ gs_memory_t *mem = pdev->v_memory;
+ pdf_font_descriptor_t *pfd = 0;
+ int code;
+ pdf_font_t *pfres;
+
+ if (with_descriptor) {
+ pfd = gs_alloc_struct(mem, pdf_font_descriptor_t,
+ &st_pdf_font_descriptor,
+ "pdf_alloc_font(descriptor)");
+ if (pfd == 0)
+ return_error(gs_error_VMerror);
+ memset(pfd, 0, sizeof(*pfd));
+ }
+ code = pdf_alloc_resource(pdev, resourceFont, rid,
+ (pdf_resource_t **)ppfres, 0L);
+ if (code < 0) {
+ gs_free_object(mem, pfd, "pdf_alloc_font(descriptor)");
+ return code;
+ }
+ pfres = *ppfres;
+ pfres->rid = rid;
+ memset((byte *)pfres + sizeof(pdf_resource_t), 0,
+ sizeof(*pfres) - sizeof(pdf_resource_t));
+ sprintf(pfres->frname, "R%ld", pfres->object->id);
+ pfres->differences = 0;
+ pfres->descriptor = pfd;
+ pfres->char_procs = 0;
+ pfres->skip = false;
+ return 0;
+}
+
+/* Add an encoding difference to a font. */
+int
+pdf_add_encoding_difference(gx_device_pdf *pdev, pdf_font_t *ppf, int chr,
+ const gs_font_base *bfont, gs_glyph glyph)
+{
+ pdf_encoding_element_t *pdiff = ppf->differences;
+
+ if (pdiff == 0) {
+ ppf->diff_id = pdf_obj_ref(pdev);
+ pdiff = gs_alloc_struct_array(pdev->pdf_memory, 256,
+ pdf_encoding_element_t,
+ &st_pdf_encoding_element,
+ "differences");
+ if (pdiff == 0)
+ return_error(gs_error_VMerror);
+ memset(pdiff, 0, sizeof(pdf_encoding_element_t) * 256);
+ ppf->differences = pdiff;
+ }
+ pdiff[chr].glyph = glyph;
+ pdiff[chr].str.data = (const byte *)
+ bfont->procs.callbacks.glyph_name(glyph, &pdiff[chr].str.size);
+ return 0;
+}
+
+/* Get the width of a given character in a (base) font. */
+int
+pdf_char_width(pdf_font_t *ppf, int ch, gs_font *font, const gs_matrix *pmat,
+ int *pwidth /* may be NULL */)
+{
+ if (ch < 0 || ch > 255)
+ return_error(gs_error_rangecheck);
+ if (!(ppf->widths_known[ch >> 3] & (1 << (ch & 7)))) {
+ pdf_font_descriptor_t *pfd = ppf->descriptor;
+
+ if (pfd == 0)
+ return_error(gs_error_rangecheck);
+ ppf->Widths[ch] = pfd->MissingWidth;
+ if (!(pfd->Flags & FONT_IS_FIXED_WIDTH)) {
+ gs_font_base *bfont = (gs_font_base *)font;
+ gs_glyph glyph = bfont->procs.encode_char(font, (gs_char)ch,
+ GLYPH_SPACE_INDEX);
+
+ if (glyph != gs_no_glyph) {
+ int wmode = font->WMode;
+ gs_matrix smat;
+ gs_glyph_info_t info;
+ int code;
+
+ /* See above re the following. */
+ if (font->FontType == ft_TrueType) {
+ gs_make_scaling(1000.0, 1000.0, &smat);
+ pmat = &smat;
+ }
+ code = font->procs.glyph_info(font, glyph, pmat,
+ GLYPH_INFO_WIDTH0 << wmode,
+ &info);
+
+ if (code < 0)
+ return code;
+ if (info.width[wmode].y != 0)
+ return_error(gs_error_rangecheck);
+ ppf->Widths[ch] = info.width[wmode].x;
+ }
+ }
+ ppf->widths_known[ch >> 3] |= 1 << (ch & 7);
+ }
+ if (pwidth)
+ *pwidth = ppf->Widths[ch];
+ return 0;
+}
+
+/* Compute the FontDescriptor for a font. */
+private int
+font_char_bbox(gs_rect *pbox, gs_font *font, int ch, const gs_matrix *pmat)
+{
+ gs_glyph glyph;
+ gs_glyph_info_t info;
+ int code;
+
+ glyph = font->procs.encode_char(font, (gs_char)ch, GLYPH_SPACE_INDEX);
+ if (glyph == gs_no_glyph)
+ return gs_error_undefined;
+ code = font->procs.glyph_info(font, glyph, pmat, GLYPH_INFO_BBOX, &info);
+ if (code < 0)
+ return code;
+ *pbox = info.bbox;
+ return 0;
+}
+int
+pdf_compute_font_descriptor(gx_device_pdf *pdev, pdf_font_descriptor_t *pfd,
+ gs_font *font, const byte *used /*[32]*/)
+{
+ gs_font_base *bfont = (gs_font_base *)font;
+ gs_glyph glyph, notdef;
+ int index;
+ int wmode = font->WMode;
+ pdf_font_descriptor_t desc;
+ gs_matrix smat;
+ gs_matrix *pmat = NULL;
+ int fixed_width = 0;
+ int code;
+
+ memset(&desc, 0, sizeof(desc));
+ desc.FontBBox.p.x = desc.FontBBox.p.y = max_int;
+ desc.FontBBox.q.x = desc.FontBBox.q.y = min_int;
+ /*
+ * Embedded TrueType fonts use a 1000-unit character space, but the
+ * font itself uses a 1-unit space. Compensate for this here.
+ */
+ if (font->FontType == ft_TrueType) {
+ gs_make_scaling(1000.0, 1000.0, &smat);
+ pmat = &smat;
+ }
+ /*
+ * Scan the entire glyph space to compute Ascent, Descent, FontBBox,
+ * and the fixed width if any.
+ */
+ notdef = gs_no_glyph;
+ for (index = 0;
+ (code = font->procs.enumerate_glyph(font, &index, GLYPH_SPACE_INDEX, &glyph)) >= 0 &&
+ index != 0;
+ ) {
+ gs_glyph_info_t info;
+ gs_const_string gnstr;
+
+ code = font->procs.glyph_info(font, glyph, pmat,
+ (GLYPH_INFO_WIDTH0 << wmode) |
+ GLYPH_INFO_BBOX | GLYPH_INFO_NUM_PIECES,
+ &info);
+ if (code < 0)
+ return code;
+ if (notdef == gs_no_glyph) {
+ gnstr.data = (const byte *)
+ bfont->procs.callbacks.glyph_name(glyph, &gnstr.size);
+ if (gnstr.size == 7 && !memcmp(gnstr.data, ".notdef", 7)) {
+ notdef = glyph;
+ desc.MissingWidth = info.width[wmode].x;
+ }
+ }
+ rect_merge(desc.FontBBox, info.bbox);
+ if (!info.num_pieces)
+ desc.Ascent = max(desc.Ascent, info.bbox.q.y);
+ if (info.width[wmode].y != 0)
+ fixed_width = min_int;
+ else if (fixed_width == 0)
+ fixed_width = info.width[wmode].x;
+ else if (info.width[wmode].x != fixed_width)
+ fixed_width = min_int;
+ }
+ if (code < 0)
+ return code;
+ if (desc.Ascent == 0)
+ desc.Ascent = desc.FontBBox.q.y;
+ desc.Descent = desc.FontBBox.p.y;
+ if (fixed_width > 0) {
+ desc.Flags |= FONT_IS_FIXED_WIDTH;
+ desc.AvgWidth = desc.MaxWidth = desc.MissingWidth = fixed_width;
+ }
+ if (font_is_symbolic(font))
+ desc.Flags |= FONT_IS_SYMBOLIC;
+ else {
+ /*
+ * Look at various specific characters to guess at the remaining
+ * descriptor values (CapHeight, ItalicAngle, StemV, and flags
+ * SERIF, SCRIPT, ITALIC, ALL_CAPS, and SMALL_CAPS). The
+ * algorithms are pretty crude.
+ */
+ /*
+ * Look at the glyphs for the lower-case letters. If they are
+ * all missing, this is an all-cap font; if any is present, check
+ * the relative heights to determine whether this is a small-cap font.
+ */
+ bool small_present = false;
+ int ch;
+ int height = min_int, x_height = min_int, descent = max_int;
+ int cap_height = 0;
+ gs_rect bbox, bbox2;
+
+ desc.Flags |= FONT_IS_ADOBE_ROMAN; /* required if not symbolic */
+ for (ch = 'a'; ch <= 'z'; ++ch) {
+ int y0, y1;
+
+ code = font_char_bbox(&bbox, font, ch, pmat);
+ if (code < 0)
+ continue;
+ small_present = true;
+ y0 = (int)bbox.p.y;
+ y1 = (int)bbox.q.y;
+ switch (ch) {
+ case 'b': case 'd': case 'f': case 'h':
+ case 'k': case 'l': case 't': /* ascender */
+ height = max(height, y1);
+ case 'i': /* anomalous ascent */
+ break;
+ case 'j': /* descender with anomalous ascent */
+ descent = min(descent, y0);
+ break;
+ case 'g': case 'p': case 'q': case 'y': /* descender */
+ descent = min(descent, y0);
+ default: /* no ascender or descender */
+ x_height = max(x_height, y1);
+ }
+ desc.XHeight = (int)x_height;
+ }
+ if (!small_present)
+ desc.Flags |= FONT_IS_ALL_CAPS;
+ else if (descent > desc.Descent / 3 || x_height > height * 0.8)
+ desc.Flags |= FONT_IS_SMALL_CAPS;
+ for (ch = 'A'; ch <= 'Z'; ++ch) {
+ code = font_char_bbox(&bbox, font, ch, pmat);
+ if (code < 0)
+ continue;
+ cap_height = max(cap_height, (int)bbox.q.y);
+ }
+ desc.CapHeight = cap_height;
+ /*
+ * Look at various glyphs to determine ItalicAngle, StemV,
+ * SERIF, SCRIPT, and ITALIC.
+ */
+ if ((code = font_char_bbox(&bbox, font, ':', pmat)) >= 0 &&
+ (code = font_char_bbox(&bbox2, font, '.', pmat)) >= 0
+ ) {
+ /* Calculate the dominant angle. */
+ int angle =
+ (int)(atan2((bbox.q.y - bbox.p.y) - (bbox2.q.y - bbox2.p.y),
+ (bbox.q.x - bbox.p.x) - (bbox2.q.x - bbox2.p.x)) *
+ radians_to_degrees) - 90;
+
+ /* Normalize to [-90..90]. */
+ while (angle > 90)
+ angle -= 180;
+ while (angle < -90)
+ angle += 180;
+ if (angle < -30)
+ angle = -30;
+ else if (angle > 30)
+ angle = 30;
+ /*
+ * For script or embellished fonts, we can get an angle that is
+ * slightly off from zero even for non-italic fonts.
+ * Compensate for this now.
+ */
+ if (angle <= 2 && angle >= -2)
+ angle = 0;
+ desc.ItalicAngle = angle;
+ }
+ if (desc.ItalicAngle)
+ desc.Flags |= FONT_IS_ITALIC;
+ if (code >= 0) {
+ double wdot = bbox2.q.x - bbox2.p.x;
+
+ if ((code = font_char_bbox(&bbox2, font, 'I', pmat)) >= 0) {
+ /* Calculate the serif and stem widths. */
+ double wcolon = bbox.q.x - bbox.p.x;
+ double wI = bbox2.q.x - bbox2.p.x;
+ double serif_width = (wI - wcolon) / 2;
+ double stem_v = wdot;
+
+ desc.StemV = (int)max(stem_v, 0);
+ if (serif_width < 0 || stem_v < 0)
+ desc.Flags |= FONT_IS_SCRIPT;
+ else if (serif_width != 0)
+ desc.Flags |= FONT_IS_SERIF;
+ }
+ }
+ }
+ if (desc.CapHeight == 0)
+ desc.CapHeight = desc.Ascent;
+ if (desc.StemV == 0)
+ desc.StemV = (int)(desc.FontBBox.q.x * 0.15);
+ *pfd = desc;
+ return 0;
+}
+
+/* ---------------- Writing font resources ---------------- */
+
+/*
+ * Determine whether a font is a subset font by examining the name.
+ */
+private bool
+has_subset_prefix(const byte *str, uint size)
+{
+ int i;
+
+ if (size < 7 || str[6] != '+')
+ return false;
+ for (i = 0; i < 6; ++i)
+ if ((uint)(str[i] - 'A') >= 26)
+ return false;
+ return true;
+}
+
+/*
+ * Make the prefix for a subset font from the font's resource ID.
+ */
+private void
+make_subset_prefix(byte *str, ulong id)
+{
+ int i;
+ ulong v;
+
+ for (i = 0, v = id * 987654321; i < 6; ++i, v /= 26)
+ str[i] = 'A' + (v % 26);
+ str[6] = '+';
+}
+
+/* Begin writing FontFile* data. */
+private int
+pdf_begin_fontfile(gx_device_pdf *pdev, long *plength_id)
+{
+ stream *s;
+
+ *plength_id = pdf_obj_ref(pdev);
+ s = pdev->strm;
+ pputs(s, "<<");
+ if (!pdev->binary_ok)
+ pputs(s, "/Filter/ASCII85Decode");
+ pprintld1(s, "/Length %ld 0 R", *plength_id);
+ return 0;
+}
+
+/* Finish writing FontFile* data. */
+private int
+pdf_end_fontfile(gx_device_pdf *pdev, long start, long length_id)
+{
+ stream *s = pdev->strm;
+ long length;
+
+ pputs(s, "\n");
+ length = pdf_stell(pdev) - start;
+ pputs(s, "endstream\n");
+ pdf_end_separate(pdev);
+ pdf_open_separate(pdev, length_id);
+ pprintld1(pdev->strm, "%ld\n", length);
+ pdf_end_separate(pdev);
+ return 0;
+}
+
+/* Write the FontFile data for an embedded Type 1 font. */
+private int
+pdf_embed_font_type1(gx_device_pdf *pdev, pdf_font_descriptor_t *pfd,
+ gs_font_type1 *font, gs_glyph subset_glyphs[256],
+ uint subset_size, const gs_const_string *pfname)
+{
+ stream poss;
+ int lengths[3];
+ int code;
+ long length_id;
+ long start;
+ psdf_binary_writer writer;
+
+ swrite_position_only(&poss);
+ /*
+ * We omit the 512 zeros and the cleartomark, and set Length3 to 0.
+ * Note that the interpreter adds them implicitly (per documentation),
+ * so we must set MARK so that the encrypted portion pushes a mark on
+ * the stack.
+ */
+#define TYPE1_OPTIONS (WRITE_TYPE1_EEXEC | WRITE_TYPE1_EEXEC_MARK)
+ code = psdf_write_type1_font(&poss, font, TYPE1_OPTIONS,
+ subset_glyphs, subset_size, pfname, lengths);
+ if (code < 0)
+ return code;
+ pdf_open_separate(pdev, pfd->FontFile_id);
+ pdf_begin_fontfile(pdev, &length_id);
+ pprintd2(pdev->strm, "/Length1 %d/Length2 %d/Length3 0>>stream\n",
+ lengths[0], lengths[1]);
+ start = pdf_stell(pdev);
+ code = psdf_begin_binary((gx_device_psdf *)pdev, &writer);
+ if (code < 0)
+ return code;
+#ifdef DEBUG
+ {
+ int check_lengths[3];
+
+ psdf_write_type1_font(writer.strm, font, TYPE1_OPTIONS,
+ subset_glyphs, subset_size, pfname,
+ check_lengths);
+ if (writer.strm == pdev->strm &&
+ (check_lengths[0] != lengths[0] ||
+ check_lengths[1] != lengths[1] ||
+ check_lengths[2] != lengths[2])
+ ) {
+ lprintf7("Type 1 font id %ld, lengths mismatch: (%d,%d,%d) != (%d,%d,%d)\n",
+ ((gs_font *)font)->id, lengths[0], lengths[1], lengths[2],
+ check_lengths[0], check_lengths[1], check_lengths[2]);
+ }
+ }
+#else
+ psdf_write_type1_font(writer.strm, font, TYPE1_OPTIONS,
+ subset_glyphs, subset_size, pfname,
+ lengths /*ignored*/);
+#endif
+#undef TYPE1_OPTIONS
+ psdf_end_binary(&writer);
+ pdf_end_fontfile(pdev, start, length_id);
+ return 0;
+}
+
+/* Write the FontFile2 data for an embedded TrueType font. */
+private int
+pdf_embed_font_type42(gx_device_pdf *pdev, pdf_font_descriptor_t *pfd,
+ gs_font_type42 *font, gs_glyph subset_glyphs[256],
+ uint subset_size, const gs_const_string *pfname)
+{
+ stream poss;
+ int length;
+ int code;
+ long length_id;
+ long start;
+ psdf_binary_writer writer;
+
+ swrite_position_only(&poss);
+#define TRUETYPE_OPTIONS (WRITE_TRUETYPE_CMAP | WRITE_TRUETYPE_NAME)
+ code = psdf_write_truetype_font(&poss, font, TRUETYPE_OPTIONS,
+ subset_glyphs, subset_size, pfname);
+ if (code < 0)
+ return code;
+ length = stell(&poss);
+ pdf_open_separate(pdev, pfd->FontFile_id);
+ pdf_begin_fontfile(pdev, &length_id);
+ pprintd1(pdev->strm, "/Length1 %d>>stream\n", length);
+ start = pdf_stell(pdev);
+ code = psdf_begin_binary((gx_device_psdf *)pdev, &writer);
+ if (code < 0)
+ return code;
+ psdf_write_truetype_font(pdev->strm, font, TRUETYPE_OPTIONS,
+ subset_glyphs, subset_size, pfname);
+#undef TRUETYPE_OPTIONS
+ psdf_end_binary(&writer);
+ pdf_end_fontfile(pdev, start, length_id);
+ return 0;
+}
+
+/*
+ * Write out the CharProcs for a synthesized font.
+ * We thought that Acrobat 2.x required this to be an indirect object,
+ * but we were wrong.
+ */
+private int
+pdf_write_char_procs(gx_device_pdf * pdev, const pdf_font_t * pef,
+ gs_int_rect * pbbox, int widths[256])
+{
+ stream *s = pdev->strm;
+ const pdf_char_proc_t *pcp;
+ int w;
+
+ pputs(s, "<<");
+ /* Write real characters. */
+ for (pcp = pef->char_procs; pcp; pcp = pcp->char_next) {
+ pbbox->p.y = min(pbbox->p.y, pcp->y_offset);
+ pbbox->q.x = max(pbbox->q.x, pcp->width);
+ pbbox->q.y = max(pbbox->q.y, pcp->height + pcp->y_offset);
+ widths[pcp->char_code] = pcp->x_width;
+ pprintld2(s, "/a%ld\n%ld 0 R", (long)pcp->char_code,
+ pcp->object->id);
+ }
+ /* Write space characters. */
+ for (w = 0; w < countof(pef->spaces); ++w) {
+ byte ch = pef->spaces[w];
+
+ if (ch) {
+ pprintld2(s, "/a%ld\n%ld 0 R", (long)ch,
+ pdev->space_char_ids[w]);
+ widths[ch] = w + X_SPACE_MIN;
+ }
+ }
+ pputs(s, ">>");
+ return 0;
+}
+
+/* Write out the Widths for an embedded or synthesized font. */
+private int
+pdf_write_widths(gx_device_pdf *pdev, int first, int last,
+ const int widths[256])
+{
+ stream *s = pdev->strm;
+ int i;
+
+ pputs(s, "[");
+ for (i = first; i <= last; ++i)
+ pprintd1(s, (i & 15 ? " %d" : ("\n%d")), widths[i]);
+ pputs(s, "]\n");
+ return 0;
+}
+
+/* Write a FontBBox dictionary element. */
+private int
+pdf_write_font_bbox(gx_device_pdf *pdev, const gs_int_rect *pbox)
+{
+ stream *s = pdev->strm;
+
+ pprintd4(s, "/FontBBox[%d %d %d %d]",
+ pbox->p.x, pbox->p.y, pbox->q.x, pbox->q.y);
+ return 0;
+}
+
+/* Write a synthesized bitmap font resource. */
+private int
+pdf_write_synthesized_type3(gx_device_pdf *pdev, const pdf_font_t *pef)
+{
+ stream *s;
+ gs_int_rect bbox;
+ int widths[256];
+
+ memset(&bbox, 0, sizeof(bbox));
+ memset(widths, 0, sizeof(widths));
+ pdf_open_separate(pdev, pef->object->id);
+ s = pdev->strm;
+ pprints1(s, "<</Type/Font/Name/%s/Subtype/Type3", pef->frname);
+ pprintld1(s, "/Encoding %ld 0 R", pdev->embedded_encoding_id);
+ pprintd1(s, "/FirstChar 0/LastChar %d/CharProcs",
+ pef->num_chars - 1);
+ pdf_write_char_procs(pdev, pef, &bbox, widths);
+ pdf_write_font_bbox(pdev, &bbox);
+ pputs(s, "/FontMatrix[1 0 0 1 0 0]/Widths");
+ pdf_write_widths(pdev, 0, pef->num_chars - 1, widths);
+ pputs(s, ">>\n");
+ pdf_end_separate(pdev);
+ return 0;
+}
+
+/*
+ * Write a Type 1 or TrueType font resource, including any encoding
+ * differences and/or descriptor.
+ */
+private int
+pdf_write_font_resource(gx_device_pdf *pdev, const pdf_font_t *pef,
+ const gs_const_string *pfname)
+{
+ stream *s;
+ const pdf_font_descriptor_t *pfd = pef->descriptor;
+ long widths_id = 0;
+ int first = 0, last = 255;
+ /*
+ * For embedded TrueType fonts, the PDF documentation doesn't specify
+ * how the Encoding interacts with the post and cmap tables. Macduff
+ * Hughes of Adobe says the only reliable way to get the desired output
+ * is not to use Encoding at all, but even this isn't adequate for
+ * non-Unicode-based fonts: right now it appears there is *no* way to
+ * get Acrobat to do the right thing.
+ */
+ bool write_differences =
+ pef->differences != 0 &&
+ (pfd == 0 || pfd->FontFile_id == 0 || pef->FontType != ft_TrueType);
+ const char *FontFile_key;
+
+ pdf_open_separate(pdev, pef->object->id);
+ s = pdev->strm;
+ switch (pef->FontType) {
+ case ft_encrypted:
+ pputs(s, "<</Subtype/Type1/BaseFont");
+ pdf_put_name(pdev, pfname->data, pfname->size);
+ FontFile_key = "/FontFile";
+ break;
+ case ft_TrueType:
+ pputs(s, "<</Subtype/TrueType/BaseFont");
+ /****** WHAT ABOUT STYLE INFO? ******/
+ pdf_put_name(pdev, pfname->data, pfname->size);
+ FontFile_key = "/FontFile2";
+ break;
+ default:
+ return_error(gs_error_rangecheck);
+ }
+ pprintld1(s, "/Type/Font/Name/R%ld", pef->object->id);
+ if (write_differences)
+ pprintld1(s, "/Encoding %ld 0 R", pef->diff_id);
+ if (pfd) {
+ while (first < last && pef->Widths[first] == pfd->MissingWidth)
+ ++first;
+ while (last > first && pef->Widths[last] == pfd->MissingWidth)
+ --last;
+ widths_id = pdf_obj_ref(pdev);
+ pprintld2(s, "/FontDescriptor %ld 0 R/Widths %ld 0 R",
+ pfd->id, widths_id);
+ pprintd2(s, "/FirstChar %d/LastChar %d", first, last);
+ }
+ pputs(s, ">>\n");
+ if (write_differences) {
+ int prev = 256;
+ int i;
+
+ pdf_end_separate(pdev);
+ pdf_open_separate(pdev, pef->diff_id);
+ pputs(s, "<</Type/Encoding/Differences[");
+ for (i = 0; i < 256; ++i)
+ if (pef->differences[i].str.data != 0) {
+ if (i != prev + 1)
+ pprintd1(s, "\n%d", i);
+ pdf_put_name(pdev,
+ pef->differences[i].str.data,
+ pef->differences[i].str.size);
+ prev = i;
+ }
+ pputs(s, "]>>\n");
+ }
+ if (pfd) {
+#define DESC_INT(str, memb)\
+ {str, gs_param_type_int, offset_of(pdf_font_descriptor_t, memb)}
+ static const gs_param_item_t required_items[] = {
+ DESC_INT("Ascent", Ascent),
+ DESC_INT("CapHeight", CapHeight),
+ DESC_INT("Descent", Descent),
+ DESC_INT("ItalicAngle", ItalicAngle),
+ DESC_INT("StemV", StemV),
+ DESC_INT("Flags", Flags),
+ gs_param_item_end
+ };
+ static const gs_param_item_t optional_items[] = {
+ DESC_INT("AvgWidth", AvgWidth),
+ DESC_INT("Leading", Leading),
+ DESC_INT("MaxWidth", MaxWidth),
+ DESC_INT("MissingWidth", MissingWidth),
+ DESC_INT("StemH", StemH),
+ DESC_INT("XHeight", XHeight),
+ gs_param_item_end
+ };
+#undef DESC_INT
+ param_printer_params_t params;
+ static const param_printer_params_t ppp_defaults = {
+ param_printer_params_default_values
+ };
+ printer_param_list_t rlist;
+ gs_param_list *const plist = (gs_param_list *)&rlist;
+ pdf_font_descriptor_t defaults;
+ int code;
+
+ pdf_end_separate(pdev);
+ pdf_open_separate(pdev, widths_id);
+ pdf_write_widths(pdev, first, last, pef->Widths);
+ pdf_end_separate(pdev);
+ pdf_open_separate(pdev, pfd->id);
+ params = ppp_defaults;
+ code = s_init_param_printer(&rlist, &params, pdev->strm);
+ pputs(s, "<</Type/FontDescriptor/FontName");
+ pdf_put_name(pdev, pfname->data, pfname->size);
+ gs_param_write_items(plist, pfd, NULL, required_items);
+ pdf_write_font_bbox(pdev, &pfd->FontBBox);
+ memset(&defaults, 0, sizeof(defaults));
+ gs_param_write_items(plist, pfd, &defaults, optional_items);
+ s_release_param_printer(&rlist);
+ if (pfd->FontFile_id) {
+ pputs(s, FontFile_key);
+ pprintld1(s, " %ld 0 R", pfd->FontFile_id);
+ }
+ pputs(s, ">>\n");
+ }
+ pdf_end_separate(pdev);
+ return 0;
+}
+
+/*
+ * Write the FontFile* data for an embedded font.
+ * Return a rangecheck error if the font can't be embedded.
+ */
+private int
+pdf_write_embedded_font(gx_device_pdf *pdev, pdf_font_descriptor_t *pfd,
+ pdf_font_t *ppf, gs_font *font)
+{
+ byte fnchars[MAX_PDF_FONT_NAME];
+ uint fnsize = font->font_name.size;
+ gs_const_string font_name;
+ bool do_subset = pdev->params.SubsetFonts && pdev->params.MaxSubsetPct > 0;
+ long subset_id = pfd->FontFile_id;
+ gs_glyph subset_glyphs[256];
+ gs_glyph *glyph_subset = 0;
+ uint subset_size = 0;
+
+ /* Determine whether to subset the font. */
+ if (do_subset) {
+ int used, i, total, index;
+ gs_glyph ignore_glyph;
+
+ for (i = 0, used = 0; i < 256/8; ++i)
+ used += byte_count_bits[ppf->chars_used[i]];
+ for (index = 0, total = 0;
+ (font->procs.enumerate_glyph(font, &index, GLYPH_SPACE_INDEX,
+ &ignore_glyph), index != 0);
+ )
+ ++total;
+ /* Test used / total >= MaxSubsetPct / 100 */
+ if (used * 100 >= pdev->params.MaxSubsetPct * total)
+ do_subset = false;
+ else {
+ subset_size = psdf_subset_glyphs(subset_glyphs, font,
+ ppf->chars_used);
+ glyph_subset = subset_glyphs;
+ }
+ }
+
+ /* Generate an appropriate font name. */
+ if (has_subset_prefix(font->font_name.chars, fnsize)) {
+ /*
+ * This font is already a subset. Replace the prefix with a newly
+ * generated one, to ensure no conflicts.
+ */
+ memcpy(fnchars + 7, font->font_name.chars + 7, fnsize - 7);
+ make_subset_prefix(fnchars, subset_id);
+ } else if (do_subset) {
+ memcpy(fnchars + 7, font->font_name.chars, fnsize);
+ make_subset_prefix(fnchars, subset_id);
+ fnsize += 7;
+ } else
+ memcpy(fnchars, font->font_name.chars, fnsize);
+ font_name.data = fnchars;
+ font_name.size = fnsize;
+ pdf_write_font_resource(pdev, ppf, &font_name);
+
+ /* Finally, write the font (or subset). */
+ switch (font->FontType) {
+ case ft_encrypted:
+ return pdf_embed_font_type1(pdev, pfd, (gs_font_type1 *)font,
+ glyph_subset, subset_size, &font_name);
+ case ft_TrueType:
+ return pdf_embed_font_type42(pdev, pfd, (gs_font_type42 *)font,
+ glyph_subset, subset_size, &font_name);
+ default:
+ return_error(gs_error_rangecheck);
+ }
+}
+
+/* Register a font for eventual writing (embedded or not). */
+private GS_NOTIFY_PROC(pdf_font_notify_proc);
+typedef struct pdf_font_notify_s {
+ gx_device_pdf *pdev;
+ pdf_font_t *pdfont;
+} pdf_font_notify_t;
+gs_private_st_ptrs2(st_pdf_font_notify, pdf_font_notify_t, "pdf_font_notify_t",
+ pdf_font_notify_enum_ptrs, pdf_font_notify_reloc_ptrs,
+ pdev, pdfont);
+int
+pdf_register_font(gx_device_pdf *pdev, gs_font *font, pdf_font_t *ppf)
+{
+ /*
+ * Note that we do this allocation in font->memory, not pdev->pdf_memory.
+ */
+ gs_memory_t *fn_memory = gs_memory_stable(font->memory);
+ pdf_font_notify_t *pfn =
+ gs_alloc_struct(fn_memory, pdf_font_notify_t,
+ &st_pdf_font_notify, "pdf_register_font");
+
+ if (pfn == 0)
+ return_error(gs_error_VMerror);
+ pfn->pdev = pdev;
+ pfn->pdfont = ppf;
+ ppf->font = font;
+ return gs_font_notify_register(font, pdf_font_notify_proc, pfn);
+}
+private int
+pdf_font_notify_proc(void *vpfn /*proc_data*/, void *event_data)
+{
+ pdf_font_notify_t *const pfn = vpfn;
+ gx_device_pdf *const pdev = pfn->pdev;
+ pdf_font_t *const ppf = pfn->pdfont;
+ gs_font *const font = ppf->font;
+ gs_memory_t *fn_memory = gs_memory_stable(font->memory);
+ gs_memory_t *save_memory = font->memory;
+ int code;
+ pdf_font_descriptor_t fdesc;
+
+ if (event_data)
+ return 0; /* unknown event */
+ /*
+ * HACK: temporarily patch the font's memory to one that we know is
+ * available even during GC or restore. (Eventually we need to fix
+ * this by prohibiting implementations of font_info and glyph_info
+ * from doing any allocations.)
+ */
+ font->memory = &gs_memory_default;
+ code = pdf_compute_font_descriptor(pdev, &fdesc, font, NULL);
+ gs_font_notify_unregister(font, pdf_font_notify_proc, vpfn);
+ gs_free_object(fn_memory, vpfn, "pdf_font_notify_proc");
+ ppf->font = 0;
+ /*
+ * Mark the font as written so that pdf_write_font_resources won't try
+ * to write it a second time, but don't attempt to free it:
+ * pdf_close_page will need to write it in the list of the page's used
+ * resources. pdf_close will take care of freeing the structure.
+ */
+ ppf->skip = true;
+ if (code >= 0) {
+ if (ppf->descriptor && ppf->descriptor->FontFile_id) {
+ /* This is an embedded font. */
+ gs_matrix save_mat;
+
+ save_mat = font->FontMatrix;
+ font->FontMatrix = ppf->orig_matrix;
+ fdesc.FontFile_id = ppf->descriptor->FontFile_id;
+ code = pdf_write_embedded_font(pdev, &fdesc, ppf, font);
+ font->FontMatrix = save_mat;
+ } else {
+ gs_const_string font_name;
+
+ font_name.data = font->font_name.chars;
+ font_name.size = font->font_name.size;
+ pdf_write_font_resource(pdev, ppf, &font_name);
+ }
+ }
+ font->memory = save_memory;
+ return code;
+}
+
+/* Write out the font resources when wrapping up the output. */
+int
+pdf_write_font_resources(gx_device_pdf *pdev)
+{
+ int j;
+ pdf_font_t *pef;
+ pdf_font_t *next;
+
+ for (j = 0; j < NUM_RESOURCE_CHAINS; ++j)
+ for (pef = (pdf_font_t *)pdev->resources[resourceFont].chains[j];
+ pef != 0; pef = next
+ ) {
+ next = pef->next; /* notify_proc unlinks the font */
+ if (PDF_FONT_IS_SYNTHESIZED(pef))
+ pdf_write_synthesized_type3(pdev, pef);
+ else if (!pef->skip) {
+ pdf_font_notify_t fn;
+
+ fn.pdev = pdev;
+ fn.pdfont = pef;
+ pdf_font_notify_proc(&fn, NULL);
+ }
+ }
+ return 0;
+}
diff --git a/gs/src/gdevpdfi.c b/gs/src/gdevpdfi.c
index e54beb7a3..2703abe6c 100644
--- a/gs/src/gdevpdfi.c
+++ b/gs/src/gdevpdfi.c
@@ -366,7 +366,6 @@ pdf_write_image_filters(gx_device_pdf * pdev, const psdf_binary_writer * pbw,
ppp.prefix = "<<";
ppp.suffix = ">>";
code = psdf_alloc_param_printer(&printer, &ppp, &s_parms,
- 0 /*no strings */ ,
pdev->pdf_memory);
if (code < 0)
return code;
@@ -477,7 +476,7 @@ typedef struct pdf_image_writer_s {
psdf_binary_writer binary;
const pdf_image_names *pin;
const char *begin_data;
- pdf_resource *pres; /* XObject resource iff not in-line */
+ pdf_resource_t *pres; /* XObject resource iff not in-line */
long length_id; /* id of length object (forward reference) */
long start_pos; /* starting file position of data */
} pdf_image_writer;
@@ -494,7 +493,7 @@ pdf_begin_write_image(gx_device_pdf * pdev, pdf_image_writer * piw, bool in_line
piw->pin = &image_names_short;
piw->begin_data = (pdev->binary_ok ? "ID " : "ID\n");
} else {
- int code = pdf_begin_resource(pdev, resourceImageXObject, gs_no_id,
+ int code = pdf_begin_resource(pdev, resourceXObject, gs_no_id,
&piw->pres);
stream *s = pdev->strm;
@@ -551,16 +550,16 @@ pdf_end_write_image(gx_device_pdf * pdev, pdf_image_writer * piw)
/* Put out a reference to an image resource. */
private int
-pdf_do_image(gx_device_pdf * pdev, const pdf_resource * pres,
+pdf_do_image(gx_device_pdf * pdev, const pdf_resource_t * pres,
const gs_matrix * pimat)
{
- int code = pdf_open_contents(pdev, pdf_in_stream);
+ int code = pdf_open_contents(pdev, PDF_IN_STREAM);
if (code < 0)
return code;
if (pimat)
pdf_put_image_matrix(pdev, pimat);
- pprintld1(pdev->strm, "/R%ld Do\nQ\n", pres->id);
+ pprintld1(pdev->strm, "/R%ld Do\nQ\n", pres->object->id);
return 0;
}
@@ -581,13 +580,13 @@ pdf_copy_mono(gx_device_pdf *pdev,
gs_image_t image;
int yi;
pdf_image_writer writer;
- pdf_stream_position ipos;
- pdf_resource *pres = 0;
+ pdf_stream_position_t ipos;
+ pdf_resource_t *pres = 0;
byte invert = 0;
/* Update clipping. */
if (pdf_must_put_clip_path(pdev, pcpath)) {
- code = pdf_open_page(pdev, pdf_in_stream);
+ code = pdf_open_page(pdev, PDF_IN_STREAM);
if (code < 0)
return code;
pdf_put_clip_path(pdev, pcpath);
@@ -601,7 +600,7 @@ pdf_copy_mono(gx_device_pdf *pdev,
pdf_set_color(pdev, one, &pdev->fill_color, "rg");
pres = pdf_find_resource_by_gs_id(pdev, resourceCharProc, id);
if (pres == 0) { /* Define the character in an embedded font. */
- pdf_char_proc *pcp;
+ pdf_char_proc_t *pcp;
int y_offset;
int max_y_offset =
(pdev->open_font == 0 ? 0 :
@@ -633,7 +632,7 @@ pdf_copy_mono(gx_device_pdf *pdev,
if (code < 0)
return code;
pcp->rid = id;
- pres = (pdf_resource *) pcp;
+ pres = (pdf_resource_t *) pcp;
goto wr;
}
pdf_make_bitmap_matrix(&image.ImageMatrix, x, y, w, h);
@@ -674,7 +673,7 @@ pdf_copy_mono(gx_device_pdf *pdev,
if (in_line)
pdf_put_image_matrix(pdev, &image.ImageMatrix);
- code = pdf_open_page(pdev, pdf_in_stream);
+ code = pdf_open_page(pdev, PDF_IN_STREAM);
if (code < 0)
return code;
code = pdf_begin_write_image(pdev, &writer, in_line);
@@ -747,7 +746,7 @@ pdf_copy_mono(gx_device_pdf *pdev,
imat.xy /= h;
imat.yx /= w;
imat.yy /= h;
- return pdf_do_char_image(pdev, (const pdf_char_proc *)pres, &imat);
+ return pdf_do_char_image(pdev, (const pdf_char_proc_t *)pres, &imat);
}
}
int
@@ -835,7 +834,7 @@ gdev_pdf_copy_color(gx_device * dev, const byte * base, int sourcex,
if (w <= 0 || h <= 0)
return 0;
- code = pdf_open_page(pdev, pdf_in_stream);
+ code = pdf_open_page(pdev, PDF_IN_STREAM);
if (code < 0)
return code;
/* Make sure we aren't being clipped. */
@@ -882,10 +881,10 @@ gdev_pdf_strip_tile_rectangle(gx_device * dev, const gx_strip_bitmap * tiles,
{
gx_device_pdf *const pdev = (gx_device_pdf *) dev;
int tw = tiles->rep_width, th = tiles->rep_height;
- pdf_resource *pres;
+ pdf_resource_t *pres;
if (tiles->id == gx_no_bitmap_id || tiles->shift != 0 ||
- w < tw || h < th ||
+ (w < tw && h < th) ||
/* We only handle full colored patterns right now. */
color0 != gx_no_color_index || color1 != gx_no_color_index ||
/* Pattern fills are only available starting in PDF 1.2. */
@@ -941,7 +940,7 @@ gdev_pdf_strip_tile_rectangle(gx_device * dev, const gx_strip_bitmap * tiles,
}
/* Fill the rectangle with the Pattern. */
{
- int code = pdf_open_page(pdev, pdf_in_stream);
+ int code = pdf_open_page(pdev, PDF_IN_STREAM);
double xscale = pdev->HWResolution[0] / 72.0,
yscale = pdev->HWResolution[1] / 72.0;
stream *s;
@@ -954,7 +953,8 @@ gdev_pdf_strip_tile_rectangle(gx_device * dev, const gx_strip_bitmap * tiles,
* leave the CTM alone here: we have to reset it to the default.
*/
pprintg2(s, "q %g 0 0 %g 0 0 cm", xscale, yscale);
- pprintld2(s, "/R%ld cs/R%ld scn ", pdev->cs_Pattern->id, pres->id);
+ pprintld2(s, "/R%ld cs/R%ld scn ", pdev->cs_Pattern->object->id,
+ pres->object->id);
pprintg4(s, "%g %g %g %g re f Q\n",
x / xscale, y / yscale, w / xscale, h / xscale);
}
@@ -1060,7 +1060,7 @@ gdev_pdf_begin_image(gx_device * dev,
return gx_default_begin_image(dev, pis, pim, format, prect,
pdcolor, pcpath, mem, pinfo);
}
- code = pdf_open_page(pdev, pdf_in_stream);
+ code = pdf_open_page(pdev, PDF_IN_STREAM);
if (code < 0)
return code;
if (prect)
diff --git a/gs/src/gdevpdfm.c b/gs/src/gdevpdfm.c
index 5d481b9e8..f6532b293 100644
--- a/gs/src/gdevpdfm.c
+++ b/gs/src/gdevpdfm.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996, 1997, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1996, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -28,7 +28,7 @@
/* GC descriptors */
private_st_pdf_article();
-private_st_pdf_named_dest();
+private_st_pdf_graphics_save();
/*
* The pdfmark pseudo-parameter indicates the occurrence of a pdfmark
@@ -38,39 +38,21 @@ private_st_pdf_named_dest();
*/
/*
- * Define the pdfmark types we know about.
+ * Define an entry in a table of pdfmark-processing procedures.
+ * (The actual table is at the end of this file, to avoid the need for
+ * forward declarations for the procedures.)
*/
-private pdfmark_proc(pdfmark_ANN);
-private pdfmark_proc(pdfmark_LNK);
-private pdfmark_proc(pdfmark_OUT);
-private pdfmark_proc(pdfmark_ARTICLE);
-private pdfmark_proc(pdfmark_DEST);
-private pdfmark_proc(pdfmark_PS);
-private pdfmark_proc(pdfmark_PAGES);
-private pdfmark_proc(pdfmark_PAGE);
-private pdfmark_proc(pdfmark_DOCINFO);
-private pdfmark_proc(pdfmark_DOCVIEW);
-private const pdfmark_name mark_names[] =
-{
- {"ANN", pdfmark_ANN, pdfmark_nameable},
- {"LNK", pdfmark_LNK, pdfmark_nameable},
- {"OUT", pdfmark_OUT, 0},
- {"ARTICLE", pdfmark_ARTICLE, 0},
- {"DEST", pdfmark_DEST, pdfmark_nameable},
- {"PS", pdfmark_PS, pdfmark_nameable},
- {"PAGES", pdfmark_PAGES, 0},
- {"PAGE", pdfmark_PAGE, 0},
- {"DOCINFO", pdfmark_DOCINFO, 0},
- {"DOCVIEW", pdfmark_DOCVIEW, 0},
- {0, 0}
-};
-private const pdfmark_name *const mark_name_tables[2] =
-{
- mark_names,
- pdfmark_names_named
-};
-
-/* ---------------- Public entry points ---------------- */
+#define PDFMARK_NAMEABLE 1 /* allows _objdef */
+#define PDFMARK_ODD_OK 2 /* OK if odd # of parameters */
+#define PDFMARK_KEEP_NAME 4 /* don't substitute reference for name */
+ /* in 1st argument */
+typedef struct pdfmark_name_s {
+ const char *mname;
+ pdfmark_proc((*proc));
+ byte options;
+} pdfmark_name;
+
+/* ---------------- Public utilities ---------------- */
/* Compare a C string and a gs_param_string. */
bool
@@ -97,98 +79,7 @@ pdfmark_scan_int(const gs_param_string * pstr, int *pvalue)
#undef max_int_str
}
-/* Process a pdfmark. */
-int
-pdfmark_process(gx_device_pdf * pdev, const gs_param_string_array * pma)
-{
- const gs_param_string *data = pma->data;
- uint size = pma->size;
- const gs_param_string *pts = &data[size - 1];
- const gs_param_string *objname = 0;
- gs_matrix ctm;
- int n;
- int code = 0;
-
- if (size < 2 ||
- sscanf((const char *)pts[-1].data, "[%g %g %g %g %g %g]",
- &ctm.xx, &ctm.xy, &ctm.yx, &ctm.yy, &ctm.tx, &ctm.ty) != 6
- )
- return_error(gs_error_rangecheck);
- /*
- * Our coordinate system is scaled so that user space is always
- * default user space. Adjust the CTM to match this.
- */
- {
- double xscale = 72.0 / pdev->HWResolution[0], yscale = 72.0 / pdev->HWResolution[1];
-
- ctm.xx *= xscale, ctm.xy *= yscale;
- ctm.yx *= xscale, ctm.yy *= yscale;
- ctm.tx *= xscale, ctm.ty *= yscale;
- }
- size -= 2; /* remove CTM & pdfmark name */
- for (n = 0; n < countof(mark_name_tables); ++n) {
- const pdfmark_name *pmn;
-
- for (pmn = mark_name_tables[n]; pmn->mname != 0; ++pmn)
- if (pdf_key_eq(pts, pmn->mname)) {
- gs_memory_t *mem = pdev->pdf_memory;
- int odd_ok = (pmn->options & pdfmark_odd_ok) != 0;
- gs_param_string *pairs;
- int j;
-
- if (size & !odd_ok)
- return_error(gs_error_rangecheck);
- if (pmn->options & pdfmark_nameable) {
- /* Look for an object name. */
- for (j = 0; j < size; j += 2) {
- if (pdf_key_eq(&data[j], "_objdef")) {
- objname = &data[j + 1];
- if (!pdfmark_objname_is_valid(objname->data,
- objname->size)
- )
- return_error(gs_error_rangecheck);
- /* Save the pairs without the name. */
- size -= 2;
- pairs = (gs_param_string *)
- gs_alloc_byte_array(mem, size,
- sizeof(gs_param_string),
- "pdfmark_process(pairs)");
- if (!pairs)
- return_error(gs_error_VMerror);
- memcpy(pairs, data, j * sizeof(*data));
- memcpy(pairs + j, data + j + 2,
- (size - j) * sizeof(*data));
- goto copied;
- }
- }
- }
- /* Save all the pairs. */
- pairs = (gs_param_string *)
- gs_alloc_byte_array(mem, size,
- sizeof(gs_param_string),
- "pdfmark_process(pairs)");
- if (!pairs)
- return_error(gs_error_VMerror);
- memcpy(pairs, data, size * sizeof(*data));
-copied: /* Substitute object references for names. */
- for (j = (pmn->options & pdfmark_keep_name ? 1 : 1 - odd_ok);
- j < size; j += 2 - odd_ok
- ) {
- code = pdfmark_replace_names(pdev, &pairs[j], &pairs[j]);
- if (code < 0) {
- gs_free_object(mem, pairs, "pdfmark_process(pairs)");
- goto out;
- }
- }
- code = (*pmn->proc) (pdev, pairs, size, &ctm, objname);
- gs_free_object(mem, pairs, "pdfmark_process(pairs)");
- goto out;
- }
- }
- out:return code;
-}
-
-/* ---------------- Utilities ---------------- */
+/* ---------------- Private utilities ---------------- */
/* Find a key in a dictionary. */
private bool
@@ -227,16 +118,17 @@ pdfmark_page_number(gx_device_pdf * pdev, const gs_param_string * pnstr)
}
/* Construct a destination string specified by /Page and/or /View. */
-/* Return 0 if none (but still fill in a default), 1 if present, */
-/* <0 if error. */
+/* Return 0 if none (but still fill in a default), 1 or 2 if present */
+/* (1 if only one of /Page or /View, 2 if both), <0 if error. */
private int
-pdfmark_make_dest(char dstr[max_dest_string], gx_device_pdf * pdev,
+pdfmark_make_dest(char dstr[MAX_DEST_STRING], gx_device_pdf * pdev,
+ const char *Page_key, const char *View_key,
const gs_param_string * pairs, uint count)
{
gs_param_string page_string, view_string;
- bool present =
- pdfmark_find_key("Page", pairs, count, &page_string) |
- pdfmark_find_key("View", pairs, count, &view_string);
+ int present =
+ pdfmark_find_key(Page_key, pairs, count, &page_string) +
+ pdfmark_find_key(View_key, pairs, count, &view_string);
int page = pdfmark_page_number(pdev, &page_string);
gs_param_string action;
int len;
@@ -245,14 +137,14 @@ pdfmark_make_dest(char dstr[max_dest_string], gx_device_pdf * pdev,
param_string_from_string(view_string, "[/XYZ 0 0 1]");
if (page == 0)
strcpy(dstr, "[null ");
- else if (pdfmark_find_key("Action", pairs, count, &action) &&
+ else if (pdfmark_find_key("/Action", pairs, count, &action) &&
pdf_key_eq(&action, "/GoToR")
)
sprintf(dstr, "[%d ", page - 1);
else
sprintf(dstr, "[%ld 0 R ", pdf_page_id(pdev, page));
len = strlen(dstr);
- if (len + view_string.size > max_dest_string)
+ if (len + view_string.size > MAX_DEST_STRING)
return_error(gs_error_limitcheck);
if (view_string.data[0] != '[' ||
view_string.data[view_string.size - 1] != ']'
@@ -263,98 +155,41 @@ pdfmark_make_dest(char dstr[max_dest_string], gx_device_pdf * pdev,
return present;
}
-/* Write pairs for a dictionary. */
-private void
-pdfmark_write_c_pair(const gx_device_pdf * pdev, const char *key,
- const gs_param_string * pvalue)
+/*
+ * If a named destination is specified by a string, convert it to a name,
+ * update *dstr, and return 1; otherwise return 0.
+ */
+private int
+pdfmark_coerce_dest(gs_param_string *dstr, char dest[MAX_DEST_STRING])
{
- stream *s = pdev->strm;
-
- pputc(s, '/');
- pputs(s, key);
- switch (pvalue->data[0]) {
- default:
- pputc(s, ' ');
- case '/':
- case '(':
- case '[':
- case '<':
- break;
- }
- pdf_put_value(pdev, pvalue->data, pvalue->size);
- pputc(s, '\n');
+ const byte *data = dstr->data;
+ uint size = dstr->size;
+
+ if (size == 0 || data[0] != '(')
+ return 0;
+ /****** HANDLE ESCAPES ******/
+ memcpy(dest, data, size - 1);
+ dest[0] = '/';
+ dest[size - 1] = 0;
+ dstr->data = (byte *)dest;
+ dstr->size = size - 1;
+ return 1;
}
-private void
-pdfmark_write_pair(const gx_device_pdf * pdev, const gs_param_string * pair)
-{
- stream *s = pdev->strm;
- pdf_put_name(pdev, pair->data, pair->size);
- pputc(s, ' ');
- pdf_put_value(pdev, pair[1].data, pair[1].size);
- pputc(s, '\n');
-}
-private void
-pdfmark_write_pairs_except(const gx_device_pdf * pdev,
- const gs_param_string * pairs, uint count, const char *const *skip_keys)
+/* Put pairs in a dictionary. */
+private int
+pdfmark_put_c_pair(gx_device_pdf * pdev, cos_dict_t *pcd,
+ const char *key, const gs_param_string * pvalue)
{
- uint i;
- static const char *const no_skip_keys[] =
- {0};
-
- if (skip_keys == 0)
- skip_keys = no_skip_keys;
- for (i = 0; i < count; i += 2) {
- const char *const *pkey;
-
- for (pkey = skip_keys; *pkey != 0; ++pkey)
- if (pdf_key_eq(&pairs[i], *pkey))
- break;
- if (!*pkey)
- pdfmark_write_pair(pdev, &pairs[i]);
- }
+ return cos_dict_put_string(pcd, pdev, (const byte *)key, strlen(key),
+ pvalue->data, pvalue->size);
}
-#define pdfmark_write_pairs(pdev, pairs, count)\
- pdfmark_write_pairs_except(pdev, pairs, count, NULL)
-
-/* Append data to a saved string. */
-int
-pdfmark_save(gx_device_pdf * pdev, gs_string * pstr,
- int (*proc) (P2(const gx_device_pdf *, void *)), void *pdata,
- client_name_t cname)
+private int
+pdfmark_put_pair(gx_device_pdf * pdev, cos_dict_t *pcd,
+ const gs_param_string * pair)
{
- gs_memory_t *mem = pdev->pdf_memory;
- stream *s;
- int code = psdf_alloc_position_stream(&s, mem);
- stream *save = pdev->strm;
-
- if (code < 0)
- return code;
- pdev->strm = s;
- code = (*proc) (pdev, pdata);
- if (code >= 0) {
- uint pos = stell(s);
- uint size = pstr->size;
- byte *str;
-
- if (pstr->data == 0)
- size = 0,
- str = gs_alloc_string(mem, pos, cname);
- else
- str = gs_resize_string(mem, pstr->data, size, size + pos, cname);
- if (str == 0)
- code = gs_note_error(gs_error_VMerror);
- else {
- pstr->data = str;
- swrite_string(s, str + size, pos);
- code = (*proc) (pdev, pdata);
- if (code >= 0)
- pstr->size = size + pos;
- }
- }
- pdev->strm = save;
- gs_free_object(mem, s, "pdfmark_save");
- return code;
+ return cos_dict_put_string(pcd, pdev, pair->data, pair->size,
+ pair[1].data, pair[1].size);
}
/* Scan a Rect value. */
@@ -365,11 +200,11 @@ pdfmark_scan_rect(gs_rect * prect, const gs_param_string * str,
uint size = str->size;
double v[4];
-#define max_rect_string_size 100
- char chars[max_rect_string_size + 3];
+#define MAX_RECT_STRING 100
+ char chars[MAX_RECT_STRING + 3];
int end_check;
- if (str->size > max_rect_string_size)
+ if (str->size > MAX_RECT_STRING)
return_error(gs_error_limitcheck);
memcpy(chars, str->data, size);
strcpy(chars + size, " 0");
@@ -382,19 +217,29 @@ pdfmark_scan_rect(gs_rect * prect, const gs_param_string * str,
return 0;
}
-/* Write a Rect value. */
+/* Make a Rect value. */
private void
-pdfmark_write_rect(stream * s, const char *key, const gs_rect * prect)
+pdfmark_make_rect(char str[MAX_RECT_STRING], const gs_rect * prect)
{
- pprints1(s, "/%s", key);
- pprintg4(s, "[%g %g %g %g]\n",
+ /*
+ * We have to use a stream and pprintf, rather than sprintf,
+ * because printf formats can't express the PDF restriction son
+ * the form of the output.
+ */
+ stream s;
+
+ swrite_string(&s, (byte *)str, MAX_RECT_STRING - 1);
+ pprintg4(&s, "[%g %g %g %g]",
prect->p.x, prect->p.y, prect->q.x, prect->q.y);
+ str[stell(&s)] = 0;
}
+/* ---------------- Miscellaneous pdfmarks ---------------- */
+
/*
- * Write the dictionary for an annotation or outline. For some unfathomable
- * reason, PDF requires the following key substitutions relative to
- * pdfmarks:
+ * Create the dictionary for an annotation or outline. For some
+ * unfathomable reason, PDF requires the following key substitutions
+ * relative to pdfmarks:
* In annotation and link dictionaries:
* /Action => /A, /Color => /C, /Title => /T
* In outline directionaries:
@@ -408,32 +253,39 @@ pdfmark_write_rect(stream * s, const char *key, const gs_rect * prect)
* /A << /S /GoToR /F xxx /D yyy' >>
* /Action /Article /Dest yyy =>
* /A << /S /Thread /D yyy' >>
+ * /Action /GoTo => drop the Action key
* Also, \n in Contents strings must be replaced with \r.
+ *
+ * We always treat /A and /F as equivalent to /Action and /File
+ * respectively. The pdfmark and PDF documentation is so confused on the
+ * issue of when the long and short names should be used that we only give
+ * this a 50-50 chance of being right.
*/
typedef struct ao_params_s {
gx_device_pdf *pdev; /* for pdfmark_make_dest */
const char *subtype; /* default Subtype in top-level dictionary */
- pdf_resource *pres; /* resource for saving source page */
+ pdf_resource_t *pres; /* resource for saving source page */
} ao_params_t;
private int
-pdfmark_write_ao_pairs(const gx_device_pdf * pdev,
- const gs_param_string * pairs, uint count,
- const gs_matrix * pctm, ao_params_t * params, bool for_outline)
+pdfmark_put_ao_pairs(gx_device_pdf * pdev, cos_dict_t *pcd,
+ const gs_param_string * pairs, uint count,
+ const gs_matrix * pctm, ao_params_t * params,
+ bool for_outline)
{
- stream *s = pdev->strm;
-
const gs_param_string *Action = 0;
const gs_param_string *File = 0;
gs_param_string Dest;
gs_param_string Subtype;
+ gs_memory_t *mem = pdev->pdf_memory;
uint i;
int code;
- char dest[max_dest_string];
+ char dest[MAX_DEST_STRING];
Dest.data = 0;
if (!for_outline) {
- code = pdfmark_make_dest(dest, params->pdev, pairs, count);
+ code = pdfmark_make_dest(dest, params->pdev, "/Page", "/View",
+ pairs, count);
if (code < 0)
return code;
else if (code == 0)
@@ -449,123 +301,158 @@ pdfmark_write_ao_pairs(const gx_device_pdf * pdev,
const gs_param_string *pair = &pairs[i];
long src_pg;
- if (params->pres != 0 && pdf_key_eq(pair, "SrcPg") &&
+ if (params->pres != 0 && pdf_key_eq(pair, "/SrcPg") &&
sscanf((const char *)pair[1].data, "%ld", &src_pg) == 1
)
params->pres->rid = src_pg - 1;
- else if (!for_outline && pdf_key_eq(pair, "Color"))
- pdfmark_write_c_pair(pdev, "C", pair + 1);
- else if (!for_outline && pdf_key_eq(pair, "Title"))
- pdfmark_write_c_pair(pdev, "T", pair + 1);
- else if (pdf_key_eq(pair, "Action"))
+ else if (!for_outline && pdf_key_eq(pair, "/Color"))
+ pdfmark_put_c_pair(pdev, pcd, "/C", pair + 1);
+ else if (!for_outline && pdf_key_eq(pair, "/Title"))
+ pdfmark_put_c_pair(pdev, pcd, "/T", pair + 1);
+ else if (pdf_key_eq(pair, "/Action") || pdf_key_eq(pair, "/A"))
Action = pair;
- else if (pdf_key_eq(pair, "File"))
+ else if (pdf_key_eq(pair, "/File") || pdf_key_eq(pair, "/F"))
File = pair;
- else if (pdf_key_eq(pair, "Dest"))
+ else if (pdf_key_eq(pair, "/Dest")) {
Dest = pair[1];
- else if (pdf_key_eq(pair, "Page") || pdf_key_eq(pair, "View")) {
+ pdfmark_coerce_dest(&Dest, dest);
+ }
+ else if (pdf_key_eq(pair, "/Page") || pdf_key_eq(pair, "/View")) {
/* Make a destination even if this is for an outline. */
if (Dest.data == 0) {
- code = pdfmark_make_dest(dest, params->pdev, pairs, count);
+ code = pdfmark_make_dest(dest, params->pdev, "/Page", "/View",
+ pairs, count);
if (code < 0)
return code;
param_string_from_string(Dest, dest);
}
- } else if (pdf_key_eq(pair, "Subtype"))
+ } else if (pdf_key_eq(pair, "/Subtype"))
Subtype = pair[1];
/*
* We also have to replace all occurrences of \n in Contents
* strings with \r. Unfortunately, they probably have already
* been converted to \012....
*/
- else if (pdf_key_eq(pair, "Contents")) {
- const byte *astr = pair[1].data;
- const uint asize = pair[1].size;
- uint i;
-
- pputs(s, "/Contents ");
- for (i = 0; i < asize; ++i)
- if (asize - i >= 2 && !memcmp(astr + i, "\\n", 2) &&
- (i == 0 || astr[i - 1] != '\\')
+ else if (pdf_key_eq(pair, "/Contents")) {
+ byte *cstr;
+ uint csize = pair[1].size;
+ cos_value_t *pcv;
+ uint i, j;
+
+ /*
+ * Copy the string into value storage, then update it in place.
+ */
+ pdfmark_put_pair(pdev, pcd, pair);
+ /* Break const so we can update the (copied) string. */
+ pcv = (cos_value_t *)
+ cos_dict_find(pcd, (const byte *)"/Contents", 9);
+ cstr = pcv->contents.chars.data;
+ /* Loop invariant: j <= i < csize. */
+ for (i = j = 0; i < csize;)
+ if (csize - i >= 2 && !memcmp(cstr + i, "\\n", 2) &&
+ (i == 0 || cstr[i - 1] != '\\')
) {
- pputs(s, "\\r");
- ++i;
- } else if (asize - i >= 4 && !memcmp(astr + i, "\\012", 4) &&
- (i == 0 || astr[i - 1] != '\\')
+ cstr[j] = '\\', cstr[j + 1] = 'r';
+ i += 2, j += 2;
+ } else if (csize - i >= 4 && !memcmp(cstr + i, "\\012", 4) &&
+ (i == 0 || cstr[i - 1] != '\\')
) {
- pputs(s, "\\r");
- i += 3;
+ cstr[j] = '\\', cstr[j + 1] = 'r';
+ i += 4, j += 2;
} else
- pputc(s, astr[i]);
- pputc(s, '\n');
- } else if (pdf_key_eq(pair, "Rect")) {
+ cstr[j++] = cstr[i++];
+ if (j != i)
+ pcv->contents.chars.data =
+ gs_resize_string(pdev->pdf_memory, cstr, csize, j,
+ "pdfmark_put_ao_pairs");
+ } else if (pdf_key_eq(pair, "/Rect")) {
gs_rect rect;
+ char rstr[MAX_RECT_STRING];
int code = pdfmark_scan_rect(&rect, pair + 1, pctm);
if (code < 0)
return code;
- pdfmark_write_rect(s, "Rect", &rect);
- } else if (for_outline && pdf_key_eq(pair, "Count"))
+ pdfmark_make_rect(rstr, &rect);
+ cos_dict_put_c_strings(pcd, pdev, "/Rect", rstr);
+ } else if (for_outline && pdf_key_eq(pair, "/Count"))
DO_NOTHING;
else
- pdfmark_write_pair(pdev, pair);
+ pdfmark_put_pair(pdev, pcd, pair);
}
- if (!for_outline && pdf_key_eq(&Subtype, "Link")) {
+ if (!for_outline && pdf_key_eq(&Subtype, "/Link")) {
if (Action)
Dest.data = 0;
}
+
/* Now handle the deferred keys. */
if (Action) {
const byte *astr = Action[1].data;
const uint asize = Action[1].size;
- pputs(s, "/A ");
if ((File != 0 || Dest.data != 0) &&
(pdf_key_eq(Action + 1, "/Launch") ||
(pdf_key_eq(Action + 1, "/GoToR") && File) ||
pdf_key_eq(Action + 1, "/Article"))
) {
- pputs(s, "<<");
+ cos_dict_t *adict = cos_dict_alloc(mem, "action dict");
+ cos_value_t avalue;
+
+ if (adict == 0)
+ return_error(gs_error_VMerror);
if (!for_outline) {
/* We aren't sure whether this is really needed.... */
- pputs(s, "/Type/Action");
+ cos_dict_put_c_strings(adict, pdev, "/Type", "/Action");
}
if (pdf_key_eq(Action + 1, "/Article"))
- pputs(s, "/S/Thread");
+ cos_dict_put_c_strings(adict, pdev, "/S", "/Thread");
else
- pdfmark_write_c_pair(pdev, "S", Action + 1);
+ pdfmark_put_c_pair(pdev, adict, "/S", Action + 1);
if (Dest.data) {
- pdfmark_write_c_pair(pdev, "D", &Dest);
+ pdfmark_put_c_pair(pdev, adict, "/D", &Dest);
Dest.data = 0; /* so we don't write it again */
}
if (File) {
- pdfmark_write_c_pair(pdev, "F", File + 1);
+ pdfmark_put_c_pair(pdev, adict, "/F", File + 1);
File = 0; /* so we don't write it again */
}
- pputs(s, ">>");
- } else {
+ cos_dict_put(pcd, pdev, (const byte *)"/A", 2,
+ COS_OBJECT_VALUE(&avalue, adict));
+ } else if (asize >= 4 && !memcmp(astr, "<<", 2)) {
/* Replace occurrences of /Dest, /File, /Subtype. */
- uint i;
-
-#define key_is(key, len)\
- (asize - i > len && !memcmp(astr + i, key, len) &&\
- scan_char_decoder[astr[i + len]] > ctype_name)
-#define replace_key(old_len, new_key)\
- BEGIN pputs(s, new_key); i += old_len - 1; END
- for (i = 0; i < asize; ++i) {
- if (key_is("/Dest", 4))
- replace_key(4, "/D");
- else if (key_is("/File", 4))
- replace_key(4, "/F");
- else if (key_is("/Subtype", 8))
- replace_key(8, "/S");
- else
- pputc(s, astr[i]);
+ const byte *scan = astr + 2;
+ const byte *end = astr + asize;
+ gs_param_string key, value;
+ cos_dict_t *adict = cos_dict_alloc(mem, "action dict");
+ cos_value_t avalue;
+ int code;
+
+ if (adict == 0)
+ return_error(gs_error_VMerror);
+ while ((code = pdf_scan_token(&scan, end, &key.data)) > 0) {
+ key.size = scan - key.data;
+ if (key.data[0] != '/' ||
+ (code = pdf_scan_token_composite(&scan, end, &value.data)) != 1)
+ break;
+ value.size = scan - value.data;
+ if (pdf_key_eq(&key, "/Dest") || pdf_key_eq(&key, "/D")) {
+ param_string_from_string(key, "/D");
+ if (value.data[0] == '(') {
+ /****** HANDLE ESCAPES ******/
+ pdfmark_coerce_dest(&value, dest);
+ }
+ } else if (pdf_key_eq(&key, "/File"))
+ param_string_from_string(key, "/F");
+ else if (pdf_key_eq(&key, "/Subtype"))
+ param_string_from_string(key, "/S");
+ cos_dict_put_string(adict, pdev, key.data, key.size,
+ value.data, value.size);
}
- }
-#undef key_is
-#undef replace_key
- pputc(s, '\n');
+ if (code <= 0 || !pdf_key_eq(&key, ">>"))
+ return_error(gs_error_rangecheck);
+ cos_dict_put(pcd, pdev, (const byte *)"/A", 2,
+ COS_OBJECT_VALUE(&avalue, adict));
+ } else if (pdf_key_eq(Action + 1, "/GoTo"))
+ pdfmark_put_pair(pdev, pcd, Action);
}
/*
* If we have /Dest or /File without the right kind of action,
@@ -573,36 +460,54 @@ pdfmark_write_ao_pairs(const gx_device_pdf * pdev,
* but I'm not sure what else to do.
*/
if (Dest.data)
- pdfmark_write_c_pair(pdev, "Dest", &Dest);
+ pdfmark_put_c_pair(pdev, pcd, "/Dest", &Dest);
if (File)
- pdfmark_write_pair(pdev, File);
+ pdfmark_put_pair(pdev, pcd, File);
if (Subtype.data)
- pdfmark_write_c_pair(pdev, "Subtype", &Subtype);
+ pdfmark_put_c_pair(pdev, pcd, "/Subtype", &Subtype);
return 0;
}
/* Copy an annotation dictionary. */
private int
pdfmark_annot(gx_device_pdf * pdev, gs_param_string * pairs, uint count,
- const gs_matrix * pctm, const char *subtype)
+ const gs_matrix * pctm, const gs_param_string *objname,
+ const char *subtype)
{
ao_params_t params;
- int code = pdf_begin_aside(pdev, &pdev->annots, NULL, &params.pres);
- stream *s = pdev->strm;
+ cos_dict_t *pcd;
+ int page_index = pdev->next_page;
+ cos_array_t *annots;
+ cos_value_t value;
+ int code;
- if (code < 0)
- return code;
+ if (pdf_page_id(pdev, page_index + 1) <= 0)
+ return_error(gs_error_rangecheck);
+ annots = pdev->pages[page_index].Annots;
+ if (annots == 0) {
+ annots = cos_array_alloc(pdev->pdf_memory, "pdfmark_annot");
+ if (annots == 0)
+ return_error(gs_error_VMerror);
+ pdev->pages[page_index].Annots = annots;
+ }
params.pdev = pdev;
params.subtype = subtype;
- params.pres->rid = pdev->next_page;
- pputs(s, "<</Type/Annot\n");
- code = pdfmark_write_ao_pairs(pdev, pairs, count, pctm, &params,
- false);
+ code = pdf_make_named_dict(pdev, objname, &pcd, true);
if (code < 0)
return code;
- pputs(s, ">>\n");
- pdf_end_aside(pdev);
- return 0;
+ code = cos_dict_put_c_strings(pcd, pdev, "/Type", "/Annot");
+ if (code < 0)
+ return code;
+ code = pdfmark_put_ao_pairs(pdev, pcd, pairs, count, pctm, &params, false);
+ if (code < 0)
+ return code;
+ if (!objname) {
+ /* Write the annotation now. */
+ COS_WRITE_OBJECT(pcd, pdev);
+ COS_RELEASE(pcd, pdev->pdf_memory, "pdfmark_annot");
+ }
+ return cos_array_add(annots, pdev,
+ cos_object_value(&value, COS_OBJECT(pcd)));
}
/* ANN pdfmark */
@@ -610,7 +515,7 @@ private int
pdfmark_ANN(gx_device_pdf * pdev, gs_param_string * pairs, uint count,
const gs_matrix * pctm, const gs_param_string * objname)
{
- return pdfmark_annot(pdev, pairs, count, pctm, "/Text");
+ return pdfmark_annot(pdev, pairs, count, pctm, objname, "/Text");
}
/* LNK pdfmark (obsolescent) */
@@ -618,49 +523,12 @@ private int
pdfmark_LNK(gx_device_pdf * pdev, gs_param_string * pairs, uint count,
const gs_matrix * pctm, const gs_param_string * objname)
{
- return pdfmark_annot(pdev, pairs, count, pctm, "/Link");
+ return pdfmark_annot(pdev, pairs, count, pctm, objname, "/Link");
}
-/* Save pairs in a string. */
-typedef struct pairs_params_s {
- const gs_param_string *pairs;
- uint count;
- const char *const *skip_keys;
- const gs_param_string *add_pairs;
- uint add_count;
-} pairs_params_t;
+/* Write and release one node of the outline tree. */
private int
-pairs_write(const gx_device_pdf * pdev, void *pdata)
-{
- const pairs_params_t *ppp = (const pairs_params_t *)pdata;
-
- pdfmark_write_pairs_except(pdev, ppp->pairs, ppp->count,
- ppp->skip_keys);
- pdfmark_write_pairs(pdev, ppp->add_pairs, ppp->add_count);
- return 0;
-}
-private int
-pdfmark_save_edited_pairs(gx_device_pdf * pdev,
- const gs_param_string * pairs, uint count, const char *const *skip_keys,
- const gs_param_string * add_pairs, uint add_count, gs_string * pstr)
-{
- pairs_params_t params;
-
- params.pairs = pairs;
- params.count = count;
- params.skip_keys = skip_keys;
- params.add_pairs = add_pairs;
- params.add_count = add_count;
-
- return pdfmark_save(pdev, pstr, pairs_write, &params,
- "pdfmark_save_edited_pairs");
-}
-#define pdfmark_save_pairs(pdev, pairs, count, pstr)\
- pdfmark_save_edited_pairs(pdev, pairs, count, NULL, NULL, 0, pstr)
-
-/* Write out one node of the outline tree. */
-private int
-pdfmark_write_outline(gx_device_pdf * pdev, pdf_outline_node * pnode,
+pdfmark_write_outline(gx_device_pdf * pdev, pdf_outline_node_t * pnode,
long next_id)
{
stream *s;
@@ -668,7 +536,7 @@ pdfmark_write_outline(gx_device_pdf * pdev, pdf_outline_node * pnode,
pdf_open_separate(pdev, pnode->id);
s = pdev->strm;
pputs(s, "<< ");
- pdf_write_saved_string(pdev, &pnode->action_string);
+ cos_dict_elements_write(pnode->action, pdev);
if (pnode->count)
pprintd1(s, "/Count %d ", pnode->count);
pprintld1(s, "/Parent %ld 0 R\n", pnode->parent_id);
@@ -681,14 +549,16 @@ pdfmark_write_outline(gx_device_pdf * pdev, pdf_outline_node * pnode,
pnode->first_id, pnode->last_id);
pputs(s, ">>\n");
pdf_end_separate(pdev);
+ COS_FREE(pnode->action, pdev->pdf_memory, "pdfmark_write_outline");
+ pnode->action = 0;
return 0;
}
/* Adjust the parent's count when writing an outline node. */
private void
-pdfmark_adjust_parent_count(pdf_outline_level * plevel)
+pdfmark_adjust_parent_count(pdf_outline_level_t * plevel)
{
- pdf_outline_level *parent = plevel - 1;
+ pdf_outline_level_t *parent = plevel - 1;
int count = plevel->last.count;
if (count > 0) {
@@ -704,7 +574,7 @@ int
pdfmark_close_outline(gx_device_pdf * pdev)
{
int depth = pdev->outline_depth;
- pdf_outline_level *plevel = &pdev->outline_levels[depth];
+ pdf_outline_level_t *plevel = &pdev->outline_levels[depth];
int code;
code = pdfmark_write_outline(pdev, &plevel->last, 0);
@@ -722,49 +592,34 @@ pdfmark_close_outline(gx_device_pdf * pdev)
}
/* OUT pdfmark */
-typedef struct out_pairs_params_s {
- const gs_param_string *pairs;
- uint count;
- const gs_matrix *pctm;
- ao_params_t ao;
-} out_pairs_params_t;
-private int
-pdfmark_OUT_write(const gx_device_pdf * pdev, void *pdata)
-{
- out_pairs_params_t *popp = (out_pairs_params_t *) pdata;
-
- return pdfmark_write_ao_pairs(pdev, popp->pairs, popp->count,
- popp->pctm, &popp->ao, true);
-}
private int
pdfmark_OUT(gx_device_pdf * pdev, gs_param_string * pairs, uint count,
const gs_matrix * pctm, const gs_param_string * no_objname)
{
int depth = pdev->outline_depth;
- pdf_outline_level *plevel = &pdev->outline_levels[depth];
+ pdf_outline_level_t *plevel = &pdev->outline_levels[depth];
int sub_count = 0;
uint i;
- pdf_outline_node node;
- out_pairs_params_t params;
+ pdf_outline_node_t node;
+ ao_params_t ao;
int code;
for (i = 0; i < count; i += 2) {
const gs_param_string *pair = &pairs[i];
- if (pdf_key_eq(pair, "Count"))
+ if (pdf_key_eq(pair, "/Count"))
pdfmark_scan_int(pair + 1, &sub_count);
}
- if (sub_count != 0 && depth == max_outline_depth - 1)
+ if (sub_count != 0 && depth == MAX_OUTLINE_DEPTH - 1)
return_error(gs_error_limitcheck);
- node.action_string.data = 0;
- params.pctm = pctm;
- params.pairs = pairs;
- params.count = count;
- params.ao.pdev = pdev;
- params.ao.subtype = 0;
- params.ao.pres = 0;
- code = pdfmark_save(pdev, &node.action_string, pdfmark_OUT_write,
- &params, "pdfmark_OUT");
+ node.action = cos_dict_alloc(pdev->pdf_memory, "pdfmark_OUT");
+ if (node.action == 0)
+ return_error(gs_error_VMerror);
+ ao.pdev = pdev;
+ ao.subtype = 0;
+ ao.pres = 0;
+ code = pdfmark_put_ao_pairs(pdev, node.action, pairs, count, pctm, &ao,
+ true);
if (code < 0)
return code;
if (pdev->outlines_id == 0)
@@ -781,6 +636,7 @@ pdfmark_OUT(gx_device_pdf * pdev, gs_param_string * pairs, uint count,
plevel[-1].last.first_id = node.id;
node.prev_id = 0;
plevel->first = node;
+ plevel->first.action = 0; /* never used */
} else { /* Write out the previous node. */
if (depth > 0)
pdfmark_adjust_parent_count(plevel);
@@ -796,6 +652,7 @@ pdfmark_OUT(gx_device_pdf * pdev, gs_param_string * pairs, uint count,
++plevel;
plevel->left = (sub_count > 0 ? sub_count : -sub_count);
plevel->first.id = 0;
+ plevel->first.action = plevel->last.action = 0; /* for GC */
if (sub_count < 0)
pdev->closed_outline_depth++;
} else {
@@ -809,9 +666,10 @@ pdfmark_OUT(gx_device_pdf * pdev, gs_param_string * pairs, uint count,
/* Write an article bead. */
private int
-pdfmark_write_bead(gx_device_pdf * pdev, const pdf_bead * pbead)
+pdfmark_write_bead(gx_device_pdf * pdev, const pdf_bead_t * pbead)
{
stream *s;
+ char rstr[MAX_RECT_STRING];
pdf_open_separate(pdev, pbead->id);
s = pdev->strm;
@@ -819,16 +677,16 @@ pdfmark_write_bead(gx_device_pdf * pdev, const pdf_bead * pbead)
pbead->article_id, pbead->prev_id, pbead->next_id);
if (pbead->page_id != 0)
pprintld1(s, "/P %ld 0 R", pbead->page_id);
- pdfmark_write_rect(s, "R", &pbead->rect);
- pputs(s, ">>\n");
+ pdfmark_make_rect(rstr, &pbead->rect);
+ pprints1(s, "/R%s>>\n", rstr);
return pdf_end_separate(pdev);
}
-/* Finish writing an article. */
+/* Finish writing an article, and release its data. */
int
-pdfmark_write_article(gx_device_pdf * pdev, const pdf_article * part)
+pdfmark_write_article(gx_device_pdf * pdev, const pdf_article_t * part)
{
- pdf_article art;
+ pdf_article_t art;
stream *s;
art = *part;
@@ -842,14 +700,10 @@ pdfmark_write_article(gx_device_pdf * pdev, const pdf_article * part)
pdfmark_write_bead(pdev, &art.last);
}
pdfmark_write_bead(pdev, &art.first);
- pdf_open_separate(pdev, art.id);
+ pdf_open_separate(pdev, art.contents->id);
s = pdev->strm;
- pprintld1(s, "<</F %ld 0 R/I<</Title ", art.first.id);
- pdf_put_value(pdev, art.title.data, art.title.size);
- if (art.info.data != 0) {
- pputs(s, "\n");
- pdf_put_value(pdev, art.info.data, art.info.size);
- }
+ pprintld1(s, "<</F %ld 0 R/I<<", art.first.id);
+ cos_dict_elements_write(art.contents, pdev);
pputs(s, ">> >>\n");
return pdf_end_separate(pdev);
}
@@ -859,44 +713,52 @@ private int
pdfmark_ARTICLE(gx_device_pdf * pdev, gs_param_string * pairs, uint count,
const gs_matrix * pctm, const gs_param_string * no_objname)
{
+ gs_memory_t *mem = pdev->pdf_memory;
gs_param_string title;
gs_param_string rectstr;
gs_rect rect;
long bead_id;
- pdf_article *part;
+ pdf_article_t *part;
int code;
- if (!pdfmark_find_key("Title", pairs, count, &title) ||
- !pdfmark_find_key("Rect", pairs, count, &rectstr)
+ if (!pdfmark_find_key("/Title", pairs, count, &title) ||
+ !pdfmark_find_key("/Rect", pairs, count, &rectstr)
)
return_error(gs_error_rangecheck);
if ((code = pdfmark_scan_rect(&rect, &rectstr, pctm)) < 0)
return code;
+ bead_id = pdf_obj_ref(pdev);
/* Find the article with this title, or create one. */
- bead_id = pdf_obj_ref(pdev);
+#if 0 /****** FIX THIS ******/
for (part = pdev->articles; part != 0; part = part->next)
if (!bytes_compare(part->title.data, part->title.size,
title.data, title.size))
break;
+#else /****** FIX THIS ******/
+ part = 0;
+#endif /****** FIX THIS ******/
if (part == 0) { /* Create the article. */
- byte *str;
+ cos_dict_t *contents =
+ cos_dict_alloc(mem, "pdfmark_ARTICLE(contents)");
- part = gs_alloc_struct(pdev->pdf_memory, pdf_article,
- &st_pdf_article, "pdfmark_ARTICLE");
- str = gs_alloc_string(pdev->pdf_memory, title.size,
- "article title");
- if (part == 0 || str == 0)
+ if (contents == 0)
return_error(gs_error_VMerror);
+ part = gs_alloc_struct(mem, pdf_article_t, &st_pdf_article,
+ "pdfmark_ARTICLE(article)");
+ if (part == 0 || contents == 0) {
+ gs_free_object(mem, part, "pdfmark_ARTICLE(article)");
+ if (contents)
+ COS_FREE(contents, mem, "pdfmark_ARTICLE(contents)");
+ return_error(gs_error_VMerror);
+ }
+ contents->id = pdf_obj_ref(pdev);
part->next = pdev->articles;
pdev->articles = part;
- memcpy(str, title.data, title.size);
- part->title.data = str;
- part->title.size = title.size;
- part->id = pdf_obj_ref(pdev);
+ cos_dict_put_string(contents, pdev, (const byte *)"/Title", 6,
+ title.data, title.size);
part->first.id = part->last.id = 0;
- part->info.data = 0;
- part->info.size = 0;
+ part->contents = contents;
}
/*
* Add the bead to the article. This is similar to what we do for
@@ -912,22 +774,22 @@ pdfmark_ARTICLE(gx_device_pdf * pdev, gs_param_string * pairs, uint count,
}
part->last.prev_id = part->last.id;
part->last.id = bead_id;
- part->last.article_id = part->id;
+ part->last.article_id = part->contents->id;
part->last.next_id = 0;
part->last.rect = rect;
{
gs_param_string page_string;
int page = 0;
- static const char *const skip_article[] =
- {
- "Title", "Rect", "Page", 0
- };
+ uint i;
- if (pdfmark_find_key("Page", pairs, count, &page_string))
+ if (pdfmark_find_key("/Page", pairs, count, &page_string))
page = pdfmark_page_number(pdev, &page_string);
part->last.page_id = pdf_page_id(pdev, page);
- pdfmark_save_edited_pairs(pdev, pairs, count, skip_article,
- NULL, 0, &part->info);
+ for (i = 0; i < count; i += 2) {
+ if (pdf_key_eq(&pairs[i], "/Rect") || pdf_key_eq(&pairs[i], "/Page"))
+ continue;
+ pdfmark_put_pair(pdev, part->contents, &pairs[i]);
+ }
}
if (part->first.id == 0) { /* This is the first bead of the article. */
part->first = part->last;
@@ -941,116 +803,183 @@ private int
pdfmark_DEST(gx_device_pdf * pdev, gs_param_string * pairs, uint count,
const gs_matrix * pctm, const gs_param_string * objname)
{
- char dest[max_dest_string];
+ int present;
+ char dest[MAX_DEST_STRING];
gs_param_string key;
- pdf_named_dest *pnd;
- byte *str;
+ cos_value_t value;
- if (!pdfmark_find_key("Dest", pairs, count, &key) ||
- !pdfmark_make_dest(dest, pdev, pairs, count) < 0
+ if (!pdfmark_find_key("/Dest", pairs, count, &key) ||
+ (present =
+ pdfmark_make_dest(dest, pdev, "/Page", "/View", pairs, count)) < 0
)
return_error(gs_error_rangecheck);
- pnd = gs_alloc_struct(pdev->pdf_memory, pdf_named_dest,
- &st_pdf_named_dest, "pdfmark_DEST");
- str = gs_alloc_string(pdev->pdf_memory, key.size,
- "named_dest key");
- if (pnd == 0 || str == 0)
- return_error(gs_error_VMerror);
- pnd->next = pdev->named_dests;
- memcpy(str, key.data, key.size);
- pnd->key.data = str;
- pnd->key.size = key.size;
- strcpy(pnd->dest, dest);
- pdev->named_dests = pnd;
- return 0;
+ cos_c_string_value(&value, dest);
+ if (!pdev->Dests) {
+ pdev->Dests = cos_dict_alloc(pdev->pdf_memory, "pdfmark_DEST(Dests)");
+ if (pdev->Dests == 0)
+ return_error(gs_error_VMerror);
+ pdev->Dests->id = pdf_obj_ref(pdev);
+ }
+ if (objname || count > (present + 1) * 2) {
+ /*
+ * Create the destination as a dictionary with a D key, since
+ * it has (or, if named, may have) additional key/value pairs.
+ */
+ cos_dict_t *ddict;
+ int i, code;
+
+ code = pdf_make_named_dict(pdev, objname, &ddict, false);
+ if (code < 0)
+ return code;
+ code = cos_dict_put_c_strings(ddict, pdev, "/D", dest);
+ for (i = 0; code >= 0 && i < count; i += 2)
+ if (!pdf_key_eq(&pairs[i], "/Dest") &&
+ !pdf_key_eq(&pairs[i], "/Page") &&
+ !pdf_key_eq(&pairs[i], "/View")
+ )
+ code = pdfmark_put_pair(pdev, ddict, &pairs[i]);
+ if (code < 0)
+ return code;
+ COS_OBJECT_VALUE(&value, ddict);
+ }
+ return cos_dict_put(pdev->Dests, pdev, key.data, key.size, &value);
}
-/* Write the contents of pass-through code. */
-/* We are inside the stream dictionary, in a 'separate' object. */
-private int
-pdfmark_write_ps(gx_device_pdf * pdev, const gs_param_string * psource)
+/* Check that pass-through PostScript code is a string. */
+private bool
+ps_source_ok(const gs_param_string * psource)
{
- stream *s = pdev->strm;
- long length_id = pdf_obj_ref(pdev);
- long start_pos, length;
-
- pprintld1(s, " /Length %ld 0 R >> stream\n", length_id);
- start_pos = pdf_stell(pdev);
- if (psource->size < 2 || psource->data[0] != '(' ||
- psource->data[psource->size - 1] != ')'
+ if (psource->size >= 2 && psource->data[0] == '(' &&
+ psource->data[psource->size - 1] == ')'
)
- lprintf1("bad PS passthrough: %s\n", psource->data);
+ return true;
else {
-/****** SHOULD REMOVE ESCAPES ******/
- pwrite(s, psource->data + 1, psource->size - 2);
+ lprintf1("bad PS passthrough: %s\n", psource->data);
+ return false;
}
- pputs(s, "\n");
- length = pdf_stell(pdev) - start_pos;
- pputs(s, "endstream\n");
- pdf_end_separate(pdev);
- pdf_open_separate(pdev, length_id);
- pprintld1(s, "%ld\n", length);
- pdf_end_separate(pdev);
- return 0;
+}
+
+/* Write the contents of pass-through PostScript code. */
+/* Return the size written on the file. */
+private uint
+pdfmark_write_ps(stream *s, const gs_param_string * psource)
+{
+ /****** REMOVE ESCAPES WITH PSSDecode, SEE gdevpdfr p. 2 ******/
+ uint size = psource->size - 2;
+
+ pwrite(s, psource->data + 1, size);
+ pputc(s, '\n');
+ return size + 1;
}
/* PS pdfmark */
+#define MAX_PS_INLINE 100
private int
pdfmark_PS(gx_device_pdf * pdev, gs_param_string * pairs, uint count,
const gs_matrix * pctm, const gs_param_string * objname)
{
- stream *s;
gs_param_string source;
gs_param_string level1;
- if (!pdfmark_find_key("DataSource", pairs, count, &source))
+ if (!pdfmark_find_key("/DataSource", pairs, count, &source) ||
+ !ps_source_ok(&source) ||
+ (pdfmark_find_key("/Level1", pairs, count, &level1) &&
+ !ps_source_ok(&level1))
+ )
return_error(gs_error_rangecheck);
- pdfmark_find_key("Level1", pairs, count, &level1);
- if (level1.data == 0 && source.size <= 100 &&
+ if (level1.data == 0 && source.size <= MAX_PS_INLINE &&
pdev->CompatibilityLevel >= 1.2 && objname == 0
- ) { /* Insert the PostScript code in-line */
- int code = pdf_open_contents(pdev, pdf_in_stream);
+ ) {
+ /* Insert the PostScript code in-line */
+ int code = pdf_open_contents(pdev, PDF_IN_STREAM);
+ stream *s;
if (code < 0)
return code;
s = pdev->strm;
pwrite(s, source.data, source.size);
pputs(s, " PS\n");
- } else { /* Put the PostScript code in a resource. */
- pdf_resource *pres;
-
-/****** SHOULD BE A NamedObject ******/
- int code = pdf_begin_resource(pdev, resourceImageXObject, gs_no_id,
- &pres);
-
+ } else {
+ /* Put the PostScript code in a resource. */
+ pdf_resource_t *pres;
+ cos_stream_t *pcs;
+ uint size;
+ int code;
+
+ code = pdf_make_named(pdev, objname, cos_type_stream,
+ (cos_object_t **)&pcs, true);
+ if (code < 0)
+ return code;
+ code = pdf_alloc_resource(pdev, resourceXObject, gs_no_id, &pres,
+ pcs->id);
+ if (code < 0)
+ return code;
+ pres->object = COS_OBJECT(pcs);
+ code = cos_stream_put_c_strings(pcs, pdev, "/Type", "/XObject");
+ if (code < 0)
+ return code;
+ code = cos_stream_put_c_strings(pcs, pdev, "/Subtype", "/PS");
if (code < 0)
return code;
- s = pdev->strm;
- pputs(s, "/Subtype/PS");
if (level1.data != 0) {
long level1_id = pdf_obj_ref(pdev);
+ char r[10 + 5]; /* %ld 0 R\0 */
+ stream *s;
+ long length_id = pdf_obj_ref(pdev);
- pprintld1(s, "/Level1 %ld 0 R", level1_id);
- pdfmark_write_ps(pdev, &source);
+ sprintf(r, "%ld 0 R", level1_id);
+ code = cos_stream_put_c_strings(pcs, pdev, "/Level1", r);
+ if (code < 0)
+ return code;
pdf_open_separate(pdev, level1_id);
- pputs(pdev->strm, "<<");
- pdfmark_write_ps(pdev, &level1);
- } else
- pdfmark_write_ps(pdev, &source);
- code = pdf_open_contents(pdev, pdf_in_stream);
+ s = pdev->strm;
+ pprintld1(s, "<</Length %ld 0 R>>stream\n", length_id);
+ size = pdfmark_write_ps(s, &level1);
+ pputs(s, "endstream\n");
+ pdf_end_separate(pdev);
+ pdf_open_separate(pdev, length_id);
+ pprintld1(s, "%ld\n", (long)size);
+ pdf_end_separate(pdev);
+ }
+ size = pdfmark_write_ps(pdev->streams.strm, &source);
+ code = cos_stream_add(pcs, pdev, size);
+ if (code < 0)
+ return code;
+ if (objname)
+ pres->named = true;
+ else {
+ /* Write the resource now, since it won't be written later. */
+ COS_WRITE_OBJECT(pcs, pdev);
+ COS_RELEASE(pcs, pdev->pdf_memory, "pdfmark_PS");
+ }
+ code = pdf_open_contents(pdev, PDF_IN_STREAM);
if (code < 0)
return code;
- pprintld1(pdev->strm, "/R%ld Do\n", pres->id);
+ pprintld1(pdev->strm, "/R%ld Do\n", pcs->id);
}
return 0;
}
+/* Common code for pdfmarks that do PUT into a specific object. */
+private int
+pdfmark_put_pairs(gx_device_pdf *pdev, cos_dict_t *pcd,
+ gs_param_string * pairs, uint count)
+{
+ int code = 0, i;
+
+ if (count & 1)
+ return_error(gs_error_rangecheck);
+ for (i = 0; code >= 0 && i < count; i += 2)
+ code = pdfmark_put_pair(pdev, pcd, pairs + i);
+ return code;
+}
+
/* PAGES pdfmark */
private int
pdfmark_PAGES(gx_device_pdf * pdev, gs_param_string * pairs, uint count,
const gs_matrix * pctm, const gs_param_string * no_objname)
{
- return pdfmark_save_pairs(pdev, pairs, count, &pdev->pages_string);
+ return pdfmark_put_pairs(pdev, pdev->Pages, pairs, count);
}
/* PAGE pdfmark */
@@ -1058,7 +987,7 @@ private int
pdfmark_PAGE(gx_device_pdf * pdev, gs_param_string * pairs, uint count,
const gs_matrix * pctm, const gs_param_string * no_objname)
{
- return pdfmark_save_pairs(pdev, pairs, count, &pdev->page_string);
+ return pdfmark_put_pairs(pdev, pdf_current_page_dict(pdev), pairs, count);
}
/* DOCINFO pdfmark */
@@ -1066,23 +995,7 @@ private int
pdfmark_DOCINFO(gx_device_pdf * pdev, gs_param_string * pairs, uint count,
const gs_matrix * pctm, const gs_param_string * no_objname)
{
- long info_id = pdf_begin_separate(pdev);
- stream *s = pdev->strm;
- uint i;
-
- if (info_id < 0)
- return info_id;
- pputs(s, "<<\n");
- for (i = 0; i < count; i += 2)
- if (!pdf_key_eq(&pairs[i], "CreationDate") &&
- !pdf_key_eq(&pairs[i], "Producer")
- )
- pdfmark_write_pair(pdev, &pairs[i]);
- pdf_write_default_info(pdev);
- pputs(s, ">>\n");
- pdf_end_separate(pdev);
- pdev->info_id = info_id;
- return 0;
+ return pdfmark_put_pairs(pdev, pdev->Info, pairs, count);
}
/* DOCVIEW pdfmark */
@@ -1090,18 +1003,557 @@ private int
pdfmark_DOCVIEW(gx_device_pdf * pdev, gs_param_string * pairs, uint count,
const gs_matrix * pctm, const gs_param_string * no_objname)
{
- char dest[max_dest_string];
-
- if (pdfmark_make_dest(dest, pdev, pairs, count)) {
- gs_param_string add_dest[2];
- static const char *const skip_dest[] =
- {"Page", "View", 0};
-
- param_string_from_string(add_dest[0], "OpenAction");
- param_string_from_string(add_dest[1], dest);
- return pdfmark_save_edited_pairs(pdev, pairs, count, skip_dest,
- add_dest, 2,
- &pdev->catalog_string);
+ char dest[MAX_DEST_STRING];
+ int code = 0;
+
+ if (count & 1)
+ return_error(gs_error_rangecheck);
+ if (pdfmark_make_dest(dest, pdev, "/Page", "/View", pairs, count)) {
+ int i;
+
+ code = cos_dict_put_c_strings(pdev->Catalog, pdev, "/OpenAction", dest);
+ for (i = 0; code >= 0 && i < count; i += 2)
+ if (!(pdf_key_eq(&pairs[i], "/Page") ||
+ pdf_key_eq(&pairs[i], "/View"))
+ )
+ code = pdfmark_put_pair(pdev, pdev->Catalog, pairs + i);
+ return code;
} else
- return pdfmark_save_pairs(pdev, pairs, count, &pdev->catalog_string);
+ return pdfmark_put_pairs(pdev, pdev->Catalog, pairs, count);
+}
+
+/* ---------------- Named object pdfmarks ---------------- */
+
+/* [ /BBox [llx lly urx ury] /_objdef {obj} /BP pdfmark */
+private int
+pdfmark_BP(gx_device_pdf * pdev, gs_param_string * pairs, uint count,
+ const gs_matrix * pctm, const gs_param_string * objname)
+{
+ gs_rect bbox;
+ cos_stream_t *pcs;
+ pdf_graphics_save_t *pdgs;
+ int code;
+ double xscale = pdev->HWResolution[0] / 72.0,
+ yscale = pdev->HWResolution[1] / 72.0;
+ char bbox_str[6 + 4 * 12];
+
+ if (objname == 0 || count != 2 || !pdf_key_eq(&pairs[0], "/BBox"))
+ return_error(gs_error_rangecheck);
+ if (sscanf((const char *)pairs[1].data, "[%lg %lg %lg %lg]",
+ &bbox.p.x, &bbox.p.y, &bbox.q.x, &bbox.q.y) != 4
+ )
+ return_error(gs_error_rangecheck);
+ code = pdf_make_named(pdev, objname, cos_type_stream,
+ (cos_object_t **)&pcs, true);
+ if (code < 0)
+ return code;
+ gs_bbox_transform(&bbox, pctm, &bbox);
+ sprintf(bbox_str, "[%.8g %.8g %.8g %.8g]",
+ bbox.p.x * xscale, bbox.p.y * yscale,
+ bbox.q.x * xscale, bbox.q.y * yscale);
+ if ((code = cos_stream_put_c_strings(pcs, pdev, "/Type", "/XObject")) < 0 ||
+ (code = cos_stream_put_c_strings(pcs, pdev, "/Subtype", "/Form")) < 0 ||
+ (code = cos_stream_put_c_strings(pcs, pdev, "/FormType", "1")) < 0 ||
+ (code = cos_stream_put_c_strings(pcs, pdev, "/Matrix", "[1 0 0 1 0 0]")) < 0 ||
+ (code = cos_stream_put_c_strings(pcs, pdev, "/BBox", bbox_str)) < 0
+ )
+ return code;
+ pdgs = gs_alloc_struct(pdev->pdf_memory, pdf_graphics_save_t,
+ &st_pdf_graphics_save, "pdfmark_BP");
+ if (pdgs == 0)
+ return_error(gs_error_VMerror);
+ if (pdev->context != PDF_IN_NONE) {
+ code = pdf_open_page(pdev, PDF_IN_STREAM);
+ if (code < 0) {
+ gs_free_object(pdev->pdf_memory, pdgs, "pdfmark_BP");
+ return code;
+ }
+ }
+ if (!pdev->open_graphics) {
+ pdev->pictures.save_strm = pdev->strm;
+ pdev->strm = pdev->pictures.strm;
+ }
+ pdgs->prev = pdev->open_graphics;
+ pdgs->object = pcs;
+ pdgs->position = stell(pdev->pictures.strm);
+ pdgs->save_context = pdev->context;
+ pdgs->save_contents_id = pdev->contents_id;
+ pdev->open_graphics = pdgs;
+ pdev->context = PDF_IN_STREAM;
+ pdev->contents_id = pcs->id;
+ return 0;
+}
+
+/* [ /EP pdfmark */
+private int
+pdfmark_EP(gx_device_pdf * pdev, gs_param_string * pairs, uint count,
+ const gs_matrix * pctm, const gs_param_string * no_objname)
+{
+ pdf_graphics_save_t *pdgs = pdev->open_graphics;
+ pdf_resource_t *pres;
+ cos_stream_t *pcs;
+ long start;
+ uint size;
+ int code;
+
+ if (count != 0 || pdgs == 0 || !(pcs = pdgs->object)->is_open)
+ return_error(gs_error_rangecheck);
+ code = pdf_open_contents(pdev, PDF_IN_STREAM);
+ if (code < 0)
+ return code;
+ code = pdf_alloc_resource(pdev, resourceXObject, gs_no_id, &pres,
+ pcs->id);
+ if (code < 0)
+ return code;
+ pres->object = COS_OBJECT(pcs);
+ start = pdgs->position;
+ pcs->is_open = false;
+ size = stell(pdev->strm) - start;
+ pdev->open_graphics = pdgs->prev;
+ pdev->context = pdgs->save_context;
+ pdev->contents_id = pdgs->save_contents_id;
+ gs_free_object(pdev->pdf_memory, pdgs, "pdfmark_EP");
+ /* Copy the data to the streams file. */
+ sflush(pdev->strm);
+ sseek(pdev->strm, start);
+ fseek(pdev->pictures.file, start, SEEK_SET);
+ pdf_copy_data(pdev->streams.strm, pdev->pictures.file, size);
+ code = cos_stream_add(pcs, pdev, size);
+ /* Keep the file in sync with the stream. */
+ fseek(pdev->pictures.file, start, SEEK_SET);
+ if (!pdev->open_graphics) {
+ pdev->strm = pdev->pictures.save_strm;
+ pdev->pictures.save_strm = 0;
+ }
+ return code;
+}
+
+/* [ {obj} /SP pdfmark */
+private int
+pdfmark_SP(gx_device_pdf * pdev, gs_param_string * pairs, uint count,
+ const gs_matrix * pctm, const gs_param_string * no_objname)
+{
+ cos_object_t *pco; /* stream */
+ gs_matrix ctm;
+ int code;
+
+ if (count != 1)
+ return_error(gs_error_rangecheck);
+ if ((code = pdf_get_named(pdev, &pairs[0], cos_type_stream, &pco)) < 0)
+ return code;
+ /****** HOW TO CHECK FOR GRAPHICS STREAM? ******/
+ if (pco->is_open)
+ return_error(gs_error_rangecheck);
+ code = pdf_open_contents(pdev, PDF_IN_STREAM);
+ if (code < 0)
+ return code;
+ ctm = *pctm;
+ ctm.tx *= pdev->HWResolution[0] / 72.0;
+ ctm.ty *= pdev->HWResolution[1] / 72.0;
+ pdf_put_matrix(pdev, "q ", &ctm, "cm\n");
+ pprintld1(pdev->strm, "/R%ld Do Q\n", pco->id);
+ return 0;
+}
+
+/* [ /_objdef {array} /type /array /OBJ pdfmark */
+/* [ /_objdef {dict} /type /dict /OBJ pdfmark */
+/* [ /_objdef {stream} /type /stream /OBJ pdfmark */
+private int
+pdfmark_OBJ(gx_device_pdf * pdev, gs_param_string * pairs, uint count,
+ const gs_matrix * pctm, const gs_param_string * objname)
+{
+ cos_type_t cotype;
+ cos_object_t *pco;
+ int code;
+
+ if (objname == 0 || count != 2 || !pdf_key_eq(&pairs[0], "/type"))
+ return_error(gs_error_rangecheck);
+ if (pdf_key_eq(&pairs[1], "/array"))
+ cotype = cos_type_array;
+ else if (pdf_key_eq(&pairs[1], "/dict"))
+ cotype = cos_type_dict;
+ else if (pdf_key_eq(&pairs[1], "/stream"))
+ cotype = cos_type_stream;
+ else
+ return_error(gs_error_rangecheck);
+ if ((code = pdf_make_named(pdev, objname, cotype, &pco, true)) < 0)
+ return code;
+ return 0;
+}
+
+/* [ {array} index value /PUT pdfmark */
+/* Dictionaries are converted to .PUTDICT */
+/* Streams are converted to .PUTSTREAM */
+private int
+pdfmark_PUT(gx_device_pdf * pdev, gs_param_string * pairs, uint count,
+ const gs_matrix * pctm, const gs_param_string * no_objname)
+{
+ cos_object_t *pco;
+ cos_value_t value;
+ int code, index;
+
+ if (count != 3)
+ return_error(gs_error_rangecheck);
+ if ((code = pdf_get_named(pdev, &pairs[0], cos_type_array, &pco)) < 0)
+ return code;
+ if ((code = pdfmark_scan_int(&pairs[1], &index)) < 0)
+ return code;
+ if (index < 0)
+ return_error(gs_error_rangecheck);
+ return cos_array_put((cos_array_t *)pco, pdev, index,
+ cos_string_value(&value, pairs[2].data, pairs[2].size));
+}
+
+/* [ {dict} key value ... /.PUTDICT pdfmark */
+private int
+pdfmark_PUTDICT(gx_device_pdf * pdev, gs_param_string * pairs, uint count,
+ const gs_matrix * pctm, const gs_param_string * no_objname)
+{
+ cos_object_t *pco;
+ int code;
+
+ if ((code = pdf_get_named(pdev, &pairs[0], cos_type_dict, &pco)) < 0)
+ return code;
+ return pdfmark_put_pairs(pdev, (cos_dict_t *)pco, pairs + 1, count - 1);
+}
+
+/* [ {stream} string ... /.PUTSTREAM pdfmark */
+private int
+pdfmark_PUTSTREAM(gx_device_pdf * pdev, gs_param_string * pairs, uint count,
+ const gs_matrix * pctm, const gs_param_string * no_objname)
+{
+ cos_object_t *pco;
+ int code, i;
+
+ if (count != 2)
+ return_error(gs_error_rangecheck);
+ if ((code = pdf_get_named(pdev, &pairs[0], cos_type_stream, &pco)) < 0)
+ return code;
+ if (!pco->is_open)
+ return_error(gs_error_rangecheck);
+ for (i = 1; code >= 0 && i < count; ++i)
+ code = cos_stream_add_bytes((cos_stream_t *)pco, pdev, pairs[i].data,
+ pairs[i].size);
+ return code;
+}
+
+/* [ {array} index value ... /.PUTINTERVAL pdfmark */
+private int
+pdfmark_PUTINTERVAL(gx_device_pdf * pdev, gs_param_string * pairs, uint count,
+ const gs_matrix * pctm, const gs_param_string * no_objname)
+{
+ cos_object_t *pco;
+ cos_value_t value;
+ int code, index, i;
+
+ if (count < 2)
+ return_error(gs_error_rangecheck);
+ if ((code = pdf_get_named(pdev, &pairs[0], cos_type_array, &pco)) < 0)
+ return code;
+ if ((code = pdfmark_scan_int(&pairs[1], &index)) < 0)
+ return code;
+ if (index < 0)
+ return_error(gs_error_rangecheck);
+ for (i = 2; code >= 0 && i < count; ++i)
+ code = cos_array_put((cos_array_t *)pco, pdev, index + i - 2,
+ cos_string_value(&value, pairs[i].data, pairs[i].size));
+ return code;
+}
+
+/* [ {stream} /CLOSE pdfmark */
+private int
+pdfmark_CLOSE(gx_device_pdf * pdev, gs_param_string * pairs, uint count,
+ const gs_matrix * pctm, const gs_param_string * no_objname)
+{
+ cos_object_t *pco;
+ int code;
+
+ if (count != 1)
+ return_error(gs_error_rangecheck);
+ if ((code = pdf_get_named(pdev, &pairs[0], cos_type_stream, &pco)) < 0)
+ return code;
+ if (!pco->is_open)
+ return_error(gs_error_rangecheck);
+ /* Currently we don't do anything special when closing a stream. */
+ pco->is_open = false;
+ return 0;
+}
+
+/* [ /NamespacePush pdfmark */
+private int
+pdfmark_NamespacePush(gx_device_pdf *pdev, gs_param_string *pairs, uint count,
+ const gs_matrix *pctm, const gs_param_string *objname)
+{
+ return 0;
+}
+
+/* [ /NamespacePop pdfmark */
+private int
+pdfmark_NamespacePop(gx_device_pdf *pdev, gs_param_string *pairs, uint count,
+ const gs_matrix *pctm, const gs_param_string *objname)
+{
+ return 0;
+}
+
+/* [ /_objdef {image} /NI pdfmark */
+private int
+pdfmark_NI(gx_device_pdf *pdev, gs_param_string *pairs, uint count,
+ const gs_matrix *pctm, const gs_param_string *objname)
+{
+ return 0;
+}
+
+/* ---------------- Document structure pdfmarks ---------------- */
+
+/* [ newsubtype1 stdsubtype1 ... /StRoleMap pdfmark */
+private int
+pdfmark_StRoleMap(gx_device_pdf *pdev, gs_param_string *pairs, uint count,
+ const gs_matrix *pctm, const gs_param_string *objname)
+{
+ return 0;
+}
+
+/* [ class1 {attrobj1} ... /StClassMap pdfmark */
+private int
+pdfmark_StClassMap(gx_device_pdf *pdev, gs_param_string *pairs, uint count,
+ const gs_matrix *pctm, const gs_param_string *objname)
+{
+ return 0;
+}
+
+/*
+ * [ [/_objdef {objname}] /Subtype name [/Title string] [/Alt string]
+ * [/ID string] [/Class name] [/At index] [/Bookmark dict] [action_pairs...]
+ * /StPNE pdfmark
+ */
+private int
+pdfmark_StPNE(gx_device_pdf *pdev, gs_param_string *pairs, uint count,
+ const gs_matrix *pctm, const gs_param_string *objname)
+{
+ return 0;
+}
+
+/* [ [/Title string] [/Open bool] [action_pairs...] /StBookmarkRoot pdfmark */
+private int
+pdfmark_StBookmarkRoot(gx_device_pdf *pdev, gs_param_string *pairs, uint count,
+ const gs_matrix *pctm, const gs_param_string *objname)
+{
+ return 0;
+}
+
+/* [ [/E {elt}] /StPush pdfmark */
+private int
+pdfmark_StPush(gx_device_pdf *pdev, gs_param_string *pairs, uint count,
+ const gs_matrix *pctm, const gs_param_string *objname)
+{
+ return 0;
+}
+
+/* [ /StPop pdfmark */
+private int
+pdfmark_StPop(gx_device_pdf *pdev, gs_param_string *pairs, uint count,
+ const gs_matrix *pctm, const gs_param_string *objname)
+{
+ return 0;
+}
+
+/* [ /StPopAll pdfmark */
+private int
+pdfmark_StPopAll(gx_device_pdf *pdev, gs_param_string *pairs, uint count,
+ const gs_matrix *pctm, const gs_param_string *objname)
+{
+ return 0;
+}
+
+/* [ [/T tagname] [/At index] /StBMC pdfmark */
+private int
+pdfmark_StBMC(gx_device_pdf *pdev, gs_param_string *pairs, uint count,
+ const gs_matrix *pctm, const gs_param_string *objname)
+{
+ return 0;
+}
+
+/* [ [/P propdict] [/T tagname] [/At index] /StBDC pdfmark */
+private int
+pdfmark_StBDC(gx_device_pdf *pdev, gs_param_string *pairs, uint count,
+ const gs_matrix *pctm, const gs_param_string *objname)
+{
+ return 0;
+}
+
+/* [ /EMC pdfmark */
+private int
+pdfmark_EMC(gx_device_pdf *pdev, gs_param_string *pairs, uint count,
+ const gs_matrix *pctm, const gs_param_string *objname)
+{
+ return 0;
+}
+
+/* [ /Obj {obj} [/At index] /StOBJ pdfmark */
+private int
+pdfmark_StOBJ(gx_device_pdf *pdev, gs_param_string *pairs, uint count,
+ const gs_matrix *pctm, const gs_param_string *objname)
+{
+ return 0;
+}
+
+/* [ /Obj {obj} /StAttr pdfmark */
+private int
+pdfmark_StAttr(gx_device_pdf *pdev, gs_param_string *pairs, uint count,
+ const gs_matrix *pctm, const gs_param_string *objname)
+{
+ return 0;
+}
+
+/* [ /StoreName name /StStore pdfmark */
+private int
+pdfmark_StStore(gx_device_pdf *pdev, gs_param_string *pairs, uint count,
+ const gs_matrix *pctm, const gs_param_string *objname)
+{
+ return 0;
+}
+
+/* [ /StoreName name /StRetrieve pdfmark */
+private int
+pdfmark_StRetrieve(gx_device_pdf *pdev, gs_param_string *pairs, uint count,
+ const gs_matrix *pctm, const gs_param_string *objname)
+{
+ return 0;
+}
+
+/* ---------------- Dispatch ---------------- */
+
+/*
+ * Define the pdfmark types we know about.
+ */
+private const pdfmark_name mark_names[] =
+{
+ /* Miscellaneous. */
+ {"ANN", pdfmark_ANN, PDFMARK_NAMEABLE},
+ {"LNK", pdfmark_LNK, PDFMARK_NAMEABLE},
+ {"OUT", pdfmark_OUT, 0},
+ {"ARTICLE", pdfmark_ARTICLE, 0},
+ {"DEST", pdfmark_DEST, PDFMARK_NAMEABLE},
+ {"PS", pdfmark_PS, PDFMARK_NAMEABLE},
+ {"PAGES", pdfmark_PAGES, 0},
+ {"PAGE", pdfmark_PAGE, 0},
+ {"DOCINFO", pdfmark_DOCINFO, 0},
+ {"DOCVIEW", pdfmark_DOCVIEW, 0},
+ /* Named objects. */
+ {"BP", pdfmark_BP, PDFMARK_NAMEABLE},
+ {"EP", pdfmark_EP, 0},
+ {"SP", pdfmark_SP, PDFMARK_ODD_OK | PDFMARK_KEEP_NAME},
+ {"OBJ", pdfmark_OBJ, PDFMARK_NAMEABLE},
+ {"PUT", pdfmark_PUT, PDFMARK_ODD_OK | PDFMARK_KEEP_NAME},
+ {".PUTDICT", pdfmark_PUTDICT, PDFMARK_ODD_OK | PDFMARK_KEEP_NAME},
+ {".PUTINTERVAL", pdfmark_PUTINTERVAL, PDFMARK_ODD_OK | PDFMARK_KEEP_NAME},
+ {".PUTSTREAM", pdfmark_PUTSTREAM, PDFMARK_ODD_OK | PDFMARK_KEEP_NAME},
+ {"CLOSE", pdfmark_CLOSE, PDFMARK_ODD_OK | PDFMARK_KEEP_NAME},
+ {"NamespacePush", pdfmark_NamespacePush, 0},
+ {"NamespacePop", pdfmark_NamespacePop, 0},
+ {"NI", pdfmark_NI, PDFMARK_NAMEABLE},
+ /* Document structure. */
+ {"StRoleMap", pdfmark_StRoleMap, 0},
+ {"StClassMap", pdfmark_StClassMap, 0},
+ {"StPNE", pdfmark_StPNE, PDFMARK_NAMEABLE},
+ {"StBookmarkRoot", pdfmark_StBookmarkRoot, 0},
+ {"StPush", pdfmark_StPush, 0},
+ {"StPop", pdfmark_StPop, 0},
+ {"StPopAll", pdfmark_StPopAll, 0},
+ {"StBMC", pdfmark_StBMC, 0},
+ {"StBDC", pdfmark_StBDC, 0},
+ {"EMC", pdfmark_EMC, 0},
+ {"StOBJ", pdfmark_StOBJ, 0},
+ {"StAttr", pdfmark_StAttr, 0},
+ {"StStore", pdfmark_StStore, 0},
+ {"StRetrieve", pdfmark_StRetrieve, 0},
+ /* End of list. */
+ {0, 0}
+};
+
+/* Process a pdfmark. */
+int
+pdfmark_process(gx_device_pdf * pdev, const gs_param_string_array * pma)
+{
+ const gs_param_string *data = pma->data;
+ uint size = pma->size;
+ const gs_param_string *pts = &data[size - 1];
+ const gs_param_string *objname = 0;
+ gs_matrix ctm;
+ const pdfmark_name *pmn;
+ int code = 0;
+
+ if (size < 2 ||
+ sscanf((const char *)pts[-1].data, "[%g %g %g %g %g %g]",
+ &ctm.xx, &ctm.xy, &ctm.yx, &ctm.yy, &ctm.tx, &ctm.ty) != 6
+ )
+ return_error(gs_error_rangecheck);
+ /*
+ * Our coordinate system is scaled so that user space is always
+ * default user space. Adjust the CTM to match this.
+ */
+ {
+ double xscale = 72.0 / pdev->HWResolution[0],
+ yscale = 72.0 / pdev->HWResolution[1];
+
+ ctm.xx *= xscale, ctm.xy *= yscale;
+ ctm.yx *= xscale, ctm.yy *= yscale;
+ ctm.tx *= xscale, ctm.ty *= yscale;
+ }
+ size -= 2; /* remove CTM & pdfmark name */
+ for (pmn = mark_names; pmn->mname != 0; ++pmn)
+ if (pdf_key_eq(pts, pmn->mname)) {
+ gs_memory_t *mem = pdev->pdf_memory;
+ int odd_ok = (pmn->options & PDFMARK_ODD_OK) != 0;
+ gs_param_string *pairs;
+ int j;
+
+ if (size & !odd_ok)
+ return_error(gs_error_rangecheck);
+ if (pmn->options & PDFMARK_NAMEABLE) {
+ /* Look for an object name. */
+ for (j = 0; j < size; j += 2) {
+ if (pdf_key_eq(&data[j], "/_objdef")) {
+ objname = &data[j + 1];
+ if (!pdf_objname_is_valid(objname->data,
+ objname->size)
+ )
+ return_error(gs_error_rangecheck);
+ /* Save the pairs without the name. */
+ size -= 2;
+ pairs = (gs_param_string *)
+ gs_alloc_byte_array(mem, size,
+ sizeof(gs_param_string),
+ "pdfmark_process(pairs)");
+ if (!pairs)
+ return_error(gs_error_VMerror);
+ memcpy(pairs, data, j * sizeof(*data));
+ memcpy(pairs + j, data + j + 2,
+ (size - j) * sizeof(*data));
+ goto copied;
+ }
+ }
+ }
+ /* Save all the pairs. */
+ pairs = (gs_param_string *)
+ gs_alloc_byte_array(mem, size, sizeof(gs_param_string),
+ "pdfmark_process(pairs)");
+ if (!pairs)
+ return_error(gs_error_VMerror);
+ memcpy(pairs, data, size * sizeof(*data));
+ copied: /* Substitute object references for names. */
+ for (j = (pmn->options & PDFMARK_KEEP_NAME ? 1 : 1 - odd_ok);
+ j < size; j += 2 - odd_ok
+ ) {
+ code = pdf_replace_names(pdev, &pairs[j], &pairs[j]);
+ if (code < 0) {
+ gs_free_object(mem, pairs, "pdfmark_process(pairs)");
+ return code;
+ }
+ }
+ code = (*pmn->proc) (pdev, pairs, size, &ctm, objname);
+ gs_free_object(mem, pairs, "pdfmark_process(pairs)");
+ break;
+ }
+ return code;
}
diff --git a/gs/src/gdevpdfo.c b/gs/src/gdevpdfo.c
index 86b4cf13e..3f1ee8e89 100644
--- a/gs/src/gdevpdfo.c
+++ b/gs/src/gdevpdfo.c
@@ -17,661 +17,641 @@
*/
-/* Named object pdfmark processing */
+/* Cos object support */
#include "memory_.h"
#include "string_.h"
#include "gx.h"
#include "gserrors.h"
#include "gsutil.h" /* for bytes_compare */
#include "gdevpdfx.h"
+#include "gdevpdfo.h"
#include "strimpl.h"
#include "sstring.h"
-/* GC procedures */
-
-private_st_pdf_named_element();
-public_st_pdf_named_object();
+/* GC descriptors */
+private_st_cos_element();
+private_st_cos_stream_piece();
+private_st_cos_object();
+private_st_cos_value();
+private_st_cos_array_element();
+private_st_cos_dict_element();
-#define pne ((pdf_named_element *)vptr)
-private
-ENUM_PTRS_BEGIN(pdf_named_elt_enum_ptrs) return 0;
-
-ENUM_PTR(0, pdf_named_element, next);
-ENUM_STRING_PTR(1, pdf_named_element, key);
-/****** WRONG IF data = 0 ******/
-ENUM_STRING_PTR(2, pdf_named_element, value);
+/* GC procedures */
+private
+ENUM_PTRS_WITH(cos_value_enum_ptrs, cos_value_t *pcv) return 0;
+ case 0: return (pcv->is_object ? ENUM_OBJ(pcv->contents.object) :
+ ENUM_STRING(&pcv->contents.chars));
ENUM_PTRS_END
-private RELOC_PTRS_BEGIN(pdf_named_elt_reloc_ptrs)
+private
+RELOC_PTRS_WITH(cos_value_reloc_ptrs, cos_value_t *pcv)
{
- RELOC_PTR(pdf_named_element, next);
- if (pne->key.data != 0)
- RELOC_STRING_PTR(pdf_named_element, key);
- RELOC_STRING_PTR(pdf_named_element, value);
+ if (pcv->is_object)
+ RELOC_VAR(pcv->contents.object);
+ else
+ RELOC_STRING_VAR(pcv->contents.chars);
}
RELOC_PTRS_END
-#undef pne
-
-#define pno ((pdf_named_object *)vptr)
-private ENUM_PTRS_BEGIN(pdf_named_obj_enum_ptrs) return 0;
-ENUM_PTR(0, pdf_named_object, next);
-ENUM_STRING_PTR(1, pdf_named_object, key);
-ENUM_PTR(2, pdf_named_object, elements);
-case 3:
-if (pno->type == named_graphics)
- ENUM_RETURN(pno->graphics.enclosing);
-else
- return 0;
+private
+ENUM_PTRS_WITH(cos_array_element_enum_ptrs, cos_array_element_t *pcae)
+{
+ return (index < cos_element_num_ptrs ?
+ ENUM_USING_PREFIX(st_cos_element, 0) :
+ ENUM_USING(st_cos_value, &pcae->value, sizeof(cos_value_t),
+ index - cos_element_num_ptrs));
+}
ENUM_PTRS_END
-private RELOC_PTRS_BEGIN(pdf_named_obj_reloc_ptrs)
+private
+RELOC_PTRS_WITH(cos_array_element_reloc_ptrs, cos_array_element_t *pcae)
{
- RELOC_PTR(pdf_named_object, next);
- RELOC_STRING_PTR(pdf_named_object, key);
- RELOC_PTR(pdf_named_object, elements);
- if (pno->type == named_graphics)
- RELOC_PTR(pdf_named_object, graphics.enclosing);
+ RELOC_PREFIX(st_cos_element);
+ RELOC_USING(st_cos_value, &pcae->value, sizeof(cos_value_t));
+}
+RELOC_PTRS_END
+private
+ENUM_PTRS_WITH(cos_dict_element_enum_ptrs, cos_dict_element_t *pcde)
+{
+ return (index < cos_element_num_ptrs ?
+ ENUM_USING_PREFIX(st_cos_element, 0) :
+ (index -= cos_element_num_ptrs) == 0 ?
+ ENUM_STRING(&pcde->key) :
+ ENUM_USING(st_cos_value, &pcde->value, sizeof(cos_value_t),
+ index - 1));
+}
+ENUM_PTRS_END
+private
+RELOC_PTRS_WITH(cos_dict_element_reloc_ptrs, cos_dict_element_t *pcde)
+{
+ RELOC_PREFIX(st_cos_element);
+ RELOC_STRING_VAR(pcde->key);
+ RELOC_USING(st_cos_value, &pcde->value, sizeof(cos_value_t));
}
RELOC_PTRS_END
-#undef pno
-
-/* ---------------- pdfmark processing ---------------- */
-
-/* Define the pdfmark types implemented here. */
-private pdfmark_proc(pdfmark_BP);
-private pdfmark_proc(pdfmark_EP);
-private pdfmark_proc(pdfmark_SP);
-private pdfmark_proc(pdfmark_OBJ);
-private pdfmark_proc(pdfmark_PUT);
-private pdfmark_proc(pdfmark_PUTDICT);
-private pdfmark_proc(pdfmark_PUTINTERVAL);
-private pdfmark_proc(pdfmark_CLOSE);
-const pdfmark_name pdfmark_names_named[] =
-{
- {"BP", pdfmark_BP, pdfmark_nameable},
- {"EP", pdfmark_EP, 0},
- {"SP", pdfmark_SP, pdfmark_odd_ok | pdfmark_keep_name},
- {"OBJ", pdfmark_OBJ, pdfmark_nameable},
- {"PUT", pdfmark_PUT, pdfmark_odd_ok | pdfmark_keep_name},
- {".PUTDICT", pdfmark_PUTDICT, pdfmark_odd_ok | pdfmark_keep_name},
- {".PUTINTERVAL", pdfmark_PUTINTERVAL, pdfmark_odd_ok | pdfmark_keep_name},
- {"CLOSE", pdfmark_CLOSE, pdfmark_odd_ok | pdfmark_keep_name},
- {0, 0}
-};
-/*
- * Predefined objects:
- * {Catalog}, {DocInfo}
- * {Page<#>}, {ThisPage}, {PrevPage}, {NextPage}
- */
+/* ---------------- Generic support ---------------- */
-/* ---------------- Utilities ---------------- */
+/* Initialize a just-allocated cos object. */
+private void
+cos_object_init(cos_object_t *pco, const cos_object_procs_t *procs)
+{
+ if (pco) {
+ pco->cos_procs = procs;
+ pco->id = 0;
+ pco->elements = 0;
+ pco->pieces = 0;
+ pco->is_open = true;
+ }
+}
-private int pdfmark_write_named(P2(gx_device_pdf * pdev,
- const pdf_named_object * pno));
-private void pdfmark_free_named(P2(gx_device_pdf * pdev,
- pdf_named_object * pno));
+/* Change a generic cos object into one of a specific type. */
+int
+cos_become(cos_object_t *pco, cos_type_t cotype)
+{
+ if (cos_type(pco) != cos_type_generic)
+ return_error(gs_error_typecheck);
+ cos_type(pco) = cotype;
+ return 0;
+}
-/* ------ Public ------ */
+/* Release a cos object. */
+cos_proc_release(cos_release); /* check prototype */
+void
+cos_release(cos_object_t *pco, gs_memory_t *mem, client_name_t cname)
+{
+ pco->cos_procs->release(pco, mem, cname);
+}
-/*
- * Look up an object name. Return e_rangecheck if the syntax is invalid.
- * If the object is missing, then:
- * - If create is false, return gs_error_undefined;
- * - If create is true, create the object and return 1.
- * Note that there is code in gdevpdf.c that relies on the fact that
- * the named_objects list is sorted by decreasing object number.
- */
+/* Free a cos object. */
+void
+cos_free(cos_object_t *pco, gs_memory_t *mem, client_name_t cname)
+{
+ cos_release(pco, mem, cname);
+ gs_free_object(mem, pco, cname);
+}
+
+/* Write a cos object on the output. */
+cos_proc_write(cos_write); /* check prototype */
+int
+cos_write(const cos_object_t *pco, gx_device_pdf *pdev)
+{
+ return pco->cos_procs->write(pco, pdev);
+}
+
+/* Write a cos object as a PDF object. */
+int
+cos_write_object(const cos_object_t *pco, gx_device_pdf *pdev)
+{
+ int code;
+
+ if (pco->id == 0)
+ return_error(gs_error_Fatal);
+ pdf_open_separate(pdev, pco->id);
+ code = cos_write(pco, pdev);
+ pdf_end_separate(pdev);
+ return code;
+}
+
+/* Make a value to store into a composite object. */
+const cos_value_t *
+cos_string_value(cos_value_t *pcv, const byte *data, uint size)
+{
+ /*
+ * It's OK to break const here, because the value will be copied
+ * before being stored in the collection.
+ */
+ pcv->contents.chars.data = (byte *)data;
+ pcv->contents.chars.size = size;
+ pcv->is_object = false;
+ return pcv;
+}
+const cos_value_t *
+cos_c_string_value(cos_value_t *pcv, const char *str)
+{
+ return cos_string_value(pcv, (const byte *)str, strlen(str));
+}
+const cos_value_t *
+cos_object_value(cos_value_t *pcv, cos_object_t *pco)
+{
+ pcv->contents.object = pco;
+ pcv->is_object = true;
+ return pcv;
+}
+
+/* Free a value. */
+private void
+cos_value_free(cos_value_t *pcv, gs_memory_t *mem, client_name_t cname)
+{
+ if (pcv->is_object) {
+ /* Free the object if this is the only reference to it. */
+ if (!pcv->contents.object->id)
+ cos_free(pcv->contents.object, mem, cname);
+ } else
+ gs_free_string(mem, pcv->contents.chars.data, pcv->contents.chars.size,
+ cname);
+}
+
+/* Write a value on the output. */
+private void
+cos_value_write(const cos_value_t *pcv, gx_device_pdf *pdev)
+{
+ if (pcv->is_object) {
+ cos_object_t *pco = pcv->contents.object;
+
+ if (pco->id)
+ pprintld1(pdev->strm, "%ld 0 R", pco->id);
+ else
+ cos_write(pco, pdev);
+ } else
+ pdf_write_value(pdev, pcv->contents.chars.data,
+ pcv->contents.chars.size);
+}
+
+/* Copy a value if necessary for putting into an array or dictionary. */
private int
-pdfmark_find_named(gx_device_pdf * pdev, const gs_param_string * pname,
- pdf_named_object ** ppno, bool create)
-{
- const byte *data = pname->data;
- uint size = pname->size;
- gs_id key_id =
- (size == 0 ? 0 : data[0] + data[size / 2] + data[size - 1]);
- pdf_resource **plist =
- &pdev->resources[resourceNamedObject].
- chains[gs_id_hash(key_id) % num_resource_chains];
- pdf_named_object *pno = (pdf_named_object *) * plist;
-
- if (!pdfmark_objname_is_valid(data, size))
- return_error(gs_error_rangecheck);
- for (; pno; pno = pno->next)
- if (!bytes_compare(data, size, pno->key.data, pno->key.size)) {
- *ppno = pno;
- return 0;
- }
- if (!create)
- return_error(gs_error_undefined);
- {
- gs_memory_t *mem = pdev->pdf_memory;
- byte *key = gs_alloc_string(mem, size, "pdf named object key");
- pdf_resource *pres;
- int code;
+cos_copy_element_value(cos_value_t *pcv, gs_memory_t *mem,
+ const cos_value_t *pvalue)
+{
+ *pcv = *pvalue;
+ if (!pvalue->is_object) {
+ byte *value_data = gs_alloc_string(mem, pvalue->contents.chars.size,
+ "cos_copy_element_value");
- if (key == 0)
+ if (value_data == 0)
return_error(gs_error_VMerror);
- code = pdf_alloc_resource(pdev, resourceNamedObject, key_id, &pres);
- if (code < 0) {
- gs_free_string(mem, key, size, "pdf named object key");
- return code;
- }
- pno = (pdf_named_object *) pres;
- memcpy(key, data, size);
- pno->id = pdf_obj_ref(pdev);
- pno->type = named_unknown; /* caller may change */
- pno->key.data = key;
- pno->key.size = size;
- pno->elements = 0;
- pno->open = true;
- /* For now, just link the object onto the private list. */
- pno->next = pdev->named_objects;
- pdev->named_objects = pno;
- *ppno = pno;
- return 1;
+ memcpy(value_data, pvalue->contents.chars.data,
+ pvalue->contents.chars.size);
+ pcv->contents.chars.data = value_data;
}
+ return 0;
}
-/* Replace object names with object references in a (parameter) string. */
-private const byte *
-pdfmark_next_object(const byte * scan, const byte * end, const byte ** pname,
- pdf_named_object ** ppno, gx_device_pdf * pdev)
-{ /*
- * Starting at scan, find the next object reference, set *pname
- * to point to it in the string, store the object at *ppno,
- * and return a pointer to the first character beyond the
- * reference. If there are no more object references, set
- * *pname = end and return end.
- */
- const byte *left;
- const byte *lit;
- const byte *right;
-
- *ppno = 0;
-top:
- left = (const byte *)memchr(scan, '{', end - scan);
- if (left == 0)
- return (*pname = end);
- lit = (const byte *)memchr(scan, '(', left - scan);
- if (lit) {
- /* Skip over the string. */
- byte buf[50]; /* size is arbitrary */
- stream_cursor_read r;
- stream_cursor_write w;
- stream_PSSD_state ss;
- int status;
-
- s_PSSD_init_inline(&ss);
- r.ptr = lit - 1;
- r.limit = end - 1;
- w.limit = buf + sizeof(buf) - 1;
- do {
- w.ptr = buf - 1;
- status = (*s_PSSD_template.process)
- ((stream_state *) & ss, &r, &w, true);
- }
- while (status == 1);
- scan = r.ptr + 1;
- goto top;
- }
- right = (const byte *)memchr(left + 1, '}', end - (left + 1));
- if (right == 0) /* malformed name */
- return (*pname = end);
- *pname = left;
- ++right;
- {
- gs_param_string sname;
+/* Release a value copied for putting, if the operation fails. */
+private void
+cos_uncopy_element_value(cos_value_t *pcv, gs_memory_t *mem)
+{
+ if (!pcv->is_object)
+ gs_free_string(mem, pcv->contents.chars.data, pcv->contents.chars.size,
+ "cos_uncopy_element_value");
+}
- sname.data = left;
- sname.size = right - left;
- pdfmark_find_named(pdev, &sname, ppno, false);
- }
- return right;
+/* ---------------- Specific object types ---------------- */
+
+/* ------ Generic objects ------ */
+
+private cos_proc_release(cos_generic_release);
+private cos_proc_write(cos_generic_write);
+const cos_object_procs_t cos_generic_procs = {
+ cos_generic_release, cos_generic_write
+};
+
+cos_object_t *
+cos_object_alloc(gs_memory_t *mem, client_name_t cname)
+{
+ cos_object_t *pco =
+ gs_alloc_struct(mem, cos_object_t, &st_cos_object, cname);
+
+ cos_object_init(pco, &cos_generic_procs);
+ return pco;
}
-int
-pdfmark_replace_names(gx_device_pdf * pdev, const gs_param_string * from,
- gs_param_string * to)
-{
- const byte *start = from->data;
- const byte *end = start + from->size;
- const byte *scan;
- uint size = 0;
- pdf_named_object *pno;
- bool any = false;
- byte *sto;
- char ref[1 + 10 + 5 + 1]; /* max obj number is 10 digits */
-
- /* Do a first pass to compute the length of the result. */
- for (scan = start; scan < end;) {
- const byte *sname;
- const byte *next =
- pdfmark_next_object(scan, end, &sname, &pno, pdev);
-
- size += sname - scan;
- if (pno) {
- sprintf(ref, " %ld 0 R ", pno->id);
- size += strlen(ref);
- }
- scan = next;
- any |= next != sname;
- }
- to->persistent = true; /* ??? */
- if (!any) {
- to->data = start;
- to->size = size;
- return 0;
- }
- sto = gs_alloc_bytes(pdev->pdf_memory, size,
- "pdfmark_replace_names");
- if (sto == 0)
- return_error(gs_error_VMerror);
- to->data = sto;
- to->size = size;
- /* Do a second pass to do the actual substitutions. */
- for (scan = start; scan < end;) {
- const byte *sname;
- const byte *next =
- pdfmark_next_object(scan, end, &sname, &pno, pdev);
- uint copy = sname - scan;
- int rlen;
-
- memcpy(sto, scan, copy);
- sto += copy;
- if (pno) {
- sprintf(ref, " %ld 0 R ", pno->id);
- rlen = strlen(ref);
- memcpy(sto, ref, rlen);
- sto += rlen;
- }
- scan = next;
- }
- return 0;
+
+private void
+cos_generic_release(cos_object_t *pco, gs_memory_t *mem, client_name_t cname)
+{
+ /* Do nothing. */
}
-/* Write and free an entire list of named objects. */
-int
-pdfmark_write_and_free_named(gx_device_pdf * pdev, pdf_named_object ** ppno)
+private int
+cos_generic_write(const cos_object_t *pco, gx_device_pdf *pdev)
{
- pdf_named_object *pno = *ppno;
- pdf_named_object *next;
+ return_error(gs_error_Fatal);
+}
- for (; pno; pno = next) {
- next = pno->next;
- pdfmark_write_named(pdev, pno);
- pdfmark_free_named(pdev, pno);
- }
- *ppno = 0;
- return 0;
+/* ------ Arrays ------ */
+
+private cos_proc_release(cos_array_release);
+private cos_proc_write(cos_array_write);
+const cos_object_procs_t cos_array_procs = {
+ cos_array_release, cos_array_write
+};
+
+cos_array_t *
+cos_array_alloc(gs_memory_t *mem, client_name_t cname)
+{
+ cos_array_t *pca =
+ gs_alloc_struct(mem, cos_array_t, &st_cos_object, cname);
+
+ cos_object_init((cos_object_t *)pca, &cos_array_procs);
+ return pca;
}
-/* ------ Private ------ */
+private void
+cos_array_release(cos_object_t *pco, gs_memory_t *mem, client_name_t cname)
+{
+ cos_array_t *const pca = (cos_array_t *)pco;
+ cos_array_element_t *cur;
+ cos_array_element_t *next;
+
+ for (cur = pca->elements; cur; cur = next) {
+ next = cur->next;
+ cos_value_free(&cur->value, mem, cname);
+ gs_free_object(mem, cur, cname);
+ }
+ pca->elements = 0;
+}
-/* Put an element of an array object. */
private int
-pdf_named_array_put(gx_device_pdf * pdev, pdf_named_object * pno, int index,
- const gs_param_string * pvalue)
+cos_array_write(const cos_object_t *pco, gx_device_pdf *pdev)
{
- gs_memory_t *mem = pdev->pdf_memory;
- pdf_named_element **ppne = &pno->elements;
- pdf_named_element *pne;
- pdf_named_element *pnext;
- gs_string value;
-
- while ((pnext = *ppne) != 0 && pnext->key.size > index)
- ppne = &pnext->next;
- value.data = gs_alloc_string(mem, pvalue->size, "named array value");
- if (value.data == 0)
- return_error(gs_error_VMerror);
- value.size = pvalue->size;
- if (pnext && pnext->key.size == index) {
- /* We're replacing an existing element. */
- gs_free_string(mem, pnext->value.data, pnext->value.size,
- "named array old value");
- pne = pnext;
- } else {
- /* Create a new element. */
- pne = gs_alloc_struct(mem, pdf_named_element, &st_pdf_named_element,
- "named array element");
- if (pne == 0) {
- gs_free_string(mem, value.data, value.size, "named array value");
- return_error(gs_error_VMerror);
- }
- pne->key.data = 0;
- pne->key.size = index;
- pne->next = pnext;
- *ppne = pne;
+ stream *s = pdev->strm;
+ const cos_array_t *const pca = (const cos_array_t *)pco;
+ cos_array_element_t *last;
+ cos_array_element_t *next;
+ cos_array_element_t *pcae;
+ uint last_index = 0;
+
+ pputs(s, "[");
+ /* Reverse the elements temporarily. */
+ for (pcae = pca->elements, last = NULL; pcae; pcae = next)
+ next = pcae->next, pcae->next = last, last = pcae;
+ for (pcae = last; pcae; ++last_index, pcae = pcae->next) {
+ for (; pcae->index > last_index; ++last_index)
+ pputs(s, "null\n");
+ cos_value_write(&pcae->value, pdev);
+ pputc(s, '\n');
}
- memcpy(value.data, pvalue->data, value.size);
- pne->value = value;
+ /* Reverse the elements back. */
+ for (pcae = last, last = NULL; pcae; pcae = next)
+ next = pcae->next, pcae->next = last, last = pcae;
+ pputs(s, "]");
return 0;
}
-/* Put an element of a dictionary object. */
-private int
-pdf_named_dict_put(gx_device_pdf * pdev, pdf_named_object * pno,
- const gs_param_string * pkey, const gs_param_string * pvalue)
+/* Put/add an element in/to an array. */
+int
+cos_array_put(cos_array_t *pca, gx_device_pdf *pdev, long index,
+ const cos_value_t *pvalue)
{
gs_memory_t *mem = pdev->pdf_memory;
- pdf_named_element **ppne = &pno->elements;
- pdf_named_element *pne;
- pdf_named_element *pnext;
- gs_string value;
-
- while ((pnext = *ppne) != 0 &&
- bytes_compare(pnext->key.data, pnext->key.size,
- pkey->data, pkey->size)
- )
- ppne = &pnext->next;
- value.data = gs_alloc_string(mem, pvalue->size, "named dict value");
- if (value.data == 0)
- return_error(gs_error_VMerror);
- value.size = pvalue->size;
- if (pnext) {
+ cos_array_element_t **ppcae = &pca->elements;
+ cos_array_element_t *pcae;
+ cos_array_element_t *next;
+ cos_value_t value;
+ int code;
+
+ code = cos_copy_element_value(&value, mem, pvalue);
+ if (code < 0)
+ return code;
+ while ((next = *ppcae) != 0 && next->index > index)
+ ppcae = &next->next;
+ if (next && next->index == index) {
/* We're replacing an existing element. */
- gs_free_string(mem, pnext->value.data, pnext->value.size,
- "named array old value");
- pne = pnext;
+ cos_value_free(&next->value, mem, "cos_array_put(old value)");
+ pcae = next;
} else {
/* Create a new element. */
- gs_string key;
-
- key.data = gs_alloc_string(mem, pkey->size, "named dict key");
- key.size = pkey->size;
- pne = gs_alloc_struct(mem, pdf_named_element, &st_pdf_named_element,
- "named dict element");
- if (key.data == 0 || pne == 0) {
- gs_free_object(mem, pne, "named dict element");
- if (key.data)
- gs_free_string(mem, key.data, key.size, "named dict key");
- gs_free_string(mem, value.data, value.size, "named dict value");
+ pcae = gs_alloc_struct(mem, cos_array_element_t, &st_cos_array_element,
+ "cos_array_put(element)");
+ if (pcae == 0) {
+ gs_free_object(mem, pcae, "cos_array_put(element)");
+ cos_uncopy_element_value(&value, mem);
return_error(gs_error_VMerror);
}
- pne->key = key;
- memcpy(key.data, pkey->data, key.size);
- pne->next = pnext;
- *ppne = pne;
+ pcae->index = index;
+ pcae->next = next;
+ *ppcae = pcae;
}
- memcpy(value.data, pvalue->data, value.size);
- pne->value = value;
+ pcae->value = value;
return 0;
}
-
-/* Write out the definition of a named object. */
-private pdf_named_element *
-pdf_reverse_elements(pdf_named_element * pne)
+int
+cos_array_add(cos_array_t *pca, gx_device_pdf *pdev, const cos_value_t *pvalue)
{
- pdf_named_element *prev = NULL;
- pdf_named_element *next;
-
- for (; pne; pne = next)
- next = pne->next, pne->next = prev, prev = pne;
- return prev;
+ return cos_array_put(pca, pdev,
+ (pca->elements ? pca->elements->index + 1 : 0L),
+ pvalue);
}
-private int
-pdfmark_write_named(gx_device_pdf * pdev, const pdf_named_object * pno)
+
+/* ------ Dictionaries ------ */
+
+private cos_proc_release(cos_dict_release);
+private cos_proc_write(cos_dict_write);
+const cos_object_procs_t cos_dict_procs = {
+ cos_dict_release, cos_dict_write
+};
+
+cos_dict_t *
+cos_dict_alloc(gs_memory_t *mem, client_name_t cname)
{
- stream *s = pdev->strm;
- pdf_named_element *pne = pno->elements;
-
- switch (pno->type) {
- case named_array:{
- uint last_index = 0;
- pdf_named_element *last = pne = pdf_reverse_elements(pne);
-
- pdf_open_obj(pdev, pno->id);
- pputs(s, "[");
- for (; pne; ++last_index, pne = pne->next) {
- for (; pne->key.size > last_index; ++last_index)
- pputs(s, "null\n");
- pdf_put_value(pdev, pne->value.data, pne->value.size);
- pputc(s, '\n');
- }
- pdf_reverse_elements(last);
- pputs(s, "]");
- }
- break;
- case named_dict:
- pdf_open_obj(pdev, pno->id);
- pputs(s, "<<");
- for (; pne; pne = pne->next) {
- pdf_put_value(pdev, pne->key.data, pne->key.size);
- pputc(s, ' ');
- pdf_put_value(pdev, pne->value.data, pne->value.size);
- pputc(s, '\n');
- }
- pputs(s, ">>");
- break;
- case named_stream:{
- pdf_named_element *last = pne = pdf_reverse_elements(pne);
-
-/****** NYI ******/
-#if 0
- pdf_open_stream(pdev, pno->id);
-/****** DOESN'T EXIST ******/
- for (; pne; pne = pne->next)
- pwrite(s, pne->value.data, pne->value.size);
- pdf_close_stream(pdev);
-/****** DITTO ******/
-#endif
- pdf_reverse_elements(last);
- }
- break;
-/****** WHAT TO DO WITH GRAPHICS/UNDEFINED? ******/
- default:
- return 0;
- }
- pdf_end_obj(pdev);
- return 0;
+ cos_dict_t *pcd =
+ gs_alloc_struct(mem, cos_dict_t, &st_cos_object, cname);
+
+ cos_object_init((cos_object_t *)pcd, &cos_dict_procs);
+ return pcd;
}
-/* Free the definition of a named object. */
private void
-pdfmark_free_named(gx_device_pdf * pdev, pdf_named_object * pno)
-{
- pdf_named_element *pne = pno->elements;
- pdf_named_element *next;
-
- for (; pne; pne = next) {
- next = pne->next;
- gs_free_string(pdev->pdf_memory, pne->value.data, pne->value.size,
- "named object element value");
- if (pne->key.data)
- gs_free_string(pdev->pdf_memory, pne->key.data, pne->key.size,
- "named object element key");
+cos_dict_release(cos_object_t *pco, gs_memory_t *mem, client_name_t cname)
+{
+ cos_dict_t *const pcd = (cos_dict_t *)pco;
+ cos_dict_element_t *cur;
+ cos_dict_element_t *next;
+
+ for (cur = pcd->elements; cur; cur = next) {
+ next = cur->next;
+ cos_value_free(&cur->value, mem, cname);
+ gs_free_string(mem, cur->key.data, cur->key.size, cname);
+ gs_free_object(mem, cur, cname);
}
- gs_free_string(pdev->pdf_memory, pno->key.data, pno->key.size,
- "named object key");
- gs_free_object(pdev->pdf_memory, pno, "named object");
+ pcd->elements = 0;
}
-/* ---------------- Individual pdfmarks ---------------- */
-
-/* [ /BBox [llx lly urx ury] /_objdef {obj} /BP pdfmark */
+/* Write the elements of a dictionary. (This procedure is exported.) */
private int
-pdfmark_BP(gx_device_pdf * pdev, gs_param_string * pairs, uint count,
- const gs_matrix * pctm, const gs_param_string * objname)
+cos_elements_write(stream *s, const cos_dict_element_t *pcde,
+ gx_device_pdf *pdev)
{
- gs_rect bbox;
- pdf_named_object *pno;
- int code;
-
- if (objname == 0 || count != 2 || !pdf_key_eq(&pairs[0], "BBox"))
- return_error(gs_error_rangecheck);
- if (sscanf((const char *)pairs[1].data, "[%lg %lg %lg %lg]",
- &bbox.p.x, &bbox.p.y, &bbox.q.x, &bbox.q.y) != 4
- )
- return_error(gs_error_rangecheck);
- code = pdfmark_find_named(pdev, objname, &pno, true);
- if (code < 0)
- return code;
- if (pno->type != named_unknown)
- return_error(gs_error_rangecheck);
- code = pdf_named_dict_put(pdev, pno, &pairs[0], &pairs[1]);
- if (code < 0)
- return code;
- pno->type = named_graphics;
- pno->graphics.enclosing = pdev->open_graphics;
- pdev->open_graphics = pno;
-/****** NYI ******/
+ /* Temporarily replace the output stream in pdev. */
+ stream *save = pdev->strm;
+
+ pdev->strm = s;
+ for (; pcde; pcde = pcde->next) {
+ pdf_write_value(pdev, pcde->key.data, pcde->key.size);
+ pputc(s, ' ');
+ cos_value_write(&pcde->value, pdev);
+ pputc(s, '\n');
+ }
+ pdev->strm = save;
return 0;
}
+int
+cos_dict_elements_write(const cos_dict_t *pcd, gx_device_pdf *pdev)
+{
+ return cos_elements_write(pdev->strm, pcd->elements, pdev);
+}
-/* [ /EP pdfmark */
private int
-pdfmark_EP(gx_device_pdf * pdev, gs_param_string * pairs, uint count,
- const gs_matrix * pctm, const gs_param_string * no_objname)
-{
- pdf_named_object *pno = pdev->open_graphics;
-
- if (count != 0 || pno == 0 || pno->type != named_graphics ||
- !pno->open
- )
- return_error(gs_error_rangecheck);
- pno->open = false;
- pdev->open_graphics = pno->graphics.enclosing;
-/****** NYI ******/
+cos_dict_write(const cos_object_t *pco, gx_device_pdf *pdev)
+{
+ stream *s = pdev->strm;
+
+ pputs(s, "<<");
+ cos_dict_elements_write((const cos_dict_t *)pco, pdev);
+ pputs(s, ">>");
return 0;
}
-/* [ {obj} /SP pdfmark */
-private int
-pdfmark_SP(gx_device_pdf * pdev, gs_param_string * pairs, uint count,
- const gs_matrix * pctm, const gs_param_string * no_objname)
+/* Put an element in a dictionary. */
+int
+cos_dict_put(cos_dict_t *pcd, gx_device_pdf *pdev, const byte *key_data,
+ uint key_size, const cos_value_t *pvalue)
{
- pdf_named_object *pno;
+ gs_memory_t *mem = pdev->pdf_memory;
+ cos_dict_element_t **ppcde = &pcd->elements;
+ cos_dict_element_t *pcde;
+ cos_dict_element_t *next;
+ cos_value_t value;
int code;
- if (count != 1)
- return_error(gs_error_rangecheck);
- if ((code = pdfmark_find_named(pdev, &pairs[0], &pno, false)) < 0)
- return code;
- if (pno->type != named_graphics || pno->open)
- return_error(gs_error_rangecheck);
- code = pdf_open_contents(pdev, pdf_in_stream);
+ code = cos_copy_element_value(&value, mem, pvalue);
if (code < 0)
return code;
- pdf_put_matrix(pdev, "q ", pctm, "cm\n");
- pprintld1(pdev->strm, "/R%ld Do Q\n", pno->id);
+ while ((next = *ppcde) != 0 &&
+ bytes_compare(next->key.data, next->key.size, key_data, key_size)
+ )
+ ppcde = &next->next;
+ if (next) {
+ /* We're replacing an existing element. */
+ cos_value_free(&next->value, mem, "cos_dict_put(old value)");
+ pcde = next;
+ } else {
+ /* Create a new element. */
+ byte *copied_key_data;
+
+ copied_key_data = gs_alloc_string(mem, key_size, "cos_dict_put(key)");
+ pcde = gs_alloc_struct(mem, cos_dict_element_t, &st_cos_dict_element,
+ "cos_dict_put(element)");
+ if (copied_key_data == 0 || pcde == 0) {
+ gs_free_object(mem, pcde, "cos_dict_put(element)");
+ if (copied_key_data)
+ gs_free_string(mem, copied_key_data, key_size,
+ "cos_dict_put(key)");
+ cos_uncopy_element_value(&value, mem);
+ return_error(gs_error_VMerror);
+ }
+ pcde->key.data = copied_key_data;
+ pcde->key.size = key_size;
+ memcpy(copied_key_data, key_data, key_size);
+ pcde->next = next;
+ *ppcde = pcde;
+ }
+ pcde->value = value;
return 0;
}
+int
+cos_dict_put_string(cos_dict_t *pcd, gx_device_pdf *pdev, const byte *key_data,
+ uint key_size, const byte *value_data, uint value_size)
+{
+ cos_value_t cvalue;
-/* [ /_objdef {array} /type /array /OBJ pdfmark */
-/* [ /_objdef {dict} /type /dict /OBJ pdfmark */
-/* [ /_objdef {stream} /type /stream /OBJ pdfmark */
-private int
-pdfmark_OBJ(gx_device_pdf * pdev, gs_param_string * pairs, uint count,
- const gs_matrix * pctm, const gs_param_string * objname)
+ return cos_dict_put(pcd, pdev, key_data, key_size,
+ cos_string_value(&cvalue, value_data, value_size));
+}
+int
+cos_dict_put_c_strings(cos_dict_t *pcd, gx_device_pdf *pdev,
+ const char *key, const char *value)
{
- pdf_named_object_type type;
- pdf_named_object *pno;
- int code;
+ cos_value_t cvalue;
- if (objname == 0 || count != 2 || !pdf_key_eq(&pairs[0], "type"))
- return_error(gs_error_rangecheck);
- if (pdf_key_eq(&pairs[1], "/array"))
- type = named_array;
- else if (pdf_key_eq(&pairs[1], "/dict"))
- type = named_dict;
- else if (pdf_key_eq(&pairs[1], "/stream"))
- type = named_stream;
- else
- return_error(gs_error_rangecheck);
- if ((code = pdfmark_find_named(pdev, objname, &pno, true)) < 0)
- return code;
- if (pno->type != named_unknown)
- return_error(gs_error_rangecheck);
- pno->type = type;
+ return cos_dict_put(pcd, pdev, (const byte *)key, strlen(key),
+ cos_c_string_value(&cvalue, value));
+}
+
+/* Look up a key in a dictionary. */
+const cos_value_t *
+cos_dict_find(const cos_dict_t *pcd, const byte *key_data, uint key_size)
+{
+ cos_dict_element_t *pcde = pcd->elements;
+
+ for (; pcde; pcde = pcde->next)
+ if (!bytes_compare(key_data, key_size, pcde->key.data, pcde->key.size))
+ return &pcde->value;
return 0;
}
-/* [ {array} index value /PUT pdfmark */
-/* [ {stream} string|file /PUT pdfmark */
-/* Dictionaries are converted to .PUTDICT */
-private int
-pdfmark_PUT(gx_device_pdf * pdev, gs_param_string * pairs, uint count,
- const gs_matrix * pctm, const gs_param_string * no_objname)
+/* ------ Streams ------ */
+
+private cos_proc_release(cos_stream_release);
+private cos_proc_write(cos_stream_write);
+const cos_object_procs_t cos_stream_procs = {
+ cos_stream_release, cos_stream_write
+};
+
+cos_stream_t *
+cos_stream_alloc(gs_memory_t *mem, client_name_t cname)
{
- pdf_named_object *pno;
- int code;
+ cos_stream_t *pcs =
+ gs_alloc_struct(mem, cos_stream_t, &st_cos_object, cname);
- if ((code = pdfmark_find_named(pdev, &pairs[0], &pno, false)) < 0)
- return code;
- switch (pno->type) {
- case named_array:{
- int index;
-
- if (count != 3)
- return_error(gs_error_rangecheck);
- if ((code = pdfmark_scan_int(&pairs[1], &index)) < 0)
- return code;
- if (index < 0)
- return_error(gs_error_rangecheck);
- code = pdf_named_array_put(pdev, pno, index, pairs + 2);
- break;
- }
- case named_stream:
- if (count != 2)
- return_error(gs_error_rangecheck);
-/****** NYI ******/
- break;
- default:
- return_error(gs_error_rangecheck);
- }
- return code;
+ cos_object_init((cos_object_t *)pcs, &cos_stream_procs);
+ return pcs;
}
-/* [ {dict} key value ... /.PUTDICT pdfmark */
-private int
-pdfmark_PUTDICT(gx_device_pdf * pdev, gs_param_string * pairs, uint count,
- const gs_matrix * pctm, const gs_param_string * no_objname)
+private void
+cos_stream_release(cos_object_t *pco, gs_memory_t *mem, client_name_t cname)
{
- pdf_named_object *pno;
- int code, i;
+ cos_stream_t *const pcs = (cos_stream_t *)pco;
+ cos_stream_piece_t *cur;
+ cos_stream_piece_t *next;
- if ((code = pdfmark_find_named(pdev, &pairs[0], &pno, false)) < 0)
- return code;
- if (!(count & 1) || pno->type != named_dict)
- return_error(gs_error_rangecheck);
- for (i = 1; code >= 0 && i < count; i += 2)
- code = pdf_named_dict_put(pdev, pno, pairs + i, pairs + i + 1);
- return code;
+ for (cur = pcs->pieces; cur; cur = next) {
+ next = cur->next;
+ gs_free_object(mem, cur, cname);
+ }
+ pcs->pieces = 0;
+ cos_dict_release(pco, mem, cname);
+}
+
+/* Write the (dictionary) elements of a stream. */
+/* (This procedure is exported.) */
+int
+cos_stream_elements_write(const cos_stream_t *pcs, gx_device_pdf *pdev)
+{
+ return cos_elements_write(pdev->strm, pcs->elements, pdev);
}
-/* [ {array} index value ... /.PUTINTERVAL pdfmark */
private int
-pdfmark_PUTINTERVAL(gx_device_pdf * pdev, gs_param_string * pairs, uint count,
- const gs_matrix * pctm, const gs_param_string * no_objname)
+cos_stream_write(const cos_object_t *pco, gx_device_pdf *pdev)
{
- pdf_named_object *pno;
- int code, index, i;
+ stream *s = pdev->strm;
+ const cos_stream_t *const pcs = (const cos_stream_t *)pco;
+ cos_stream_piece_t *last;
+ cos_stream_piece_t *next;
+ cos_stream_piece_t *pcsp = pcs->pieces;
+ FILE *sfile = pdev->streams.file;
+ long end_pos;
+ long length;
+ int code;
- if ((code = pdfmark_find_named(pdev, &pairs[0], &pno, false)) < 0)
- return code;
- if (count < 2 || pno->type != named_array)
- return_error(gs_error_rangecheck);
- if ((code = pdfmark_scan_int(&pairs[1], &index)) < 0)
- return code;
- if (index < 0)
- return_error(gs_error_rangecheck);
- for (i = 2; code >= 0 && i < count; ++i)
- code = pdf_named_array_put(pdev, pno, index + i - 2, &pairs[i]);
+ /****** DOESN'T ENCODE OR COMPRESS YET ******/
+
+ sflush(pdev->streams.strm);
+ end_pos = ftell(sfile);
+
+ /* Do a first pass to calculate the length. */
+ {
+ stream poss;
+
+ swrite_position_only(&poss);
+ for (length = stell(&poss); pcsp; pcsp = pcsp->next)
+ length += pcsp->size;
+ }
+
+ /* Now write the stream. */
+ pputs(s, "<<");
+ cos_elements_write(s, pcs->elements, pdev);
+ pprintld1(s, "/Length %ld>>stream\n", length);
+ /* Reverse the elements temporarily. */
+ for (pcsp = pcs->pieces, last = NULL; pcsp; pcsp = next)
+ next = pcsp->next, pcsp->next = last, last = pcsp;
+ for (pcsp = last, code = 0; pcsp && code >= 0; pcsp = pcsp->next) {
+ fseek(sfile, pcsp->position, SEEK_SET);
+ pdf_copy_data(s, sfile, pcsp->size);
+ }
+ /* Reverse the elements back. */
+ for (pcsp = last, last = NULL; pcsp; pcsp = next)
+ next = pcsp->next, pcsp->next = last, last = pcsp;
+ pputs(s, "endstream\n");
+
+ fseek(sfile, end_pos, SEEK_SET);
return code;
}
-/* [ {stream} /CLOSE pdfmark */
-private int
-pdfmark_CLOSE(gx_device_pdf * pdev, gs_param_string * pairs, uint count,
- const gs_matrix * pctm, const gs_param_string * no_objname)
+/* Put an element in a stream's dictionary. */
+int
+cos_stream_put(cos_stream_t *pcs, gx_device_pdf *pdev, const byte *key_data,
+ uint key_size, const cos_value_t *pvalue)
{
- pdf_named_object *pno;
- int code;
+ return cos_dict_put((cos_dict_t *)pcs, pdev, key_data, key_size, pvalue);
+}
+int
+cos_stream_put_c_strings(cos_stream_t *pcs, gx_device_pdf *pdev,
+ const char *key, const char *value)
+{
+ return cos_dict_put_c_strings((cos_dict_t *)pcs, pdev, key, value);
+}
- if (count != 1)
- return_error(gs_error_rangecheck);
- if ((code = pdfmark_find_named(pdev, &pairs[0], &pno, false)) < 0)
- return code;
- if (pno->type != named_stream || !pno->open)
- return_error(gs_error_rangecheck);
- /* Currently we don't do anything special when closing a stream. */
- pno->open = false;
+/* Add a contents piece to a stream object: size bytes just written on */
+/* streams.strm. */
+int
+cos_stream_add(cos_stream_t *pcs, gx_device_pdf * pdev, uint size)
+{
+ stream *s = pdev->streams.strm;
+ long position = stell(s);
+ cos_stream_piece_t *prev = pcs->pieces;
+
+ /* Check for consecutive writing -- just an optimization. */
+ if (prev != 0 && prev->position + prev->size + size == position) {
+ prev->size += size;
+ } else {
+ gs_memory_t *mem = pdev->pdf_memory;
+ cos_stream_piece_t *pcsp =
+ gs_alloc_struct(mem, cos_stream_piece_t, &st_cos_stream_piece,
+ "cos_stream_add");
+
+ if (pcsp == 0)
+ return_error(gs_error_VMerror);
+ pcsp->position = position - size;
+ pcsp->size = size;
+ pcsp->next = pcs->pieces;
+ pcs->pieces = pcsp;
+ }
return 0;
}
+
+/* Add bytes to a stream object. */
+int
+cos_stream_add_bytes(cos_stream_t *pcs, gx_device_pdf * pdev,
+ const byte *data, uint size)
+{
+ pwrite(pdev->streams.strm, data, size);
+ return cos_stream_add(pcs, pdev, size);
+}
diff --git a/gs/src/gdevpdfo.h b/gs/src/gdevpdfo.h
new file mode 100644
index 000000000..bd124c10d
--- /dev/null
+++ b/gs/src/gdevpdfo.h
@@ -0,0 +1,235 @@
+/* Copyright (C) 1999 Aladdin Enterprises. All rights reserved.
+
+ This file is part of Aladdin Ghostscript.
+
+ Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
+ or distributor accepts any responsibility for the consequences of using it,
+ or for whether it serves any particular purpose or works at all, unless he
+ or she says so in writing. Refer to the Aladdin Ghostscript Free Public
+ License (the "License") for full details.
+
+ Every copy of Aladdin Ghostscript must include a copy of the License,
+ normally in a plain ASCII text file named PUBLIC. The License grants you
+ the right to copy, modify and redistribute Aladdin Ghostscript, but only
+ under certain conditions described in the License. Among other things, the
+ License requires that the copyright notice and this notice be preserved on
+ all copies.
+ */
+
+
+/* Internal definitions for "objects" for pdfwrite driver. */
+
+#ifndef gdevpdfo_INCLUDED
+# define gdevpdfo_INCLUDED
+
+/*
+ * This file defines the structures and support procedures for what Adobe
+ * calls "Cos objects". (We don't know what "Cos" stands for, but in our
+ * case, it's a good acronym for "Collection and stream".) We only
+ * support arrays, dictionaries, and streams: we merge all other types into a
+ * single string type, which holds the printed representation that will be
+ * written on the output file, and we only support that type as an element
+ * of the collection types.
+ *
+ * Note that Cos objects are *not* reference-counted. Objects without
+ * an ID are assumed to be referenced from only one place; objects with
+ * IDs are managed manually. We also assume that strings (the keys of
+ * dictionaries, and the values in arrays and dictionaries) are "owned"
+ * by their referencing object.
+ */
+
+/* Define some needed abstract types. */
+#ifndef gx_device_pdf_DEFINED
+# define gx_device_pdf_DEFINED
+typedef struct gx_device_pdf_s gx_device_pdf;
+#endif
+
+/* ---------------- Structures ---------------- */
+
+/*
+ * Define the generic structure for elements of arrays and
+ * dictionaries/streams.
+ */
+#define cos_element_common(etype)\
+ etype *next
+typedef struct cos_element_s cos_element_t;
+struct cos_element_s {
+ cos_element_common(cos_element_t);
+};
+#define private_st_cos_element() /* in gdevpdfo.c */\
+ gs_private_st_ptrs1(st_cos_element, cos_element_t, "cos_element_t",\
+ cos_element_enum_ptrs, cos_element_reloc_ptrs, next)
+#define cos_element_num_ptrs 1
+
+/*
+ * Define the structure for a piece of stream contents.
+ */
+typedef struct cos_stream_piece_s cos_stream_piece_t;
+struct cos_stream_piece_s {
+ cos_element_common(cos_stream_piece_t);
+ long position; /* in streams file */
+ uint size;
+};
+#define private_st_cos_stream_piece() /* in gdevpdfo.c */\
+ gs_private_st_suffix_add0_local(st_cos_stream_piece, cos_stream_piece_t,\
+ "cos_stream_piece_t", cos_element_enum_ptrs, cos_element_reloc_ptrs,\
+ st_cos_element)
+
+/*
+ * Define the object procedures for Cos objects.
+ */
+typedef struct cos_object_s cos_object_t;
+typedef struct cos_object_procs_s {
+
+#define cos_proc_release(proc)\
+ void proc(P3(cos_object_t *pco, gs_memory_t *mem, client_name_t cname))
+ cos_proc_release((*release));
+
+#define cos_proc_write(proc)\
+ int proc(P2(const cos_object_t *pco, gx_device_pdf *pdev))
+ cos_proc_write((*write));
+
+} cos_object_procs_t;
+typedef const cos_object_procs_t *cos_type_t;
+#define cos_type(pco) ((pco)->cos_procs)
+
+/*
+ * Define the generic structure for Cos objects. Note that all Cos
+ * objects have the same structure and type, aside from their elements.
+ * This allows us to "mutate" a forward-referenced object into its
+ * proper type in place.
+ *
+ * Note that we distinguish elements from contents. Arrays and
+ * dictionaries have only elements; streams have both elements
+ * (additional elements of the stream dictionary) and contents pieces.
+ *
+ * The is_open member currently has no function other than error checking.
+ * It is set to true when the object is created, to false by the CLOSE
+ * and EP pdfmarks, and is checked by CLOSE, PUT, and SP.
+ */
+#define cos_object_struct(otype_s, etype)\
+struct otype_s {\
+ const cos_object_procs_t *cos_procs; /* must be first */\
+ long id;\
+ etype *elements;\
+ cos_stream_piece_t *pieces;\
+ bool is_open; /* see above */\
+}
+cos_object_struct(cos_object_s, cos_element_t);
+#define private_st_cos_object() /* in gdevpdfo.c */\
+ gs_private_st_ptrs2(st_cos_object, cos_object_t, "cos_object_t",\
+ cos_object_enum_ptrs, cos_object_reloc_ptrs, elements, pieces)
+extern const cos_object_procs_t cos_generic_procs;
+#define cos_type_generic (&cos_generic_procs)
+
+/*
+ * Define the macro for casting any cos object to type cos_object_t.
+ * Using cos_procs ensures that the argument is, in fact, a cos object.
+ */
+#define COS_OBJECT(pc) ((cos_object_t *)&((pc)->cos_procs))
+#define CONST_COS_OBJECT(pc) ((const cos_object_t *)&((pc)->cos_procs))
+
+/*
+ * Define the structure for the value of an array or dictionary element.
+ * This is where we create the union of composite and scalar types.
+ */
+typedef struct cos_value_s {
+ bool is_object;
+ union vc_ {
+ cos_object_t *object; /* is_object = true */
+ gs_string chars; /* is_object = false */
+ } contents;
+} cos_value_t;
+#define private_st_cos_value() /* in gdevpdfo.c */\
+ gs_private_st_composite(st_cos_value, cos_value_t,\
+ "cos_value_t", cos_value_enum_ptrs, cos_value_reloc_ptrs)
+
+/*
+ * Define Cos arrays, dictionaries, and streams.
+ *
+ * The elements of arrays are stored sorted in decreasing index order.
+ * The elements of dictionaries/streams are not sorted.
+ * The contents pieces of streams are stored in reverse order.
+ */
+ /* array */
+typedef struct cos_array_element_s cos_array_element_t;
+struct cos_array_element_s {
+ cos_element_common(cos_array_element_t);
+ long index;
+ cos_value_t value;
+};
+#define private_st_cos_array_element() /* in gdevpdfo.c */\
+ gs_private_st_composite(st_cos_array_element, cos_array_element_t,\
+ "cos_array_element_t", cos_array_element_enum_ptrs, cos_array_element_reloc_ptrs)
+typedef cos_object_struct(cos_array_s, cos_array_element_t) cos_array_t;
+extern const cos_object_procs_t cos_array_procs;
+#define cos_type_array (&cos_array_procs)
+ /* dict */
+typedef struct cos_dict_element_s cos_dict_element_t;
+struct cos_dict_element_s {
+ cos_element_common(cos_dict_element_t);
+ gs_string key;
+ cos_value_t value;
+};
+#define private_st_cos_dict_element() /* in gdevpdfo.c */\
+ gs_private_st_composite(st_cos_dict_element, cos_dict_element_t,\
+ "cos_dict_element_t", cos_dict_element_enum_ptrs, cos_dict_element_reloc_ptrs)
+typedef cos_object_struct(cos_dict_s, cos_dict_element_t) cos_dict_t;
+extern const cos_object_procs_t cos_dict_procs;
+#define cos_type_dict (&cos_dict_procs)
+ /* stream */
+typedef cos_object_struct(cos_stream_s, cos_dict_element_t) cos_stream_t;
+extern const cos_object_procs_t cos_stream_procs;
+#define cos_type_stream (&cos_stream_procs)
+
+/* ---------------- Procedures ---------------- */
+
+/* Create a Cos object. */
+cos_object_t *cos_object_alloc(P2(gs_memory_t *, client_name_t));
+cos_array_t *cos_array_alloc(P2(gs_memory_t *, client_name_t));
+cos_dict_t *cos_dict_alloc(P2(gs_memory_t *, client_name_t));
+cos_stream_t *cos_stream_alloc(P2(gs_memory_t *, client_name_t));
+int cos_become(P2(cos_object_t *, cos_type_t));
+
+/* Define wrappers for calling the object procedures. */
+cos_proc_release(cos_release);
+#define COS_RELEASE(pc, mem, cname) cos_release(COS_OBJECT(pc), mem, cname)
+cos_proc_write(cos_write);
+#define COS_WRITE(pc, pdev) cos_write(CONST_COS_OBJECT(pc), pdev)
+
+/* Make a value to store into a composite object. */
+const cos_value_t *cos_string_value(P3(cos_value_t *, const byte *, uint));
+const cos_value_t *cos_c_string_value(P2(cos_value_t *, const char *));
+const cos_value_t *cos_object_value(P2(cos_value_t *, cos_object_t *));
+#define COS_OBJECT_VALUE(pcv, pc) cos_object_value(pcv, COS_OBJECT(pc))
+
+/* Put an element in / add an element to a Cos object. */
+ /* array */
+int cos_array_put(P4(cos_array_t *, gx_device_pdf *, long, const cos_value_t *));
+int cos_array_add(P3(cos_array_t *, gx_device_pdf *, const cos_value_t *));
+ /* dict */
+int cos_dict_put(P5(cos_dict_t *, gx_device_pdf *, const byte *, uint, const cos_value_t *));
+int cos_dict_put_string(P6(cos_dict_t *, gx_device_pdf *, const byte *, uint, const byte *, uint));
+int cos_dict_put_c_strings(P4(cos_dict_t *, gx_device_pdf *, const char *, const char *));
+ /* stream */
+int cos_stream_add(P3(cos_stream_t *, gx_device_pdf *, uint));
+int cos_stream_add_bytes(P4(cos_stream_t *, gx_device_pdf *, const byte *, uint));
+int cos_stream_put(P5(cos_stream_t *, gx_device_pdf *, const byte *, uint, const cos_value_t *)); /* = dict_put */
+int cos_stream_put_c_strings(P4(cos_stream_t *, gx_device_pdf *, const char *, const char *)); /* = dict_put_c_strings */
+
+/* Look up a key in a dictionary. */
+const cos_value_t *cos_dict_find(P3(const cos_dict_t *, const byte *, uint));
+
+/* Write the elements of a dictionary/stream on the output. */
+int cos_dict_elements_write(P2(const cos_dict_t *, gx_device_pdf *));
+int cos_stream_elements_write(P2(const cos_stream_t *, gx_device_pdf *)); /* = dict_elements_write */
+
+/* Write a cos object as a PDF object. */
+int cos_write_object(P2(const cos_object_t *pco, gx_device_pdf *pdev));
+#define COS_WRITE_OBJECT(pc, pdev) cos_write_object(CONST_COS_OBJECT(pc), pdev)
+
+/* Free a cos object. */
+void cos_free(P3(cos_object_t *pco, gs_memory_t *mem, client_name_t cname));
+#define COS_FREE(pc, mem, cname) cos_free(COS_OBJECT(pc), mem, cname)
+
+#endif /* gdevpdfo_INCLUDED */
diff --git a/gs/src/gdevpdfp.c b/gs/src/gdevpdfp.c
index 000de4c3a..7b1313afe 100644
--- a/gs/src/gdevpdfp.c
+++ b/gs/src/gdevpdfp.c
@@ -34,7 +34,6 @@
* Their "value" is an array of strings, some of which may be the result
* of converting arbitrary PostScript objects to string form.
* pdfmark - see gdevpdfm.c
- * show - see gdevpdft.c
*/
private const int CoreDistVersion = 3000; /* Distiller 3.0 */
@@ -80,30 +79,11 @@ gdev_pdf_put_params(gx_device * dev, gs_param_list * plist)
psdf_version save_version = pdev->version;
/*
- * If this is one of the pseudo-parameters (show or pdfmark),
+ * If this is a pseudo-parameter (show or pdfmark),
* don't bother checking for any real ones.
*/
{
- gs_param_string pps;
-
- code = param_read_string(plist, (param_name = "show"), &pps);
- switch (code) {
- case 0:
- pdf_open_document(pdev);
- code = pdfshow_process(pdev, plist, &pps);
- if (code >= 0)
- return code;
- /* falls through for errors */
- default:
- param_signal_error(plist, param_name, code);
- return code;
- case 1:
- break;
- }
- }
-
- {
gs_param_string_array ppa;
code = param_read_string_array(plist, (param_name = "pdfmark"), &ppa);
@@ -186,8 +166,8 @@ gdev_pdf_put_params(gx_device * dev, gs_param_list * plist)
pdev->ReEncodeCharacters = rec;
if (fon != pdev->FirstObjectNumber) {
pdev->FirstObjectNumber = fon;
- if (pdev->tfile != 0) {
- fseek(pdev->tfile, 0L, SEEK_SET);
+ if (pdev->xref.file != 0) {
+ fseek(pdev->xref.file, 0L, SEEK_SET);
pdf_initialize_ids(pdev);
}
}
diff --git a/gs/src/gdevpdfr.c b/gs/src/gdevpdfr.c
new file mode 100644
index 000000000..3ad08875d
--- /dev/null
+++ b/gs/src/gdevpdfr.c
@@ -0,0 +1,425 @@
+/* Copyright (C) 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
+
+ This file is part of Aladdin Ghostscript.
+
+ Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
+ or distributor accepts any responsibility for the consequences of using it,
+ or for whether it serves any particular purpose or works at all, unless he
+ or she says so in writing. Refer to the Aladdin Ghostscript Free Public
+ License (the "License") for full details.
+
+ Every copy of Aladdin Ghostscript must include a copy of the License,
+ normally in a plain ASCII text file named PUBLIC. The License grants you
+ the right to copy, modify and redistribute Aladdin Ghostscript, but only
+ under certain conditions described in the License. Among other things, the
+ License requires that the copyright notice and this notice be preserved on
+ all copies.
+ */
+
+
+/* Named object pdfmark processing */
+#include "memory_.h"
+#include "string_.h"
+#include "gx.h"
+#include "gserrors.h"
+#include "gsutil.h" /* for bytes_compare */
+#include "gdevpdfx.h"
+#include "scanchar.h"
+#include "strimpl.h"
+#include "sstring.h"
+
+#ifndef gs_error_syntaxerror
+# define gs_error_syntaxerror gs_error_rangecheck
+#endif
+
+/* Test whether an object name has valid syntax, {name}. */
+bool
+pdf_objname_is_valid(const byte *data, uint size)
+{
+ return (size >= 2 && data[0] == '{' &&
+ (const byte *)memchr(data, '}', size) == data + size - 1);
+}
+
+/*
+ * Look up a named object. Return e_rangecheck if the syntax is invalid.
+ * If the object is missing, return e_undefined.
+ */
+int
+pdf_find_named(gx_device_pdf * pdev, const gs_param_string * pname,
+ cos_object_t **ppco)
+{
+ const cos_value_t *pvalue;
+
+ if (!pdf_objname_is_valid(pname->data, pname->size))
+ return_error(gs_error_rangecheck);
+ if ((pvalue = cos_dict_find(pdev->named_objects, pname->data, pname->size)) != 0) {
+ *ppco = pvalue->contents.object;
+ return 0;
+ }
+ return_error(gs_error_undefined);
+}
+
+/*
+ * Create a named object. id = -1L means do not assign an id. pname = 0
+ * means just create the object, do not name it.
+ */
+int
+pdf_create_named(gx_device_pdf *pdev, const gs_param_string *pname,
+ cos_type_t cotype, cos_object_t **ppco, long id)
+{
+ gs_memory_t *mem = pdev->pdf_memory;
+ cos_object_t *pco;
+ cos_value_t value;
+
+ *ppco = pco = cos_object_alloc(mem, "pdf_create_named");
+ if (pco == 0)
+ return_error(gs_error_VMerror);
+ pco->id =
+ (id == -1 ? 0L : id == 0 ? pdf_obj_ref(pdev) : id);
+ if (pname) {
+ int code = cos_dict_put(pdev->named_objects, pdev, pname->data,
+ pname->size, cos_object_value(&value, pco));
+
+ if (code < 0)
+ return code;
+ }
+ if (cotype != cos_type_generic)
+ cos_become(pco, cotype);
+ *ppco = pco;
+ return 0;
+}
+int
+pdf_create_named_dict(gx_device_pdf *pdev, const gs_param_string *pname,
+ cos_dict_t **ppcd, long id)
+{
+ cos_object_t *pco;
+ int code = pdf_create_named(pdev, pname, cos_type_dict, &pco, id);
+
+ *ppcd = (cos_dict_t *)pco;
+ return code;
+}
+
+/*
+ * Look up a named object as for pdf_find_named. If the object does not
+ * exist, create it (as a dictionary if it is one of the predefined names
+ * {ThisPage}, {NextPage}, {PrevPage}, or {Page<#>}, otherwise as a
+ * generic object) and return 1.
+ */
+int
+pdf_refer_named(gx_device_pdf * pdev, const gs_param_string * pname_orig,
+ cos_object_t **ppco)
+{
+ const gs_param_string *pname = pname_orig;
+ int code = pdf_find_named(pdev, pname, ppco);
+ char page_name_chars[6 + 10 + 2]; /* {Page<n>}, enough for an int */
+ gs_param_string pnstr;
+ int page_number;
+
+ if (code != gs_error_undefined)
+ return code;
+ /*
+ * Check for a predefined name. Map ThisPage, PrevPage, and NextPage
+ * to the appropriate Page<#> name.
+ */
+ if (pname->size >= 7 &&
+ sscanf((const char *)pname->data, "{Page%d}", &page_number) == 1
+ )
+ goto cpage;
+ if (pdf_key_eq(pname, "{ThisPage}"))
+ page_number = pdev->next_page + 1;
+ else if (pdf_key_eq(pname, "{NextPage}"))
+ page_number = pdev->next_page + 2;
+ else if (pdf_key_eq(pname, "{PrevPage}"))
+ page_number = pdev->next_page;
+ else {
+ code = pdf_create_named(pdev, pname, cos_type_generic, ppco, 0L);
+ return (code < 0 ? code : 1);
+ }
+ if (page_number <= 0)
+ return code;
+ sprintf(page_name_chars, "{Page%d}", page_number);
+ param_string_from_string(pnstr, page_name_chars);
+ pname = &pnstr;
+ code = pdf_find_named(pdev, pname, ppco);
+ if (code != gs_error_undefined)
+ return code;
+ cpage:
+ if (pdf_page_id(pdev, page_number) <= 0)
+ return_error(gs_error_rangecheck);
+ *ppco = COS_OBJECT(pdev->pages[page_number - 1].Page);
+ return 0;
+}
+
+/*
+ * Look up a named object as for pdf_refer_named. If the object already
+ * exists and is not simply a forward reference, return e_rangecheck;
+ * if it exists as a forward reference, set its type and return 0;
+ * otherwise, create the object with the given type and return 1.
+ */
+int
+pdf_make_named(gx_device_pdf * pdev, const gs_param_string * pname,
+ cos_type_t cotype, cos_object_t **ppco, bool assign_id)
+{
+ if (pname) {
+ int code = pdf_refer_named(pdev, pname, ppco);
+ cos_object_t *pco = *ppco;
+
+ if (code < 0)
+ return code;
+ if (cos_type(pco) != cos_type_generic)
+ return_error(gs_error_rangecheck);
+ if (assign_id && pco->id == 0)
+ pco->id = pdf_obj_ref(pdev);
+ cos_become(pco, cotype);
+ return code;
+ } else {
+ int code = pdf_create_named(pdev, pname, cotype, ppco,
+ (assign_id ? 0L : -1L));
+
+ return (code < 0 ? code : 1);
+ }
+}
+int
+pdf_make_named_dict(gx_device_pdf * pdev, const gs_param_string * pname,
+ cos_dict_t **ppcd, bool assign_id)
+{
+ cos_object_t *pco;
+ int code = pdf_make_named(pdev, pname, cos_type_dict, &pco, assign_id);
+
+ *ppcd = (cos_dict_t *)pco;
+ return code;
+}
+
+/*
+ * Look up a named object as for pdf_refer_named. If the object does not
+ * exist, return e_undefined; if the object exists but has the wrong type,
+ * return e_typecheck.
+ */
+int
+pdf_get_named(gx_device_pdf * pdev, const gs_param_string * pname,
+ cos_type_t cotype, cos_object_t **ppco)
+{
+ int code = pdf_refer_named(pdev, pname, ppco);
+
+ if (code < 0)
+ return code;
+ if (cos_type(*ppco) != cotype)
+ return_error(gs_error_typecheck);
+ return code;
+}
+
+/*
+ * Scan a token from a string. <<, >>, [, and ] are treated as tokens.
+ * Return 1 if a token was scanned, 0 if we reached the end of the string,
+ * or an error. On a successful return, the token extends from *ptoken up
+ * to but not including *pscan.
+ *
+ * Note that this scanner expects a subset of PostScript syntax, not PDF
+ * syntax. In particular, it doesn't understand ASCII85 strings, and it
+ * doesn't process the PDF #-escape syntax within names. Note also that
+ * it does only minimal syntax checking.
+ */
+int
+pdf_scan_token(const byte **pscan, const byte * end, const byte **ptoken)
+{
+ const byte *p = *pscan;
+ int ch;
+
+ while (p < end && scan_char_decoder[*p] == ctype_space)
+ ++p;
+ *ptoken = p;
+ if (p >= end) {
+ *pscan = p;
+ return 0;
+ }
+ switch (*p) {
+ case '%':
+ case ')':
+ return_error(gs_error_syntaxerror);
+ case '(': {
+ /* Skip over the string. */
+ byte buf[50]; /* size is arbitrary */
+ stream_cursor_read r;
+ stream_cursor_write w;
+ stream_PSSD_state ss;
+ int status;
+
+ s_PSSD_init_inline(&ss);
+ r.ptr = p; /* skip the '(' */
+ r.limit = end - 1;
+ w.limit = buf + sizeof(buf) - 1;
+ do {
+ w.ptr = buf - 1;
+ status = (*s_PSSD_template.process)
+ ((stream_state *) & ss, &r, &w, true);
+ }
+ while (status == 1);
+ *pscan = r.ptr + 1;
+ return 1;
+ }
+ case '<':
+ if (end - p < 2)
+ return_error(gs_error_syntaxerror);
+ if (p[1] != '<') {
+ /*
+ * We need the cast because some compilers declare memchar as
+ * returning a char * rather than a void *.
+ */
+ p = (const byte *)memchr(p + 1, '>', end - p - 1);
+ if (p == 0)
+ return_error(gs_error_syntaxerror);
+ }
+ goto m2;
+ case '>':
+ if (end - p < 2 || p[1] != '>')
+ return_error(gs_error_syntaxerror);
+m2: *pscan = p + 2;
+ return 1;
+ case '[': case ']': case '{': case '}':
+ *pscan = p + 1;
+ return 1;
+ case '/':
+ ++p;
+ default:
+ break;
+ }
+ while (p <= end && scan_char_decoder[ch = *p] <= ctype_name)
+ ++p;
+ *pscan = p;
+ if (p == *ptoken) /* no chars scanned, i.e., not ctype_name */
+ return_error(gs_error_syntaxerror);
+ return 1;
+}
+/*
+ * Scan a possibly composite token: arrays and dictionaries are treated as
+ * single tokens.
+ */
+int
+pdf_scan_token_composite(const byte **pscan, const byte * end,
+ const byte **ptoken_orig)
+{
+ int level = 0;
+ const byte *ignore_token;
+ const byte **ptoken = ptoken_orig;
+ int code;
+
+ do {
+ code = pdf_scan_token(pscan, end, ptoken);
+ if (code <= 0)
+ return (code < 0 || level == 0 ? code :
+ gs_note_error(gs_error_syntaxerror));
+ switch (**ptoken) {
+ case '<': case '[': case '{':
+ ++level; break;
+ case '>': case ']': case '}':
+ if (level == 0)
+ return_error(gs_error_syntaxerror);
+ --level; break;
+ }
+ ptoken = &ignore_token;
+ } while (level);
+ return code;
+}
+
+/* Replace object names with object references in a (parameter) string. */
+private const byte *
+pdfmark_next_object(const byte * scan, const byte * end, const byte **pname,
+ cos_object_t **ppco, gx_device_pdf * pdev)
+{
+ /*
+ * Starting at scan, find the next object reference, set *pname
+ * to point to it in the string, store the object at *ppco,
+ * and return a pointer to the first character beyond the
+ * reference. If there are no more object references, set
+ * *pname = end, *ppco = 0, and return end.
+ */
+ int code;
+
+ while ((code = pdf_scan_token(&scan, end, pname)) != 0) {
+ gs_param_string sname;
+
+ if (code < 0) {
+ ++scan;
+ continue;
+ }
+ if (**pname != '{')
+ continue;
+ /* Back up over the { and rescan as a single token. */
+ scan = *pname;
+ code = pdf_scan_token_composite(&scan, end, pname);
+ if (code < 0) {
+ ++scan;
+ continue;
+ }
+ sname.data = *pname;
+ sname.size = scan - sname.data;
+ /*
+ * Forward references are allowed. If there is an error,
+ * simply retain the name as a literal string.
+ */
+ code = pdf_refer_named(pdev, &sname, ppco);
+ if (code < 0)
+ continue;
+ return scan;
+ }
+ *ppco = 0;
+ return end;
+}
+int
+pdf_replace_names(gx_device_pdf * pdev, const gs_param_string * from,
+ gs_param_string * to)
+{
+ const byte *start = from->data;
+ const byte *end = start + from->size;
+ const byte *scan;
+ uint size = 0;
+ cos_object_t *pco;
+ bool any = false;
+ byte *sto;
+ char ref[1 + 10 + 5 + 1]; /* max obj number is 10 digits */
+
+ /* Do a first pass to compute the length of the result. */
+ for (scan = start; scan < end;) {
+ const byte *sname;
+ const byte *next =
+ pdfmark_next_object(scan, end, &sname, &pco, pdev);
+
+ size += sname - scan;
+ if (pco) {
+ sprintf(ref, " %ld 0 R ", pco->id);
+ size += strlen(ref);
+ }
+ scan = next;
+ any |= next != sname;
+ }
+ to->persistent = true; /* ??? */
+ if (!any) {
+ to->data = start;
+ to->size = size;
+ return 0;
+ }
+ sto = gs_alloc_bytes(pdev->pdf_memory, size, "pdf_replace_names");
+ if (sto == 0)
+ return_error(gs_error_VMerror);
+ to->data = sto;
+ to->size = size;
+ /* Do a second pass to do the actual substitutions. */
+ for (scan = start; scan < end;) {
+ const byte *sname;
+ const byte *next =
+ pdfmark_next_object(scan, end, &sname, &pco, pdev);
+ uint copy = sname - scan;
+ int rlen;
+
+ memcpy(sto, scan, copy);
+ sto += copy;
+ if (pco) {
+ sprintf(ref, " %ld 0 R ", pco->id);
+ rlen = strlen(ref);
+ memcpy(sto, ref, rlen);
+ sto += rlen;
+ }
+ scan = next;
+ }
+ return 0;
+}
diff --git a/gs/src/gdevpdft.c b/gs/src/gdevpdft.c
index ac71d2a2d..e67324700 100644
--- a/gs/src/gdevpdft.c
+++ b/gs/src/gdevpdft.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996, 1997, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1996, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -23,17 +23,23 @@
#include "string_.h"
#include "gx.h"
#include "gserrors.h"
+#include "gsmatrix.h"
#include "gsutil.h" /* for bytes_compare */
+#include "gxfixed.h" /* for gxfcache.h */
+#include "gxfont.h"
+#include "gxfont0.h"
+#include "gxfcache.h" /* for orig_fonts list */
+#include "gxpath.h" /* for getting current point */
#include "gdevpdfx.h"
#include "scommon.h"
/*
- * When a base font is selected, we have many alternatives for how to handle
- * characters whose encoding doesn't match their encoding in the base font's
- * built-in encoding. If a character's glyph doesn't match the character's
- * glyph in the encoding built up so far, we check if the font has that
- * glyph at all; if not, we fall back to a bitmap. Otherwise, we use one
- * or both of the following algorithms:
+ * When a base font is selected, we have several alternatives for how to
+ * handle characters whose encoding doesn't match their encoding in the base
+ * font's built-in encoding. If a character's glyph doesn't match the
+ * character's glyph in the encoding built up so far, we check if the font
+ * has that glyph at all; if not, we fall back to a bitmap. Otherwise, we
+ * use one or both of the following algorithms:
*
* 1. If this is the first time a character at this position has been
* seen, assign its glyph to that position in the encoding.
@@ -46,469 +52,667 @@
* We do this step if the device parameter ReEncodeCharacters is true.
* (This is the default.)
*
- * 3. Finally, fall back to using bitmaps (for the entire string).
+ * 3. Finally, fall back to using a bitmap.
*
* If it is essential that all strings in the output contain exactly the
* same character codes as the input, set ReEncodeCharacters to false. If
* it is important that strings be searchable, but some non-searchable
* strings can be tolerated, the defaults are appropriate. If searchability
* is not important, set ReAssignCharacters to false.
+ *
+ * Acrobat Reader 3's Print function has a bug that make re-encoded
+ * characters print as blank if the font is substituted (not embedded).
+ * Therefore, if CompatibilityLevel <= 1.2, for non-embedded fonts, no
+ * substitutions or re-encodings are allowed.
*/
+/* Forward references */
+private int pdf_set_font_and_size(P3(gx_device_pdf * pdev, pdf_font_t * font,
+ floatp size));
+private int pdf_set_text_matrix(P2(gx_device_pdf * pdev,
+ const gs_matrix * pmat));
+private int pdf_append_chars(P3(gx_device_pdf * pdev, const byte * str,
+ uint size));
+
+/* Define the text enumerator. */
+typedef struct pdf_text_enum_s {
+ gs_text_enum_common;
+ gs_text_enum_t *pte_default;
+} pdf_text_enum_t;
+extern_st(st_gs_text_enum);
+gs_private_st_suffix_add1(st_pdf_text_enum, pdf_text_enum_t, "pdf_text_enum_t",
+ pdf_text_enum_enum_ptrs, pdf_text_enum_reloc_ptrs, st_gs_text_enum,
+ pte_default);
+
/*
- * The show pseudo-parameter is currently the way that the PostScript code
- * passes show operations to the PDF writer. It is a hack! Its "value"
- * is the string being shown. The following other parameters must be "set"
- * at the same time:
- * /showX px
- * /showY py
- * /showValues [{cx cy char} {ax ay}] (optional)
- * /showFontName /fontname
- * /showMatrix [xx xy yx yy tx ty]
- * /showEncoding [e0 .. e255] (optional)
- * /showBaseEncoding [e0 ... e255] (optional)
- * /showCharStrings << charnames => anything >> (optional)
- * Note that px/y and tx/y are floating point values in device space;
- * cx/y and ax/y are in text space. The matrix is the concatenation of
- * FontMatrix
- * inverse of base FontMatrix
- * CTM
- * This represents the transformation from a 1-unit-based character space
- * to device space. The base encoding is StandardEncoding for all fonts
- * except Symbol and ZapfDingbats; the encodings are not passed if the
- * encoding is eq to the base encoding, since in this case no check for
- * whether the string is encodable in the base encoding is needed.
+ * Define quantities derived from the current font and CTM, used within
+ * the text processing loop.
*/
+typedef struct pdf_text_process_state_s {
+ float chars; /* scaled character spacing (Tc) */
+ float words; /* scaled word spacing (Tw) */
+ float size; /* font size for Tf */
+ gs_matrix text_matrix; /* normalized FontMatrix * CTM for Tm */
+ pdf_font_t *pdfont;
+} pdf_text_process_state_t;
-/* Define the 14 standard built-in fonts. */
-private const char *const standard_font_names[] =
+/* Forward references */
+private int pdf_encode_char(P4(gx_device_pdf *pdev, int chr,
+ gs_font_base *bfont, pdf_font_t *ppf));
+
+/* Define the auxiliary procedures for text processing. */
+private int
+pdf_text_resync(gs_text_enum_t *pte, const gs_text_enum_t *pfrom)
{
- "Courier", "Courier-Bold", "Courier-Oblique", "Courier-BoldOblique",
-"Helvetica", "Helvetica-Bold", "Helvetica-Oblique", "Helvetica-BoldOblique",
- "Symbol",
- "Times-Roman", "Times-Bold", "Times-Italic", "Times-BoldItalic",
- "ZapfDingbats",
- 0
-};
+ pdf_text_enum_t *const penum = (pdf_text_enum_t *)pte;
+
+ if ((pte->text.operation ^ pfrom->text.operation) & ~TEXT_FROM_ANY)
+ return_error(gs_error_rangecheck);
+ if (penum->pte_default) {
+ int code = gs_text_resync(penum->pte_default, pfrom);
+
+ if (code < 0)
+ return code;
+ }
+ pte->text = pfrom->text;
+ gs_text_enum_copy_dynamic(pte, pfrom, false);
+ return 0;
+}
+private bool
+pdf_text_is_width_only(const gs_text_enum_t *pte)
+{
+ const pdf_text_enum_t *const penum = (const pdf_text_enum_t *)pte;
-/* Define StandardEncoding. */
-private const char notdef_string[] = ".notdef";
+ if (penum->pte_default)
+ return gs_text_is_width_only(penum->pte_default);
+ return false;
+}
+private int
+pdf_text_current_width(const gs_text_enum_t *pte, gs_point *pwidth)
+{
+ const pdf_text_enum_t *const penum = (const pdf_text_enum_t *)pte;
-#define notdef notdef_string
-private const char *const std_enc_strings[256] =
+ if (penum->pte_default)
+ return gs_text_current_width(penum->pte_default, pwidth);
+ return_error(gs_error_rangecheck); /* can't happen */
+}
+private int
+pdf_text_set_cache(gs_text_enum_t *pte, const double *pw,
+ gs_text_cache_control_t control)
{
- /* \00x */
- notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
- notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
- notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
- notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
- /* \04x */
- "space", "exclam", "quotedbl", "numbersign",
- "dollar", "percent", "ampersand", "quoteright",
- "parenleft", "parenright", "asterisk", "plus",
- "comma", "hyphen", "period", "slash",
- "zero", "one", "two", "three",
- "four", "five", "six", "seven",
- "eight", "nine", "colon", "semicolon",
- "less", "equal", "greater", "question",
- /* \10x */
- "at", "A", "B", "C", "D", "E", "F", "G",
- "H", "I", "J", "K", "L", "M", "N", "O",
- "P", "Q", "R", "S", "T", "U", "V", "W",
- "X", "Y", "Z", "bracketleft",
- "backslash", "bracketright", "asciicircum", "underscore",
- /* \14x */
- "quoteleft", "a", "b", "c", "d", "e", "f", "g",
- "h", "i", "j", "k", "l", "m", "n", "o",
- "p", "q", "r", "s", "t", "u", "v", "w",
- "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", notdef,
- /* \20x */
- notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
- notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
- notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
- notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
- /* \24x */
- notdef, "exclamdown", "cent", "sterling",
- "fraction", "yen", "florin", "section",
- "currency", "quotesingle", "quotedblleft", "guillemotleft",
- "guilsinglleft", "guilsinglright", "fi", "fl",
- notdef, "endash", "dagger", "daggerdbl",
- "periodcentered", notdef, "paragraph", "bullet",
- "quotesinglbase", "quotedblbase", "quotedblright", "guillemotright",
- "ellipsis", "perthousand", notdef, "questiondown",
- /* \30x */
- notdef, "grave", "acute", "circumflex",
- "tilde", "macron", "breve", "dotaccent",
- "dieresis", notdef, "ring", "cedilla",
- notdef, "hungarumlaut", "ogonek", "caron",
- "emdash", notdef, notdef, notdef,
- notdef, notdef, notdef, notdef,
- notdef, notdef, notdef, notdef,
- notdef, notdef, notdef, notdef,
- /* \34x", */
- notdef, "AE", notdef, "ordfeminine", notdef, notdef, notdef, notdef,
- "Lslash", "Oslash", "OE", "ordmasculine", notdef, notdef, notdef, notdef,
- notdef, "ae", notdef, notdef, notdef, "dotlessi", notdef, notdef,
- "lslash", "oslash", "oe", "germandbls", notdef, notdef, notdef, notdef
-};
+ pdf_text_enum_t *const penum = (pdf_text_enum_t *)pte;
-#undef notdef
+ if (penum->pte_default)
+ return gs_text_set_cache(penum->pte_default, pw, control);
+ return_error(gs_error_rangecheck); /* can't happen */
+}
+private int
+pdf_text_retry(gs_text_enum_t *pte)
+{
+ pdf_text_enum_t *const penum = (pdf_text_enum_t *)pte;
-/* Forward references */
-private int pdf_set_font_and_size(P3(gx_device_pdf * pdev, pdf_font * font,
- floatp size));
-private int pdf_set_text_matrix(P2(gx_device_pdf * pdev,
- const gs_matrix * pmat));
-private int pdf_append_chars(P3(gx_device_pdf * pdev, const byte * str,
- uint size));
-private int pdf_check_encoding(P6(gx_device_pdf * pdev, gs_param_string * pstr,
- gs_param_list * plist, byte * strbuf,
- int max_strbuf, pdf_font * ppf));
+ if (penum->pte_default)
+ return gs_text_retry(penum->pte_default);
+ return_error(gs_error_rangecheck); /* can't happen */
+}
+private void
+pdf_text_release(gs_text_enum_t *pte, client_name_t cname)
+{
+ pdf_text_enum_t *const penum = (pdf_text_enum_t *)pte;
-/* Process a show operation. */
+ if (penum->pte_default) {
+ gs_text_release(penum->pte_default, cname);
+ penum->pte_default = 0;
+ }
+ gx_default_text_release(pte, cname);
+}
+
+/* Begin processing text. */
+private text_enum_proc_process(pdf_text_process);
+private const gs_text_enum_procs_t pdf_text_procs = {
+ pdf_text_resync, pdf_text_process,
+ pdf_text_is_width_only, pdf_text_current_width,
+ pdf_text_set_cache, pdf_text_retry,
+ pdf_text_release
+};
int
-pdfshow_process(gx_device_pdf * pdev, gs_param_list * plist,
- const gs_param_string * pts)
+gdev_pdf_text_begin(gx_device * dev, gs_imager_state * pis,
+ const gs_text_params_t *text, gs_font * font,
+ gx_path * path, const gx_device_color * pdcolor,
+ const gx_clip_path * pcpath,
+ gs_memory_t * mem, gs_text_enum_t ** ppte)
{
- gs_param_string str, fnstr;
- gs_param_float_array va;
- float v_cx = 0, v_cy = 0, v_ax = 0, v_ay = 0, v_px, v_py;
- int v_cch = 32;
- gs_param_float_array ma;
+ gx_device_pdf *const pdev = (gx_device_pdf *)dev;
+ pdf_text_enum_t *penum;
+ gs_fixed_point cpt;
int code;
- pdf_font *ppf;
- stream *s;
- double sx = pdev->HWResolution[0] / 72.0, sy = pdev->HWResolution[1] / 72.0;
- float size;
- byte strbuf[200];
- str = *pts;
- if (str.size == 0)
- return 0; /* nothing to do */
- /* Find or create the font resource. */
- if ((code = param_read_string(plist, "showFontName", &fnstr)))
- return_error(gs_error_rangecheck);
- {
- int i;
+ if ((text->operation &
+ ~(TEXT_FROM_STRING | TEXT_FROM_BYTES |
+ TEXT_ADD_TO_ALL_WIDTHS | TEXT_ADD_TO_SPACE_WIDTH |
+ TEXT_REPLACE_WIDTHS |
+ TEXT_DO_DRAW | TEXT_RETURN_WIDTH)) != 0 ||
+ !gx_dc_is_pure(pdcolor) ||
+ gx_path_current_point(path, &cpt) < 0
+ )
+ return gx_default_text_begin(dev, pis, text, font, path, pdcolor,
+ pcpath, mem, ppte);
+ /* Set the clipping path and color. */
- for (i = 0; i < num_resource_chains; ++i)
- for (ppf = (pdf_font *) pdev->resources[resourceFont].chains[i];
- ppf != 0; ppf = ppf->next
- )
- if (!bytes_compare(ppf->fname.chars, ppf->fname.size,
- fnstr.data, fnstr.size)
- )
- goto found;
- found:DO_NOTHING;
- }
- if (ppf == 0) {
- /*
- * Currently, we only handle the built-in fonts. By doing
- * things in this order, we may wind up including some base
- * fonts that aren't actually needed, but it's unlikely.
- */
- const char *const *ppfn;
+ if (pdf_must_put_clip_path(pdev, pcpath)) {
+ int code = pdf_open_page(pdev, PDF_IN_STREAM);
- for (ppfn = standard_font_names; *ppfn; ++ppfn)
- if (strlen(*ppfn) == fnstr.size &&
- !strncmp(*ppfn, (const char *)fnstr.data, fnstr.size)
- )
- break;
- if (!*ppfn)
- return_error(gs_error_undefined);
- /*
- * Allocate the font resource, but don't write it yet,
- * because we don't know yet whether it will need
- * a modified Encoding.
- */
- code = pdf_alloc_resource(pdev, resourceFont, gs_no_id,
- (pdf_resource **) & ppf);
if (code < 0)
- return_error(gs_error_undefined);
- memcpy(ppf->fname.chars, fnstr.data, fnstr.size);
- ppf->fname.size = fnstr.size;
- ppf->frname[0] = 0; /* not an embedded font */
- memset(ppf->chars_used, 0, sizeof(ppf->chars_used));
- ppf->differences = 0;
- ppf->num_chars = 0; /* ditto */
- ppf->char_procs = 0; /* for GC */
+ return code;
+ pdf_put_clip_path(pdev, pcpath);
}
- /* Check that all characters can be encoded. */
- code = pdf_check_encoding(pdev, &str, plist, strbuf, sizeof(strbuf), ppf);
+ pdf_set_color(pdev, gx_dc_pure_color(pdcolor), &pdev->fill_color, "rg");
+
+ /* Allocate and initialize the enumerator. */
+
+ rc_alloc_struct_1(penum, pdf_text_enum_t, &st_pdf_text_enum, mem,
+ return_error(gs_error_VMerror), "gdev_pdf_text_begin");
+ penum->rc.free = rc_free_text_enum;
+ penum->pte_default = 0;
+ code = gs_text_enum_init((gs_text_enum_t *)penum, &pdf_text_procs,
+ dev, pis, text, font, path, pdcolor, pcpath, mem);
+ if (code < 0) {
+ gs_free_object(mem, penum, "gdev_pdf_text_begin");
+ return code;
+ }
+ *ppte = (gs_text_enum_t *)penum;
+
+ return 0;
+}
+
+/*
+ * Compute the cached values in the text state from the text parameters,
+ * current_font, and pis->ctm.
+ */
+private int
+pdf_update_text_state(pdf_text_process_state_t *ppts, const pdf_text_enum_t *penum)
+{
+ gx_device_pdf *const pdev = (gx_device_pdf *)penum->dev;
+ gs_font *font = penum->current_font;
+ gs_font *base_font = font;
+ pdf_font_t *ppf;
+ pdf_font_descriptor_t fdesc;
+ gs_fixed_point cpt;
+ gs_matrix orig_matrix, smat, tmat;
+ gs_const_string font_name;
+ double
+ sx = pdev->HWResolution[0] / 72.0,
+ sy = pdev->HWResolution[1] / 72.0;
+ float chars, words, size;
+ int code = gx_path_current_point(penum->path, &cpt);
+
if (code < 0)
return code;
- /* Read and check the rest of the parameters now. */
- if ((code = param_read_float(plist, "showX", &v_px)) ||
- (code = param_read_float(plist, "showY", &v_py)) ||
- (code = param_read_float_array(plist, "showMatrix", &ma)) ||
- ma.size != 6
- )
+
+ /* PDF always uses 1000 units per em for font metrics. */
+ switch (font->FontType) {
+ case ft_TrueType:
+ /* The TrueType FontMatrix is 1 unit per em, which is what we want. */
+ gs_make_identity(&orig_matrix);
+ break;
+ case ft_encrypted:
+ case ft_encrypted2:
+ gs_make_scaling(0.001, 0.001, &orig_matrix);
+ break;
+ default:
return_error(gs_error_rangecheck);
- switch ((code = param_read_float_array(plist, "showValues", &va))) {
- case 1:
- break;
- default:
- return_error(code);
- case 0:
- {
- const float *vp = va.data;
-
- switch (va.size) {
- case 3:
- v_cx = vp[0], v_cy = vp[1], v_cch = (int)vp[2];
- break;
- case 5:
- v_cx = vp[0], v_cy = vp[1], v_cch = (int)vp[2];
- vp += 3;
- case 2:
- v_ax = vp[0], v_ay = vp[1];
- break;
- default:
- return_error(gs_error_rangecheck);
- }
- if (v_cy != 0 || (v_cch != 32 && v_cx != 0) || v_ay != 0)
- return_error(gs_error_undefined);
- }
}
+ if (!pdf_find_orig_font(pdev, font, &font_name, &orig_matrix)) {
+ while (base_font->base != base_font)
+ base_font = base_font->base;
+ font_name.data = base_font->font_name.chars;
+ font_name.size = base_font->font_name.size;
+ }
+
+ /* Compute the scaling matrix and combined matrix. */
+
+ gs_matrix_invert(&orig_matrix, &smat);
+ gs_matrix_multiply(&font->FontMatrix, &smat, &smat);
+ tmat = ctm_only(penum->pis);
+ tmat.tx = tmat.ty = 0;
+ gs_matrix_multiply(&smat, &tmat, &tmat);
+
/* Try to find a reasonable size value. This isn't necessary, */
/* but it's worth the effort. */
- size = fabs(ma.data[3]) / sy;
+
+ size = fabs(tmat.yy) / sy;
if (size < 0.01)
- size = fabs(ma.data[0]) / sx;
+ size = fabs(tmat.xx) / sx;
if (size < 0.01)
size = 1;
- /* We attempt to eliminate redundant parameter settings. */
- pdf_set_font_and_size(pdev, ppf, size);
- {
- float chars = v_ax * size;
- if (pdev->text.character_spacing != chars) {
- code = pdf_open_contents(pdev, pdf_in_text);
+ /* Check for spacing parameters we can handle, and transform them. */
+
+ if (penum->text.operation & TEXT_ADD_TO_ALL_WIDTHS) {
+ gs_point pt;
+
+ gs_distance_transform_inverse(penum->text.delta_all.x,
+ penum->text.delta_all.y,
+ &smat, &pt);
+ if (pt.y != 0)
+ return_error(gs_error_rangecheck);
+ chars = pt.x * size;
+ } else
+ chars = 0.0;
+
+ if (penum->text.operation & TEXT_ADD_TO_SPACE_WIDTH) {
+ gs_point pt;
+
+ gs_distance_transform_inverse(penum->text.delta_space.x,
+ penum->text.delta_space.y,
+ &smat, &pt);
+ if (pt.y != 0 || penum->text.space.s_char != 32)
+ return_error(gs_error_rangecheck);
+ words = pt.x * size;
+ } else
+ words = 0.0;
+
+ /* Find or create the font resource. */
+
+ ppf = (pdf_font_t *)pdf_find_resource_by_gs_id(pdev, resourceFont, font->id);
+ if (ppf == 0 || ppf->skip) {
+ int index = -1;
+ pdf_font_t ftemp;
+
+ switch (pdf_font_embed_status(pdev, font, &index)) {
+ case FONT_EMBED_YES:
+ code = pdf_compute_font_descriptor(pdev, &fdesc, font, NULL);
if (code < 0)
return code;
- s = pdev->strm;
- pprintg1(s, "%g Tc\n", chars);
- pdev->text.character_spacing = chars;
- }
- }
- {
- float words = v_cx * size;
+ fdesc.FontFile_id = pdf_obj_ref(pdev);
+ goto wf;
+ case FONT_EMBED_NO:
+ code = pdf_compute_font_descriptor(pdev, &fdesc, font, NULL);
+ if (code < 0)
+ return code;
+wf: fdesc.id = pdf_obj_ref(pdev);
+ {
+ /*
+ * Before allocating the font resource, check that we can
+ * get all the widths.
+ */
+ int i;
- if (pdev->text.word_spacing != words) {
- code = pdf_open_contents(pdev, pdf_in_text);
+ memset(&ftemp, 0, sizeof(ftemp));
+ ftemp.descriptor = &fdesc;
+ for (i = 0; i <= 255; ++i) {
+ code = pdf_char_width(&ftemp, i, font, NULL, NULL);
+ if (code < 0 && code != gs_error_undefined)
+ return code;
+ }
+ }
+ /* falls through */
+ case FONT_EMBED_BASE14:
+ /*
+ * Allocate the font resource, but don't write it yet,
+ * because we don't know yet whether it will need
+ * a modified Encoding.
+ */
+ code = pdf_alloc_font(pdev, font->id, &ppf, index < 0);
+ if (code < 0)
+ return code;
+ memcpy(ppf->fname.chars, font_name.data, font_name.size);
+ ppf->fname.size = font_name.size;
+ ppf->FontType = font->FontType;
+ ppf->index = index;
+ if (index < 0) {
+ *ppf->descriptor = fdesc;
+ ppf->font = font;
+ ppf->orig_matrix = orig_matrix;
+ /*
+ * C's bizarre coercion rules make us use memcpy here
+ * rather than direct assignments, even though sizeof()
+ * gives the correct value....
+ */
+ memcpy(ppf->Widths, ftemp.Widths, sizeof(ppf->Widths));
+ memcpy(ppf->widths_known, ftemp.widths_known,
+ sizeof(ppf->widths_known));
+ }
+ code = pdf_register_font(pdev, font, ppf);
if (code < 0)
return code;
- s = pdev->strm;
- pprintg1(s, "%g Tw\n", words);
- pdev->text.word_spacing = words;
}
}
- {
- gs_matrix tmat;
+ tmat.xx /= size;
+ tmat.xy /= size;
+ tmat.yx /= size;
+ tmat.yy /= size;
+ tmat.tx += fixed2float(cpt.x);
+ tmat.ty += fixed2float(cpt.y);
- tmat.xx = ma.data[0] / size;
- tmat.xy = ma.data[1] / size;
- tmat.yx = ma.data[2] / size;
- tmat.yy = ma.data[3] / size;
- tmat.tx = v_px + ma.data[4];
- tmat.ty = v_py + ma.data[5];
- pdf_set_text_matrix(pdev, &tmat);
+ /* Store the updated values. */
+
+ ppts->chars = chars;
+ ppts->words = words;
+ ppts->size = size;
+ ppts->text_matrix = tmat;
+ ppts->pdfont = ppf;
+
+ return 0;
+}
+
+/*
+ * For a given character, check whether the encodings are compatible, and if
+ * not, whether we can re-encode the character using the base encoding.
+ * Return the (possibly re-encoded) character if successful.
+ */
+private int
+try_encode_char(gx_device_pdf *pdev, int chr, gs_font_base *bfont,
+ pdf_font_t *ppf)
+{
+ /* Note: ei, but not bei, may be ENCODING_INDEX_UNKNOWN. */
+ gs_encoding_index_t ei = bfont->encoding_index;
+ gs_encoding_index_t bei = pdf_standard_fonts[ppf->index].base_encoding;
+ pdf_encoding_element_t *pdiff = ppf->differences;
+ gs_glyph font_glyph, glyph;
+
+ if (ei == bei && pdiff == 0) {
+ /*
+ * Just note that the character has been used with its original
+ * encoding.
+ */
+ return chr;
+ }
+
+#define ENCODE(ch)\
+ (pdiff != 0 && pdiff[ch].str.data != 0 ?\
+ pdiff[ch].glyph :\
+ bfont->procs.callbacks.known_encode((gs_char)(ch), bei))
+
+ font_glyph = ENCODE(chr);
+ glyph =
+ (ei == ENCODING_INDEX_UNKNOWN ?
+ bfont->procs.encode_char((gs_font *)bfont, chr, GLYPH_SPACE_NAME) :
+ bfont->procs.callbacks.known_encode(chr, ei));
+ if (glyph == font_glyph)
+ return chr;
+
+ if (ppf->descriptor != 0 &&
+ ppf->descriptor->FontFile_id == 0 &&
+ pdev->CompatibilityLevel <= 1.2
+ ) {
+ /*
+ * Work around the bug in Acrobat Reader 3's Print function
+ * that makes re-encoded characters in substituted fonts
+ * print as blank.
+ */
+ return_error(gs_error_undefined);
+ }
+
+ if (pdev->ReAssignCharacters) {
+ /*
+ * If this is the first time we've seen this character,
+ * assign the glyph to its position in the encoding.
+ */
+ if ((pdiff == 0 || pdiff[chr].str.data == 0) &&
+ !(ppf->chars_used[chr >> 3] & (1 << (chr & 7)))
+ ) {
+ int code =
+ pdf_add_encoding_difference(pdev, ppf, chr, bfont, glyph);
+
+ if (code >= 0)
+ return chr;
+ }
}
- /* If we re-encoded the string, pdf_check_encoding changed */
- /* str.data to strbuf. */
- return pdf_append_chars(pdev, str.data, str.size);
+ if (pdev->ReEncodeCharacters) {
+ /*
+ * Look for the character at some other position in the
+ * encoding.
+ */
+ int c, code;
+
+ for (c = 0; c < 256; ++c) {
+ if (ENCODE(c) == glyph)
+ return c;
+ }
+ /*
+ * The character isn't encoded anywhere. Look for a
+ * never-referenced .notdef position where we can put it.
+ */
+ for (c = 0; c < 256; ++c) {
+ gs_const_string gnstr;
+
+ if (ppf->chars_used[c >> 3] & (1 << (c & 7)))
+ continue; /* slot already referenced */
+ font_glyph = ENCODE(c);
+ if (font_glyph == gs_no_glyph)
+ break;
+ gnstr.data = (const byte *)
+ bfont->procs.callbacks.glyph_name(font_glyph,
+ &gnstr.size);
+ if (gnstr.size == 7 &&
+ !memcmp(gnstr.data, ".notdef", 7)
+ )
+ break;
+ }
+ if (c == 256) /* no .notdef positions left */
+ return_error(gs_error_undefined);
+ code = pdf_add_encoding_difference(pdev, ppf, c, bfont, glyph);
+ return (code < 0 ? code : c);
+ }
+
+ return_error(gs_error_undefined);
+
+#undef ENCODE
}
+private int
+pdf_encode_char(gx_device_pdf *pdev, int chr, gs_font_base *bfont,
+ pdf_font_t *ppf)
+{
+ int c = try_encode_char(pdev, chr, bfont, ppf);
-/* Create an encoding differences vector for a font. */
+ if (c >= 0)
+ ppf->chars_used[c >> 3] |= 1 << (c & 7);
+ return c;
+}
+
+/*
+ * Write out commands to make the output state match the processing state.
+ */
private int
-pdf_create_differences(gx_device_pdf * pdev, pdf_font * ppf)
+pdf_write_text_process_state(gx_device_pdf *pdev,
+ const pdf_text_process_state_t *ppts,
+ const gs_const_string *pstr)
{
- gs_const_string *pdiff = ppf->differences;
- int i;
+ int code;
+ stream *s;
+
+ pdf_set_font_and_size(pdev, ppts->pdfont, ppts->size);
+ code = pdf_set_text_matrix(pdev, &ppts->text_matrix);
+ if (code < 0)
+ return code;
+
+ if (pdev->text.character_spacing != ppts->chars &&
+ pstr->size + pdev->text.buffer_count > 1
+ ) {
+ code = pdf_open_page(pdev, PDF_IN_TEXT);
+ if (code < 0)
+ return code;
+ s = pdev->strm;
+ pprintg1(s, "%g Tc\n", ppts->chars);
+ pdev->text.character_spacing = ppts->chars;
+ }
+
+ if (pdev->text.word_spacing != ppts->words &&
+ (memchr(pstr->data, 32, pstr->size) ||
+ memchr(pdev->text.buffer, 32, pdev->text.buffer_count))
+ ) {
+ code = pdf_open_page(pdev, PDF_IN_TEXT);
+ if (code < 0)
+ return code;
+ s = pdev->strm;
+ pprintg1(s, "%g Tw\n", ppts->words);
+ pdev->text.word_spacing = ppts->words;
+ }
- if (pdiff != 0)
- return 0;
- ppf->diff_id = pdf_obj_ref(pdev);
- pdiff = gs_alloc_struct_array(pdev->pdf_memory, 256, gs_const_string,
- &st_const_string_element,
- "differences");
- if (pdiff == 0)
- return_error(gs_error_VMerror);
- for (i = 0; i < 256; ++i)
- pdiff[i].data = 0, pdiff[i].size = 0;
- ppf->differences = pdiff;
return 0;
}
/*
- * Check whether the encodings are compatible, and if not,
- * whether we can re-encode the string using the base encoding.
+ * Continue processing text. Per the check in pdf_text_begin, we know the
+ * operation is TEXT_FROM_STRING/BYTES, TEXT_DO_DRAW, and possibly
+ * TEXT_ADD_TO_ALL_WIDTHS, TEXT_ADD_TO_SPACE_WIDTH, TEXT_REPLACE_WIDTHS,
+ * and/or TEXT_RETURN_WIDTH.
*/
private int
-pdf_check_encoding(gx_device_pdf * pdev, gs_param_string * pstr,
- gs_param_list * plist, byte * strbuf, int max_strbuf, pdf_font * ppf)
+pdf_text_process(gs_text_enum_t *pte)
{
- gs_param_string_array ea, bea;
+ pdf_text_enum_t *const penum = (pdf_text_enum_t *)pte;
+ gx_device_pdf *const pdev = (gx_device_pdf *)penum->dev;
+ gs_text_enum_t *pte_default = penum->pte_default;
+ gs_font *font;
+ const gs_text_params_t *text = &pte->text;
+ gs_text_params_t alt_text;
+ pdf_text_process_state_t text_state;
+ gs_const_string str;
+ int i;
+ byte strbuf[200];
int code;
- gs_const_string *pdiff = ppf->differences;
- uint i;
- ea.data = bea.data = 0;
- switch ((code = param_read_name_array(plist, "showEncoding", &ea))) {
- default:
+ top:
+ if (pte_default) {
+ /* Continue processing using the default algorithms. */
+ code = gs_text_process(pte_default);
+ gs_text_enum_copy_dynamic(pte, pte_default, true);
+ if (code)
return code;
- case 0:
- if (ea.size != 256)
- return_error(gs_error_rangecheck);
- case 1:
- DO_NOTHING;
+ gs_text_release(pte_default, "pdf_text_process");
+ penum->pte_default = pte_default = 0;
+ /****** FOR NOW ******/
+ return 0;
}
- switch ((code = param_read_name_array(plist, "showBaseEncoding", &bea))) {
- default:
- return code;
- case 0:
- if (bea.size != 256)
- return_error(gs_error_rangecheck);
- case 1:
- DO_NOTHING;
+ str.data = text->data.bytes;
+ str.size = text->size;
+ font = penum->current_font;
+ switch (font->FontType) {
+ case ft_TrueType:
+ case ft_encrypted:
+ case ft_encrypted2:
+ break;
+ case ft_composite: {
+ gs_font_type0 *const font0 = (gs_font_type0 *)font;
+ fmap_type fmt = font0->data.FMapType;
+
+ if (fmap_type_is_modal(fmt) || fmt == fmap_CMap)
+ goto dflt;
+ break;
+ }
+ default:
+ goto dflt;
}
- if (ea.data == bea.data && pdiff == 0) {
- /*
- * Just note the characters that have been used with their
- * original encodings.
- */
- for (i = 0; i < pstr->size; ++i) {
- byte chr = pstr->data[i];
+ code = pdf_update_text_state(&text_state, penum);
+ if (code < 0)
+ goto dflt;
+
+ /* Check that all characters can be encoded. */
+
+ for (i = 0; i < str.size; ++i) {
+ int chr = str.data[i];
+ int code = pdf_encode_char(pdev, chr, (gs_font_base *)font,
+ text_state.pdfont);
- ppf->chars_used[chr >> 3] |= 1 << (chr & 7);
+ if (code < 0)
+ goto dflt;
+ if (code != chr) {
+ /*
+ * It really simplifies things if we can buffer
+ * the entire string locally in one piece....
+ */
+ if (str.data != strbuf) {
+ if (str.size > sizeof(strbuf))
+ goto dflt;
+ memcpy(strbuf, str.data, str.size);
+ str.data = strbuf;
+ }
+ strbuf[i] = (byte)code;
}
- return 0; /* encodings are the same */
}
- for (i = 0; i < pstr->size; ++i) {
- byte chr = pstr->data[i];
-
-#define set_encoded(sdata, ssize, ch)\
- (pdiff != 0 && pdiff[ch].data != 0 ?\
- (sdata = pdiff[ch].data, ssize = pdiff[ch].size) :\
- bea.data == 0 ?\
- (sdata = (const byte *)std_enc_strings[ch],\
- ssize = strlen((const char *)sdata)) :\
- (sdata = bea.data[ch].data, ssize = bea.data[ch].size))
- const byte *fedata;
- uint fesize;
- const byte *edata;
- uint esize;
-
- set_encoded(fedata, fesize, chr);
- if (ea.data == 0)
- esize = strlen((const char *)
- (edata = (const byte *)std_enc_strings[chr]));
- else
- edata = ea.data[chr].data, esize = ea.data[chr].size;
- if (edata == fedata ||
- (esize == fesize &&
- !memcmp(edata, fedata, esize))
- )
- ppf->chars_used[chr >> 3] |= 1 << (chr & 7);
- else {
- if (pdev->ReAssignCharacters) {
- /*
- * If this is the first time we've seen this character,
- * assign the glyph to its position in the encoding.
- */
- if ((pdiff == 0 || pdiff[chr].data == 0) &&
- !(ppf->chars_used[chr >> 3] & (1 << (chr & 7)))
- ) {
- int code = pdf_create_differences(pdev, ppf);
- if (code < 0)
- return code;
- pdiff = ppf->differences;
- /*
- * Since the entry in ea is the string for a name,
- * or a const C string, we don't need to copy it.
- */
- pdiff[chr].data = edata;
- pdiff[chr].size = esize;
- continue;
- }
- }
- if (pdev->ReEncodeCharacters) {
- /*
- * Look for the character at some other position in the
- * encoding.
- */
- int c;
+ /* Write text-related parameters. */
+ /* We attempt to eliminate redundant parameter settings. */
- for (c = 0; c < 256; ++c) {
- set_encoded(fedata, fesize, c);
- if (esize == fesize && !memcmp(edata, fedata, esize))
- break;
- }
- if (c == 256) {
- /*
- * The character isn't encoded anywhere. Look for a
- * never-referenced .notdef position where we can put
- * it.
- */
- int code;
-
- for (c = 0; c < 256; ++c) {
- set_encoded(fedata, fesize, c);
- if (!bytes_compare(fedata, fesize,
- (const byte *)".notdef", 7) &&
- !(ppf->chars_used[c >> 3] & (1 << (c & 7)))
- )
- break;
- }
- if (c == 256) /* no .notdef positions left */
- return_error(gs_error_undefined);
- code = pdf_create_differences(pdev, ppf);
- if (code < 0)
- return code;
- ppf->differences[c].data = edata;
- ppf->differences[c].size = esize;
- }
- /*
- * It really simplifies things if we can buffer
- * the entire string locally in one piece....
- */
- if (pstr->data != strbuf) {
- if (pstr->size > max_strbuf)
- return_error(gs_error_limitcheck);
- memcpy(strbuf, pstr->data, pstr->size);
- pstr->data = strbuf;
- }
- strbuf[i] = (byte) c;
- continue;
+ code = pdf_write_text_process_state(pdev, &text_state, &str);
+ if (code < 0)
+ goto dflt;
+
+ if (text->operation & TEXT_REPLACE_WIDTHS) {
+ gs_point w;
+ gs_matrix tmat;
+
+ w.x = w.y = 0;
+ tmat = text_state.text_matrix;
+ for (; pte->index < str.size; pte->index++, pte->xy_index++) {
+ gs_point d, dpt;
+
+ code = pdf_append_chars(pdev, str.data + pte->index, 1);
+ if (code < 0)
+ return code;
+ gs_text_replaced_width(&pte->text, pte->xy_index, &d);
+ w.x += d.x, w.y += d.y;
+ gs_distance_transform(d.x, d.y, &ctm_only(pte->pis), &dpt);
+ tmat.tx += dpt.x;
+ tmat.ty += dpt.y;
+ if (pte->index + 1 < str.size) {
+ code = pdf_set_text_matrix(pdev, &tmat);
+ if (code < 0)
+ return code;
}
- return_error(gs_error_undefined);
}
+ pte->returned.total_width = w;
+ return
+ (text->operation & TEXT_RETURN_WIDTH ?
+ gx_path_add_point(pte->path, float2fixed(tmat.tx),
+ float2fixed(tmat.ty)) :
+ 0);
}
- return 0;
+ code = pdf_append_chars(pdev, str.data + pte->index,
+ str.size - pte->index);
+ pte->index = 0;
+ if (code < 0)
+ goto dflt;
+ /* Call the default implementation to get the widths if needed. */
+ if (!(text->operation & TEXT_RETURN_WIDTH))
+ return 0;
+ alt_text = *text;
+ alt_text.operation ^= TEXT_DO_DRAW | TEXT_DO_CHARWIDTH;
+ text = &alt_text;
+ dflt:
+ code = gx_default_text_begin(pte->dev, pte->pis, text, pte->current_font,
+ pte->path, pte->pdcolor, pte->pcpath,
+ pte->memory, &penum->pte_default);
+ if (code < 0)
+ return code;
+ pte_default = penum->pte_default;
+ gs_text_enum_copy_dynamic(pte_default, pte, false);
+ goto top;
}
-/* ---------------- Embedded fonts ---------------- */
+/* ---------------- Font utilities ---------------- */
+
+/* Forward declarations */
+private int assign_char_code(P1(gx_device_pdf * pdev));
/*
* Set the current font and size, writing a Tf command if needed.
*/
private int
-pdf_set_font_and_size(gx_device_pdf * pdev, pdf_font * font, floatp size)
+pdf_set_font_and_size(gx_device_pdf * pdev, pdf_font_t * font, floatp size)
{
if (font != pdev->text.font || size != pdev->text.size) {
- int code = pdf_open_contents(pdev, pdf_in_text);
+ int code = pdf_open_page(pdev, PDF_IN_TEXT);
stream *s = pdev->strm;
if (code < 0)
return code;
- if (font->frname[0])
- pprints1(s, "/%s ", font->frname);
- else
- pprintld1(s, "/R%ld ", font->id);
+ pprints1(s, "/%s ", font->frname);
pprintg1(s, "%g Tf\n", size);
pdev->text.font = font;
pdev->text.size = size;
@@ -517,73 +721,15 @@ pdf_set_font_and_size(gx_device_pdf * pdev, pdf_font * font, floatp size)
return 0;
}
-/* Assign a code for a char_proc. */
-private int
-assign_char_code(gx_device_pdf * pdev)
-{
- pdf_font *font = pdev->open_font;
-
- if (font == 0) { /* This is the very first embedded font. */
- /* Create the (canned) Encoding array. */
- long id = pdf_begin_separate(pdev);
- stream *s = pdev->strm;
- int i;
-
- /*
- * Even though the PDF reference documentation says that a
- * BaseEncoding key is required unless the encoding is
- * "based on the base font's encoding" (and there is no base
- * font in this case), Acrobat 2.1 gives an error if the
- * BaseEncoding key is present.
- */
- pputs(s, "<</Type/Encoding/Differences[0");
- for (i = 0; i < 256; ++i) {
- if (!(i & 15))
- pputs(s, "\n");
- pprintd1(s, "/a%d", i);
- }
- pputs(s, "\n] >>\n");
- pdf_end_separate(pdev);
- pdev->embedded_encoding_id = id;
- }
- if (font == 0 || font->num_chars == 256) { /* Start a new embedded font. */
- pdf_resource *pres;
- int code = pdf_alloc_resource(pdev, resourceFont, gs_no_id, &pres);
- char *pc;
-
- if (code < 0)
- return code;
- font = (pdf_font *) pres;
- font->fname.size = 0;
- font->used_on_page = false;
- if (pdev->open_font == 0)
- memset(font->frname, 0, sizeof(font->frname));
- else
- strcpy(font->frname, pdev->open_font->frname);
- for (pc = font->frname; *pc == 'Z'; ++pc)
- *pc = '@';
- if ((*pc)++ == 0)
- *pc = 'A', pc[1] = 0;
- font->differences = 0;
- font->num_chars = 0;
- font->char_procs = 0;
- font->max_y_offset = 0;
- memset(font->spaces, 0, sizeof(font->spaces));
- pdev->open_font = font;
- }
- return font->num_chars++;
-}
-
/*
* Set the text matrix for writing text.
* The translation component of the matrix is the text origin.
* If the non-translation components of the matrix differ from the
* current ones, write a Tm command; otherwise, write either a Td command
* or a Tj command using space pseudo-characters.
- * Do not write a \n after the command.
*/
private int
-set_text_distance(gs_point * pdist, const gs_point * ppt, const gs_matrix * pmat)
+set_text_distance(gs_point *pdist, const gs_point *ppt, const gs_matrix *pmat)
{
double rounded;
@@ -600,7 +746,8 @@ private int
pdf_set_text_matrix(gx_device_pdf * pdev, const gs_matrix * pmat)
{
stream *s = pdev->strm;
- double sx = 72.0 / pdev->HWResolution[0], sy = 72.0 / pdev->HWResolution[1];
+ double sx = 72.0 / pdev->HWResolution[0],
+ sy = 72.0 / pdev->HWResolution[1];
int code;
if (pmat->xx == pdev->text.matrix.xx &&
@@ -611,18 +758,19 @@ pdf_set_text_matrix(gx_device_pdf * pdev, const gs_matrix * pmat)
* If we aren't already in text context, BT will reset
* the text matrix.
*/
- (pdev->context == pdf_in_text || pdev->context == pdf_in_string)
- ) { /* Use Td or a pseudo-character. */
+ (pdev->context == PDF_IN_TEXT || pdev->context == PDF_IN_STRING)
+ ) {
+ /* Use Td or a pseudo-character. */
gs_point dist;
set_text_distance(&dist, &pdev->text.current, pmat);
- if (dist.y == 0 && dist.x >= x_space_min &&
- dist.x <= x_space_max &&
+ if (dist.y == 0 && dist.x >= X_SPACE_MIN &&
+ dist.x <= X_SPACE_MAX &&
pdev->text.font != 0 &&
- font_is_embedded(pdev->text.font)
+ PDF_FONT_IS_SYNTHESIZED(pdev->text.font)
) { /* Use a pseudo-character. */
int dx = (int)dist.x;
- int dx_i = dx - x_space_min;
+ int dx_i = dx - X_SPACE_MIN;
byte space_char = pdev->text.font->spaces[dx_i];
if (space_char == 0) {
@@ -634,7 +782,8 @@ pdf_set_text_matrix(gx_device_pdf * pdev, const gs_matrix * pmat)
space_char =
pdev->open_font->spaces[dx_i] =
(byte) code;
- if (pdev->space_char_ids[dx_i] == 0) { /* Create the space char_proc now. */
+ if (pdev->space_char_ids[dx_i] == 0) {
+ /* Create the space char_proc now. */
char spstr[3 + 14 + 1];
stream *s;
@@ -651,20 +800,20 @@ pdf_set_text_matrix(gx_device_pdf * pdev, const gs_matrix * pmat)
return 0;
}
td: /* Use Td. */
- code = pdf_open_page(pdev, pdf_in_text);
+ code = pdf_open_page(pdev, PDF_IN_TEXT);
if (code < 0)
return code;
set_text_distance(&dist, &pdev->text.line_start, pmat);
- pprintg2(s, "%g %g Td", dist.x, dist.y);
+ pprintg2(s, "%g %g Td\n", dist.x, dist.y);
} else { /* Use Tm. */
- code = pdf_open_page(pdev, pdf_in_text);
+ code = pdf_open_page(pdev, PDF_IN_TEXT);
if (code < 0)
return code;
/*
* See stream_to_text in gdevpdf.c for why we need the following
* matrix adjustments.
*/
- pprintg6(pdev->strm, "%g %g %g %g %g %g Tm",
+ pprintg6(pdev->strm, "%g %g %g %g %g %g Tm\n",
pmat->xx * sx, pmat->xy * sy,
pmat->yx * sx, pmat->yy * sy,
pmat->tx * sx, pmat->ty * sy);
@@ -686,12 +835,12 @@ pdf_append_chars(gx_device_pdf * pdev, const byte * str, uint size)
while (left)
if (pdev->text.buffer_count == max_text_buffer) {
- int code = pdf_open_contents(pdev, pdf_in_text);
+ int code = pdf_open_page(pdev, PDF_IN_TEXT);
if (code < 0)
return code;
} else {
- int code = pdf_open_contents(pdev, pdf_in_string);
+ int code = pdf_open_page(pdev, PDF_IN_STRING);
uint copy;
if (code < 0)
@@ -705,15 +854,67 @@ pdf_append_chars(gx_device_pdf * pdev, const byte * str, uint size)
return 0;
}
-/* Begin a CharProc for an embedded (bitmap) font. */
+/* ---------------- Synthesized fonts ---------------- */
+
+/* Assign a code for a char_proc. */
+private int
+assign_char_code(gx_device_pdf * pdev)
+{
+ pdf_font_t *font = pdev->open_font;
+
+ if (font == 0) {
+ /* This is the very first synthesized font. */
+ /* Create the (canned) Encoding array. */
+ long id = pdf_begin_separate(pdev);
+ stream *s = pdev->strm;
+ int i;
+
+ /*
+ * Even though the PDF reference documentation says that a
+ * BaseEncoding key is required unless the encoding is
+ * "based on the base font's encoding" (and there is no base
+ * font in this case), Acrobat 2.1 gives an error if the
+ * BaseEncoding key is present.
+ */
+ pputs(s, "<</Type/Encoding/Differences[0");
+ for (i = 0; i < 256; ++i) {
+ if (!(i & 15))
+ pputs(s, "\n");
+ pprintd1(s, "/a%d", i);
+ }
+ pputs(s, "\n] >>\n");
+ pdf_end_separate(pdev);
+ pdev->embedded_encoding_id = id;
+ }
+ if (font == 0 || font->num_chars == 256) {
+ /* Start a new synthesized font. */
+ int code = pdf_alloc_font(pdev, gs_no_id, &font, false);
+ char *pc;
+
+ if (code < 0)
+ return code;
+ if (pdev->open_font == 0)
+ memset(font->frname, 0, sizeof(font->frname));
+ else
+ strcpy(font->frname, pdev->open_font->frname);
+ for (pc = font->frname; *pc == 'Z'; ++pc)
+ *pc = '@';
+ if ((*pc)++ == 0)
+ *pc = 'A', pc[1] = 0;
+ pdev->open_font = font;
+ }
+ return font->num_chars++;
+}
+
+/* Begin a CharProc for a synthesized (bitmap) font. */
int
pdf_begin_char_proc(gx_device_pdf * pdev, int w, int h, int x_width,
- int y_offset, gs_id id, pdf_char_proc ** ppcp, pdf_stream_position * ppos)
+ int y_offset, gs_id id, pdf_char_proc_t ** ppcp, pdf_stream_position_t * ppos)
{
- pdf_resource *pres;
- pdf_char_proc *pcp;
+ pdf_resource_t *pres;
+ pdf_char_proc_t *pcp;
int char_code = assign_char_code(pdev);
- pdf_font *font = pdev->open_font;
+ pdf_font_t *font = pdev->open_font;
int code;
if (char_code < 0)
@@ -721,7 +922,7 @@ pdf_begin_char_proc(gx_device_pdf * pdev, int w, int h, int x_width,
code = pdf_begin_resource(pdev, resourceCharProc, id, &pres);
if (code < 0)
return code;
- pcp = (pdf_char_proc *) pres;
+ pcp = (pdf_char_proc_t *) pres;
pcp->font = font;
pcp->char_next = font->char_procs;
font->char_procs = pcp;
@@ -749,7 +950,7 @@ pdf_begin_char_proc(gx_device_pdf * pdev, int w, int h, int x_width,
/* End a CharProc. */
int
-pdf_end_char_proc(gx_device_pdf * pdev, pdf_stream_position * ppos)
+pdf_end_char_proc(gx_device_pdf * pdev, pdf_stream_position_t * ppos)
{
stream *s = pdev->strm;
long start_pos = ppos->start_pos;
@@ -766,9 +967,9 @@ pdf_end_char_proc(gx_device_pdf * pdev, pdf_stream_position * ppos)
return 0;
}
-/* Put out a reference to an image as a character in an embedded font. */
+/* Put out a reference to an image as a character in a synthesized font. */
int
-pdf_do_char_image(gx_device_pdf * pdev, const pdf_char_proc * pcp,
+pdf_do_char_image(gx_device_pdf * pdev, const pdf_char_proc_t * pcp,
const gs_matrix * pimat)
{
pdf_set_font_and_size(pdev, pcp->font, 1.0);
diff --git a/gs/src/gdevpdfu.c b/gs/src/gdevpdfu.c
new file mode 100644
index 000000000..fe21cab52
--- /dev/null
+++ b/gs/src/gdevpdfu.c
@@ -0,0 +1,692 @@
+/* Copyright (C) 1999 Aladdin Enterprises. All rights reserved.
+
+ This file is part of Aladdin Ghostscript.
+
+ Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
+ or distributor accepts any responsibility for the consequences of using it,
+ or for whether it serves any particular purpose or works at all, unless he
+ or she says so in writing. Refer to the Aladdin Ghostscript Free Public
+ License (the "License") for full details.
+
+ Every copy of Aladdin Ghostscript must include a copy of the License,
+ normally in a plain ASCII text file named PUBLIC. The License grants you
+ the right to copy, modify and redistribute Aladdin Ghostscript, but only
+ under certain conditions described in the License. Among other things, the
+ License requires that the copyright notice and this notice be preserved on
+ all copies.
+ */
+
+
+/* Output utilities for PDF-writing driver */
+#include "math_.h"
+#include "memory_.h"
+#include "string_.h"
+#include "time_.h"
+#include "gx.h"
+#include "gp.h"
+#include "gserrors.h"
+#include "gxdevice.h"
+#include "gxfixed.h"
+#include "gxistate.h"
+#include "gxpaint.h"
+#include "gzpath.h"
+#include "gzcpath.h"
+#include "gdevpdfx.h"
+#include "scanchar.h"
+#include "strimpl.h" /* for short-sighted compilers */
+#include "scfx.h" /* s_CFE_template is default */
+#include "sstring.h"
+#include "szlibx.h"
+
+/* Define the size of internal stream buffers. */
+/* (This is not a limitation, it only affects performance.) */
+#define sbuf_size 512
+
+/* Optionally substitute other filters for FlateEncode for debugging. */
+#if 1
+# define compression_filter_name "FlateDecode"
+# define compression_filter_template s_zlibE_template
+# define compression_filter_state stream_zlib_state
+#else
+# include "slzwx.h"
+# define compression_filter_name "LZWDecode"
+# define compression_filter_template s_LZWE_template
+# define compression_filter_state stream_LZW_state
+#endif
+
+/* GC descriptors */
+private_st_pdf_resource();
+private_st_pdf_font();
+private_st_pdf_char_proc();
+
+/* ---------------- Utilities ---------------- */
+
+/* ------ Document ------ */
+
+/* Open the document if necessary. */
+void
+pdf_open_document(gx_device_pdf * pdev)
+{
+ if (!is_in_page(pdev) && pdf_stell(pdev) == 0) {
+ stream *s = pdev->strm;
+ int level = (int)(pdev->CompatibilityLevel * 10 + 0.5);
+
+ pprintd2(s, "%%PDF-%d.%d\n", level / 10, level % 10);
+ pdev->binary_ok = !pdev->params.ASCII85EncodePages;
+ if (pdev->binary_ok)
+ pputs(s, "%\307\354\217\242\n");
+ }
+ /*
+ * Determine the compression method. Currently this does nothing.
+ * It also isn't clear whether the compression method can now be
+ * changed in the course of the document.
+ *
+ * The following algorithm is per an update to TN # 5151 by
+ * Adobe Developer Support.
+ */
+ if (!pdev->params.CompressPages)
+ pdev->compression = pdf_compress_none;
+ else if (pdev->CompatibilityLevel < 1.2)
+ pdev->compression = pdf_compress_LZW;
+ else if (pdev->params.UseFlateCompression)
+ pdev->compression = pdf_compress_Flate;
+ else
+ pdev->compression = pdf_compress_LZW;
+}
+
+/* ------ Objects ------ */
+
+/* Allocate an object ID. */
+private long
+pdf_next_id(gx_device_pdf * pdev)
+{
+ return (pdev->next_id)++;
+}
+
+/*
+ * Return the current position in the output. Note that this may be in the
+ * main output file, the asides file, or the pictures file. If the current
+ * file is the pictures file, positions returned by pdf_stell must only be
+ * used locally (for computing lengths or patching), since there is no way
+ * to map them later to the eventual position in the output file.
+ */
+long
+pdf_stell(gx_device_pdf * pdev)
+{
+ stream *s = pdev->strm;
+ long pos = stell(s);
+
+ if (s == pdev->asides.strm)
+ pos += ASIDES_BASE_POSITION;
+ return pos;
+}
+
+/* Allocate an ID for a future object. */
+long
+pdf_obj_ref(gx_device_pdf * pdev)
+{
+ long id = pdf_next_id(pdev);
+ long pos = pdf_stell(pdev);
+
+ fwrite(&pos, sizeof(pos), 1, pdev->xref.file);
+ return id;
+}
+
+/* Begin an object, optionally allocating an ID. */
+long
+pdf_open_obj(gx_device_pdf * pdev, long id)
+{
+ stream *s = pdev->strm;
+
+ if (id <= 0) {
+ id = pdf_obj_ref(pdev);
+ } else {
+ long pos = pdf_stell(pdev);
+ FILE *tfile = pdev->xref.file;
+ long tpos = ftell(tfile);
+
+ fseek(tfile, (id - pdev->FirstObjectNumber) * sizeof(pos),
+ SEEK_SET);
+ fwrite(&pos, sizeof(pos), 1, tfile);
+ fseek(tfile, tpos, SEEK_SET);
+ }
+ pprintld1(s, "%ld 0 obj\n", id);
+ return id;
+}
+long
+pdf_begin_obj(gx_device_pdf * pdev)
+{
+ return pdf_open_obj(pdev, 0L);
+}
+
+/* End an object. */
+int
+pdf_end_obj(gx_device_pdf * pdev)
+{
+ pputs(pdev->strm, "endobj\n");
+ return 0;
+}
+
+/* ------ Graphics ------ */
+
+/* Reset the graphics state parameters to initial values. */
+void
+pdf_reset_graphics(gx_device_pdf * pdev)
+{
+ color_set_pure(&pdev->fill_color, 0); /* black */
+ color_set_pure(&pdev->stroke_color, 0); /* ditto */
+ pdev->flatness = -1;
+ {
+ static const gx_line_params lp_initial =
+ {gx_line_params_initial};
+
+ pdev->line_params = lp_initial;
+ }
+}
+
+/* Set the fill or stroke color. */
+int
+pdf_set_color(gx_device_pdf * pdev, gx_color_index color,
+ gx_drawing_color * pdcolor, const char *rgs)
+{
+ if (gx_dc_pure_color(pdcolor) != color) {
+ int code;
+
+ /*
+ * In principle, we can set colors in either stream or text
+ * context. However, since we currently enclose all text
+ * strings inside a gsave/grestore, this causes us to lose
+ * track of the color when we leave text context. Therefore,
+ * we require stream context for setting colors.
+ */
+#if 0
+ switch (pdev->context) {
+ case PDF_IN_STREAM:
+ case PDF_IN_TEXT:
+ break;
+ case PDF_IN_NONE:
+ code = pdf_open_page(pdev, PDF_IN_STREAM);
+ goto open;
+ case PDF_IN_STRING:
+ code = pdf_open_page(pdev, PDF_IN_TEXT);
+ open:if (code < 0)
+ return code;
+ }
+#else
+ code = pdf_open_page(pdev, PDF_IN_STREAM);
+ if (code < 0)
+ return code;
+#endif
+ color_set_pure(pdcolor, color);
+ psdf_set_color((gx_device_vector *) pdev, pdcolor, rgs);
+ }
+ return 0;
+}
+
+/* Write matrix values. */
+void
+pdf_put_matrix(gx_device_pdf * pdev, const char *before,
+ const gs_matrix * pmat, const char *after)
+{
+ stream *s = pdev->strm;
+
+ if (before)
+ pputs(s, before);
+ pprintg6(s, "%g %g %g %g %g %g ",
+ pmat->xx, pmat->xy, pmat->yx, pmat->yy, pmat->tx, pmat->ty);
+ if (after)
+ pputs(s, after);
+}
+
+/*
+ * Write a name, with escapes for unusual characters. In PDF 1.1, we have
+ * no choice but to replace these characters with '?'; in PDF 1.2, we can
+ * use an escape sequence for anything except a null <00>.
+ */
+void
+pdf_put_name(const gx_device_pdf * pdev, const byte * nstr, uint size)
+{
+ stream *s = pdev->strm;
+ uint i;
+ bool escape = pdev->CompatibilityLevel >= 1.2;
+ char hex[4];
+
+ pputc(s, '/');
+ for (i = 0; i < size; ++i) {
+ uint c = nstr[i];
+
+ switch (c) {
+ case '%':
+ case '(':
+ case ')':
+ case '<':
+ case '>':
+ case '[':
+ case ']':
+ case '{':
+ case '}':
+ /* These characters are invalid in both 1.1 and 1.2, */
+ /* but can be escaped in 1.2. */
+ if (escape) {
+ sprintf(hex, "#%02x", c);
+ pputs(s, hex);
+ break;
+ }
+ /* falls through */
+ case 0:
+ /* This is invalid in 1.1 and 1.2, and cannot be escaped. */
+ pputc(s, '?');
+ break;
+ case '/':
+ case '#':
+ /* These are valid in 1.1, but must be escaped in 1.2. */
+ if (escape) {
+ sprintf(hex, "#%02x", c);
+ pputs(s, hex);
+ break;
+ }
+ /* falls through */
+ default:
+ pputc(s, c);
+ }
+ }
+}
+
+/*
+ * Write a string in its shortest form ( () or <> ). Note that
+ * this form is different depending on whether binary data are allowed.
+ * We wish PDF supported ASCII85 strings ( <~ ~> ), but it doesn't.
+ */
+void
+pdf_put_string(const gx_device_pdf * pdev, const byte * str, uint size)
+{
+ psdf_write_string(pdev->strm, str, size,
+ (pdev->binary_ok ? PRINT_BINARY_OK : 0));
+}
+
+/* Write a value, treating names specially. */
+void
+pdf_write_value(const gx_device_pdf * pdev, const byte * vstr, uint size)
+{
+ if (size > 0 && vstr[0] == '/')
+ pdf_put_name(pdev, vstr + 1, size - 1);
+ else
+ pwrite(pdev->strm, vstr, size);
+}
+
+/* ------ Page contents ------ */
+
+/* Handle transitions between contexts. */
+private int
+ none_to_stream(P1(gx_device_pdf *)), stream_to_text(P1(gx_device_pdf *)),
+ string_to_text(P1(gx_device_pdf *)), text_to_stream(P1(gx_device_pdf *)),
+ stream_to_none(P1(gx_device_pdf *));
+typedef int (*context_proc) (P1(gx_device_pdf *));
+private const context_proc context_procs[4][4] =
+{
+ {0, none_to_stream, none_to_stream, none_to_stream},
+ {stream_to_none, 0, stream_to_text, stream_to_text},
+ {text_to_stream, text_to_stream, 0, 0},
+ {string_to_text, string_to_text, string_to_text, 0}
+};
+
+/* Enter stream context. */
+private int
+none_to_stream(gx_device_pdf * pdev)
+{
+ stream *s;
+
+ if (pdev->contents_id != 0)
+ return_error(gs_error_Fatal); /* only 1 contents per page */
+ pdev->contents_id = pdf_begin_obj(pdev);
+ pdev->contents_length_id = pdf_obj_ref(pdev);
+ s = pdev->strm;
+ pprintld1(s, "<</Length %ld 0 R", pdev->contents_length_id);
+ if (pdev->compression == pdf_compress_Flate)
+ pprints1(s, "/Filter /%s", compression_filter_name);
+ pputs(s, ">>\nstream\n");
+ pdev->contents_pos = pdf_stell(pdev);
+ if (pdev->compression == pdf_compress_Flate) { /* Set up the Flate filter. */
+ const stream_template *template = &compression_filter_template;
+ stream *es = s_alloc(pdev->pdf_memory, "PDF compression stream");
+ byte *buf = gs_alloc_bytes(pdev->pdf_memory, sbuf_size,
+ "PDF compression buffer");
+ compression_filter_state *st =
+ gs_alloc_struct(pdev->pdf_memory, compression_filter_state,
+ template->stype, "PDF compression state");
+
+ if (es == 0 || st == 0 || buf == 0)
+ return_error(gs_error_VMerror);
+ s_std_init(es, buf, sbuf_size, &s_filter_write_procs,
+ s_mode_write);
+ st->memory = pdev->pdf_memory;
+ st->template = template;
+ es->state = (stream_state *) st;
+ es->procs.process = template->process;
+ es->strm = s;
+ (*template->set_defaults) ((stream_state *) st);
+ (*template->init) ((stream_state *) st);
+ pdev->strm = s = es;
+ }
+ /* Scale the coordinate system. */
+ pprintg2(s, "%g 0 0 %g 0 0 cm\n",
+ 72.0 / pdev->HWResolution[0], 72.0 / pdev->HWResolution[1]);
+ /* Do a level of gsave for the clipping path. */
+ pputs(s, "q\n");
+ return PDF_IN_STREAM;
+}
+/* Enter text context from stream context. */
+private int
+stream_to_text(gx_device_pdf * pdev)
+{
+ /*
+ * Bizarrely enough, Acrobat Reader cares how the final font size is
+ * obtained -- the CTM (cm), text matrix (Tm), and font size (Tf)
+ * are *not* all equivalent. In particular, it seems to use the
+ * product of the text matrix and font size to decide how to
+ * anti-alias characters. Therefore, we have to temporarily patch
+ * the CTM so that the scale factors are unity. What a nuisance!
+ */
+ pprintg2(pdev->strm, "q %g 0 0 %g 0 0 cm BT\n",
+ pdev->HWResolution[0] / 72.0, pdev->HWResolution[1] / 72.0);
+ pdev->procsets |= Text;
+ gs_make_identity(&pdev->text.matrix);
+ pdev->text.line_start.x = pdev->text.line_start.y = 0;
+ pdev->text.buffer_count = 0;
+ return PDF_IN_TEXT;
+}
+/* Exit string context to text context. */
+private int
+string_to_text(gx_device_pdf * pdev)
+{
+ pdf_put_string(pdev, pdev->text.buffer, pdev->text.buffer_count);
+ pputs(pdev->strm, "Tj\n");
+ pdev->text.buffer_count = 0;
+ return PDF_IN_TEXT;
+}
+/* Exit text context to stream context. */
+private int
+text_to_stream(gx_device_pdf * pdev)
+{
+ pputs(pdev->strm, "ET Q\n");
+ pdev->text.font = 0; /* because of Q */
+ return PDF_IN_STREAM;
+}
+/* Exit stream context. */
+private int
+stream_to_none(gx_device_pdf * pdev)
+{
+ stream *s = pdev->strm;
+ long length;
+
+ if (pdev->compression == pdf_compress_Flate) { /* Terminate the Flate filter. */
+ stream *fs = s->strm;
+
+ sclose(s);
+ gs_free_object(pdev->pdf_memory, s->cbuf, "zlib buffer");
+ gs_free_object(pdev->pdf_memory, s, "zlib stream");
+ pdev->strm = s = fs;
+ }
+ length = pdf_stell(pdev) - pdev->contents_pos;
+ pputs(s, "endstream\n");
+ pdf_end_obj(pdev);
+ pdf_open_obj(pdev, pdev->contents_length_id);
+ pprintld1(s, "%ld\n", length);
+ pdf_end_obj(pdev);
+ return PDF_IN_NONE;
+}
+
+/* Begin a page contents part. */
+int
+pdf_open_contents(gx_device_pdf * pdev, pdf_context_t context)
+{
+ int (*proc) (P1(gx_device_pdf *));
+
+ while ((proc = context_procs[pdev->context][context]) != 0) {
+ int code = (*proc) (pdev);
+
+ if (code < 0)
+ return code;
+ pdev->context = (pdf_context_t) code;
+ }
+ pdev->context = context;
+ return 0;
+}
+
+/* Close the current contents part if we are in one. */
+int
+pdf_close_contents(gx_device_pdf * pdev, bool last)
+{
+ if (pdev->context == PDF_IN_NONE)
+ return 0;
+ if (last) { /* Exit from the clipping path gsave. */
+ pdf_open_contents(pdev, PDF_IN_STREAM);
+ pputs(pdev->strm, "Q\n");
+ pdev->text.font = 0;
+ }
+ return pdf_open_contents(pdev, PDF_IN_NONE);
+}
+
+/* ------ Resources et al ------ */
+
+/* Define the allocator descriptors for the resource types. */
+private const char *const resource_names[] = {
+ pdf_resource_type_names
+};
+private const gs_memory_struct_type_t *const resource_structs[] = {
+ pdf_resource_type_structs
+};
+
+/* Find a resource of a given type by gs_id. */
+pdf_resource_t *
+pdf_find_resource_by_gs_id(gx_device_pdf * pdev, pdf_resource_type_t rtype,
+ gs_id rid)
+{
+ pdf_resource_t **pchain = PDF_RESOURCE_CHAIN(pdev, rtype, rid);
+ pdf_resource_t **pprev = pchain;
+ pdf_resource_t *pres;
+
+ for (; (pres = *pprev) != 0; pprev = &pres->next)
+ if (pres->rid == rid) {
+ if (pprev != pchain) {
+ *pprev = pres->next;
+ pres->next = *pchain;
+ *pchain = pres;
+ }
+ return pres;
+ }
+ return 0;
+}
+
+/* Begin an object logically separate from the contents. */
+long
+pdf_open_separate(gx_device_pdf * pdev, long id)
+{
+ pdf_open_document(pdev);
+ pdev->asides.save_strm = pdev->strm;
+ pdev->strm = pdev->asides.strm;
+ return pdf_open_obj(pdev, id);
+}
+long
+pdf_begin_separate(gx_device_pdf * pdev)
+{
+ return pdf_open_separate(pdev, 0L);
+}
+
+/* Begin an aside (resource, annotation, ...). */
+private int
+pdf_alloc_aside(gx_device_pdf * pdev, pdf_resource_t ** plist,
+ const gs_memory_struct_type_t * pst, pdf_resource_t **ppres,
+ long id)
+{
+ pdf_resource_t *pres;
+ cos_object_t *object;
+
+ if (pst == NULL)
+ pst = &st_pdf_resource;
+ pres = gs_alloc_struct(pdev->pdf_memory, pdf_resource_t, pst,
+ "pdf_alloc_aside(resource)");
+ object = cos_object_alloc(pdev->pdf_memory, "pdf_alloc_aside(object)");
+ if (pres == 0 || object == 0) {
+ return_error(gs_error_VMerror);
+ }
+ object->id = (id < 0 ? -1L : id == 0 ? pdf_obj_ref(pdev) : id);
+ pres->next = *plist;
+ *plist = pres;
+ pres->prev = pdev->last_resource;
+ pdev->last_resource = pres;
+ pres->named = false;
+ pres->used_on_page = true;
+ pres->object = object;
+ *ppres = pres;
+ return 0;
+}
+int
+pdf_begin_aside(gx_device_pdf * pdev, pdf_resource_t ** plist,
+ const gs_memory_struct_type_t * pst, pdf_resource_t ** ppres)
+{
+ long id = pdf_begin_separate(pdev);
+
+ if (id < 0)
+ return (int)id;
+ return pdf_alloc_aside(pdev, plist, pst, ppres, id);
+}
+
+/* Begin a resource of a given type. */
+int
+pdf_begin_resource_body(gx_device_pdf * pdev, pdf_resource_type_t rtype,
+ gs_id rid, pdf_resource_t ** ppres)
+{
+ return pdf_begin_aside(pdev, PDF_RESOURCE_CHAIN(pdev, rtype, rid),
+ resource_structs[rtype], ppres);
+}
+int
+pdf_begin_resource(gx_device_pdf * pdev, pdf_resource_type_t rtype, gs_id rid,
+ pdf_resource_t ** ppres)
+{
+ int code = pdf_begin_resource_body(pdev, rtype, rid, ppres);
+
+ if (code >= 0 && resource_names[rtype] != 0) {
+ stream *s = pdev->strm;
+
+ pprints1(s, "<</Type/%s", resource_names[rtype]);
+ pprintld1(s, "/Name/R%ld", (*ppres)->object->id);
+ }
+ return code;
+}
+
+/* Allocate a resource, but don't open the stream. */
+int
+pdf_alloc_resource(gx_device_pdf * pdev, pdf_resource_type_t rtype, gs_id rid,
+ pdf_resource_t ** ppres, long id)
+{
+ return pdf_alloc_aside(pdev, PDF_RESOURCE_CHAIN(pdev, rtype, rid),
+ resource_structs[rtype], ppres, id);
+}
+
+/* End an aside or other separate object. */
+int
+pdf_end_separate(gx_device_pdf * pdev)
+{
+ int code = pdf_end_obj(pdev);
+
+ pdev->strm = pdev->asides.save_strm;
+ pdev->asides.save_strm = 0;
+ return code;
+}
+int
+pdf_end_aside(gx_device_pdf * pdev)
+{
+ return pdf_end_separate(pdev);
+}
+
+/* End a resource. */
+int
+pdf_end_resource(gx_device_pdf * pdev)
+{
+ return pdf_end_aside(pdev);
+}
+
+/* Copy data from a temporary file to a stream. */
+void
+pdf_copy_data(stream *s, FILE *file, long count)
+{
+ long left = count;
+ byte buf[sbuf_size];
+
+ while (left > 0) {
+ uint copy = min(left, sbuf_size);
+
+ fread(buf, 1, sbuf_size, file);
+ pwrite(s, buf, copy);
+ left -= copy;
+ }
+}
+
+/* ------ Pages ------ */
+
+/* Get or assign the ID for a page. */
+/* Returns 0 if the page number is out of range. */
+long
+pdf_page_id(gx_device_pdf * pdev, int page_num)
+{
+ cos_dict_t *Page;
+
+ if (page_num < 1)
+ return 0;
+ if (page_num >= pdev->num_pages) { /* Grow the pages array. */
+ uint new_num_pages =
+ max(page_num + 10, pdev->num_pages << 1);
+ pdf_page_t *new_pages =
+ gs_resize_object(pdev->pdf_memory, pdev->pages, new_num_pages,
+ "pdf_page_id(resize pages)");
+
+ if (new_pages == 0)
+ return 0;
+ memset(&new_pages[pdev->num_pages], 0,
+ (new_num_pages - pdev->num_pages) * sizeof(pdf_page_t));
+ pdev->pages = new_pages;
+ pdev->num_pages = new_num_pages;
+ }
+ if ((Page = pdev->pages[page_num - 1].Page) == 0) {
+ pdev->pages[page_num - 1].Page = Page =
+ cos_dict_alloc(pdev->pdf_memory, "pdf_page_id");
+ Page->id = pdf_obj_ref(pdev);
+ }
+ return Page->id;
+}
+
+/* Get the dictionary object for the current page. */
+cos_dict_t *
+pdf_current_page_dict(gx_device_pdf *pdev)
+{
+ if (pdf_page_id(pdev, pdev->next_page + 1) <= 0)
+ return 0;
+ return pdev->pages[pdev->next_page].Page;
+}
+
+/* Write saved page- or document-level information. */
+int
+pdf_write_saved_string(gx_device_pdf * pdev, gs_string * pstr)
+{
+ if (pstr->data != 0) {
+ pwrite(pdev->strm, pstr->data, pstr->size);
+ gs_free_string(pdev->pdf_memory, pstr->data, pstr->size,
+ "pdf_write_saved_string");
+ pstr->data = 0;
+ }
+ return 0;
+}
+
+/* Open a page for writing. */
+int
+pdf_open_page(gx_device_pdf * pdev, pdf_context_t context)
+{
+ if (!is_in_page(pdev)) {
+ if (pdf_page_id(pdev, pdev->next_page + 1) == 0)
+ return_error(gs_error_VMerror);
+ pdf_open_document(pdev);
+ }
+ /* Note that context may be PDF_IN_NONE here. */
+ return pdf_open_contents(pdev, context);
+}
diff --git a/gs/src/gdevpdfx.h b/gs/src/gdevpdfx.h
index 6718fe210..d0162df6d 100644
--- a/gs/src/gdevpdfx.h
+++ b/gs/src/gdevpdfx.h
@@ -23,103 +23,201 @@
# define gdevpdfx_INCLUDED
#include "gsparam.h"
+#include "gsuid.h"
#include "gxdevice.h"
+#include "gxfont.h"
#include "gxline.h"
#include "stream.h"
-#include "gdevpstr.h"
+#include "spprint.h"
#include "gdevpsdf.h"
+#include "gdevpdfo.h"
/* ---------------- Statically allocated sizes ---------------- */
-/* These should all really be dynamic.... */
-
-/* Define the maximum number of contents fragments on a page. */
-#define max_contents_ids 300
+/* These should really be dynamic.... */
/* Define the maximum depth of an outline tree. */
/* Note that there is no limit on the breadth of the tree. */
-#define max_outline_depth 8
+#define MAX_OUTLINE_DEPTH 8
/* Define the maximum size of a destination array string. */
-#define max_dest_string 80
+#define MAX_DEST_STRING 80
/* ================ Types and structures ================ */
+/* Define the possible contexts for the output stream. */
+typedef enum {
+ PDF_IN_NONE,
+ PDF_IN_STREAM,
+ PDF_IN_TEXT,
+ PDF_IN_STRING
+} pdf_context_t;
+
/* ---------------- Resources ---------------- */
typedef enum {
- /* Standard PDF resources. */
- resourceFont,
- resourceEncoding,
- resourceFontDescriptor,
+ /*
+ * Standard PDF resources. Font must be last, because resources
+ * up to but not including Font are written page-by-page.
+ */
resourceColorSpace,
- resourceImageXObject,
+ /*resourceExtGState,*/ /* not needed */
resourcePattern,
- /* Internally used resources. */
+ /*resourceShading,*/ /* not needed */
+ resourceXObject,
+ resourceFont,
+ /*
+ * Internally used (pseudo-)resources.
+ */
resourceCharProc,
- resourceNamedObject,
- num_resource_types
-} pdf_resource_type;
+ NUM_RESOURCE_TYPES
+} pdf_resource_type_t;
#define pdf_resource_type_names\
- "Font", "Encoding", "FontDescriptor", "ColorSpace", "XObject",\
- "Pattern", 0, 0, 0
+ "ColorSpace", "Pattern", "XObject", "Font",\
+ 0
#define pdf_resource_type_structs\
- &st_pdf_font, &st_pdf_resource, &st_pdf_resource, &st_pdf_resource,\
- &st_pdf_resource, &st_pdf_resource, &st_pdf_char_proc, &st_pdf_named_object
+ &st_pdf_resource, &st_pdf_resource, &st_pdf_resource, &st_pdf_font,\
+ &st_pdf_char_proc
#define pdf_resource_common(typ)\
- typ *next; /* next resource of this type */\
- pdf_resource *prev; /* previously allocated resource */\
- gs_id rid; /* optional key */\
- long id
-typedef struct pdf_resource_s pdf_resource;
+ typ *next; /* next resource of this type */\
+ pdf_resource_t *prev; /* previously allocated resource */\
+ gs_id rid; /* optional ID key */\
+ bool named;\
+ bool used_on_page;\
+ cos_object_t *object
+typedef struct pdf_resource_s pdf_resource_t;
struct pdf_resource_s {
- pdf_resource_common(pdf_resource);
+ pdf_resource_common(pdf_resource_t);
};
#define private_st_pdf_resource()\
- gs_private_st_ptrs2(st_pdf_resource, pdf_resource, "pdf_resource",\
- pdf_resource_enum_ptrs, pdf_resource_reloc_ptrs, next, prev)
+ gs_private_st_ptrs3(st_pdf_resource, pdf_resource_t, "pdf_resource_t",\
+ pdf_resource_enum_ptrs, pdf_resource_reloc_ptrs, next, prev, object)
+
+/* ------ Fonts ------ */
+
+/*
+ * The PDF writer creates 3 different kinds of font resources:
+ *
+ * - Synthesized Type 3 bitmap fonts, identified by num_chars != 0
+ * (or equivalently PDF_FONT_IS_SYNTHESIZED = true).
+ *
+ * - Non-embedded Type 1 or TrueType fonts, identified by num_chars == 0,
+ * descriptor != 0, descriptor->FontFile_id == 0. A font is in the
+ * base 14 iff index >= 0.
+ *
+ * - Embedded Type 1 or TrueType fonts, identified by num_chars == 0,
+ * descriptor != 0, descriptor->FontFile_id != 0.
+ */
+
+#define PDF_NUM_STD_FONTS 14
+#define pdf_do_std_fonts(m)\
+ m("Courier", ENCODING_INDEX_STANDARD)\
+ m("Courier-Bold", ENCODING_INDEX_STANDARD)\
+ m("Courier-Oblique", ENCODING_INDEX_STANDARD)\
+ m("Courier-BoldOblique", ENCODING_INDEX_STANDARD)\
+ m("Helvetica", ENCODING_INDEX_STANDARD)\
+ m("Helvetica-Bold", ENCODING_INDEX_STANDARD)\
+ m("Helvetica-Oblique", ENCODING_INDEX_STANDARD)\
+ m("Helvetica-BoldOblique", ENCODING_INDEX_STANDARD)\
+ m("Symbol", ENCODING_INDEX_SYMBOL)\
+ m("Times-Roman", ENCODING_INDEX_STANDARD)\
+ m("Times-Bold", ENCODING_INDEX_STANDARD)\
+ m("Times-Italic", ENCODING_INDEX_STANDARD)\
+ m("Times-BoldItalic", ENCODING_INDEX_STANDARD)\
+ m("ZapfDingbats", ENCODING_INDEX_DINGBATS)
+
+/* Font descriptors (not handled as separate resources) */
+typedef struct pdf_font_descriptor_s {
+ long id;
+ /* Required elements */
+ int Ascent, CapHeight, Descent, ItalicAngle, StemV;
+ gs_int_rect FontBBox;
+ uint Flags;
+ /* Optional elements (default to 0) */
+ long FontFile_id;
+ int AvgWidth, Leading, MaxWidth, MissingWidth, StemH, XHeight;
+} pdf_font_descriptor_t;
+/* Flag bits */
+/*#define FONT_IS_FIXED_WIDTH (1<<0)*/ /* define in gxfont.h */
+#define FONT_IS_SERIF (1<<1)
+#define FONT_IS_SYMBOLIC (1<<2)
+#define FONT_IS_SCRIPT (1<<3)
+#define FONT_IS_ADOBE_ROMAN (1<<5)
+#define FONT_IS_ITALIC (1<<6)
+#define FONT_IS_ALL_CAPS (1<<16)
+#define FONT_IS_SMALL_CAPS (1<<17)
+#define FONT_IS_FORCE_BOLD (1<<18)
+#define private_st_pdf_font_descriptor()\
+ gs_private_st_simple(st_pdf_font_descriptor, pdf_font_descriptor_t,\
+ "pdf_font_descriptor_t")
/* Font resources */
-typedef struct pdf_char_proc_s pdf_char_proc; /* forward reference */
-typedef struct pdf_font_s pdf_font;
+typedef struct pdf_char_proc_s pdf_char_proc_t; /* forward reference */
+typedef struct pdf_font_s pdf_font_t;
+/*
+ * PDF font names must be large enough for the 14 built-in fonts,
+ * and also large enough for any reasonable font name + 7 characters
+ * for the subsetting prefix.
+ */
+#define MAX_PDF_FONT_NAME (7 + gs_font_name_max + 1)
typedef struct pdf_font_name_s {
- byte chars[40]; /* arbitrary, must be large enough for */
- /* the 14 built-in fonts */
+ byte chars[MAX_PDF_FONT_NAME];
uint size;
-} pdf_font_name;
+} pdf_font_name_t;
+typedef struct pdf_encoding_element_s {
+ gs_glyph glyph;
+ gs_const_string str;
+} pdf_encoding_element_t;
+#define private_st_pdf_encoding_element()\
+ gs_private_st_composite(st_pdf_encoding_element, pdf_encoding_element_t,\
+ "pdf_encoding_element_t[]", pdf_encoding_elt_enum_ptrs,\
+ pdf_encoding_elt_reloc_ptrs)
struct pdf_font_s {
- pdf_resource_common(pdf_font);
- pdf_font_name fname;
- bool used_on_page;
- char frname[6 + 1]; /* xxxxxx\0 */
+ pdf_resource_common(pdf_font_t);
+ pdf_font_name_t fname;
+ font_type FontType;
+ gs_font *font; /* non-0 iff font will notify us; */
+ /* should be a weak pointer */
+ int index; /* in pdf_standard_fonts */
+ gs_matrix orig_matrix; /* FontMatrix of unscaled font for embedding */
+ /*
+ * For synthesized fonts, frname is A, B, ...; for other fonts,
+ * frname is R<id>. The string is null-terminated.
+ */
+ char frname[1/*R*/ + (sizeof(long) * 8 / 3 + 1) + 1/*\0*/];
/* Encoding differences for base fonts. */
byte chars_used[32]; /* 1 bit per character code */
- gs_const_string *differences;
+ pdf_encoding_element_t *differences; /* [256] */
long diff_id;
- /* Bookkeeping for embedded fonts. */
+ /* Bookkeeping for non-synthesized fonts. */
+ pdf_font_descriptor_t *descriptor;
+ int Widths[256];
+ byte widths_known[32]; /* 1 bit per character code */
+ bool skip; /* font was already written, skip it */
+ /* Bookkeeping for synthesized fonts. */
int num_chars;
-#define font_is_embedded(font) ((font)->num_chars != 0)
- pdf_char_proc *char_procs;
+#define PDF_FONT_IS_SYNTHESIZED(pdfont) ((pdfont)->num_chars != 0)
+ pdf_char_proc_t *char_procs;
int max_y_offset;
/* Pseudo-characters for spacing. */
/* The range should be determined by the device resolution.... */
-#define x_space_min 24
-#define x_space_max 150
- byte spaces[x_space_max - x_space_min + 1];
+#define X_SPACE_MIN 24
+#define X_SPACE_MAX 150
+ byte spaces[X_SPACE_MAX - X_SPACE_MIN + 1];
};
#define private_st_pdf_font()\
- gs_private_st_suffix_add2(st_pdf_font, pdf_font, "pdf_font",\
+ gs_private_st_suffix_add4(st_pdf_font, pdf_font_t, "pdf_font_t",\
pdf_font_enum_ptrs, pdf_font_reloc_ptrs, st_pdf_resource,\
- differences, char_procs)
+ font, differences, descriptor, char_procs)
-/* CharProc pseudo-resources for embedded fonts */
+/* CharProc pseudo-resources for synthesized fonts */
struct pdf_char_proc_s {
- pdf_resource_common(pdf_char_proc);
- pdf_font *font;
- pdf_char_proc *char_next; /* next char_proc for same font */
+ pdf_resource_common(pdf_char_proc_t);
+ pdf_font_t *font;
+ pdf_char_proc_t *char_next; /* next char_proc for same font */
int width, height;
int x_width; /* X escapement */
int y_offset; /* of character (0,0) */
@@ -127,48 +225,26 @@ struct pdf_char_proc_s {
};
#define private_st_pdf_char_proc()\
- gs_private_st_suffix_add2(st_pdf_char_proc, pdf_char_proc,\
- "pdf_char_proc", pdf_char_proc_enum_ptrs,\
+ gs_private_st_suffix_add2(st_pdf_char_proc, pdf_char_proc_t,\
+ "pdf_char_proc_t", pdf_char_proc_enum_ptrs,\
pdf_char_proc_reloc_ptrs, st_pdf_resource, font, char_next)
-/* Named object pseudo-resources. */
-/*
- * The elements of arrays are stored sorted in decreasing index order.
- * The elements of dictionaries are not sorted.
- * The elements of streams don't use the key, and are stored in
- * reverse order.
- */
-typedef struct pdf_named_element_s pdf_named_element;
-struct pdf_named_element_s {
- pdf_named_element *next;
- gs_string key; /* if array, data = 0, size = index */
- gs_string value;
-};
-typedef enum {
- named_unknown, /* forward reference */
- named_array, named_dict, named_stream, /* OBJ or predefined */
- named_graphics, /* BP/EP */
- named_other /* ANN, DEST, LNK, PS */
-} pdf_named_object_type;
-
-#define private_st_pdf_named_element() /* in gdevpdfo.c */\
- gs_private_st_composite(st_pdf_named_element, pdf_named_element,\
- "pdf_named_element", pdf_named_elt_enum_ptrs, pdf_named_elt_reloc_ptrs)
-typedef struct pdf_named_object_s pdf_named_object;
-struct pdf_named_object_s {
- pdf_resource_common(pdf_named_object);
- pdf_named_object_type type;
- gs_string key;
- pdf_named_element *elements; /* (extra key/value pairs for graphics) */
- bool open; /* stream, graphics */
- struct gr_ { /* graphics only */
- pdf_named_object *enclosing;
- } graphics;
+/* ------ Named objects ------ */
+
+/* Define an element of the graphics object accumulation (BP/EP) stack. */
+typedef struct pdf_graphics_save_s pdf_graphics_save_t;
+struct pdf_graphics_save_s {
+ pdf_graphics_save_t *prev;
+ cos_stream_t *object;
+ long position;
+ pdf_context_t save_context;
+ long save_contents_id;
};
-#define public_st_pdf_named_object() /* in gdevpdfo.c */\
- gs_public_st_composite(st_pdf_named_object, pdf_named_object,\
- "pdf_named_object", pdf_named_obj_enum_ptrs, pdf_named_obj_reloc_ptrs)
+#define private_st_pdf_graphics_save() /* in gdevpdfm.c */\
+ gs_private_st_ptrs2(st_pdf_graphics_save, pdf_graphics_save_t,\
+ "pdf_graphics_save_t", pdf_graphics_save_enum_ptrs,\
+ pdf_graphics_save_reloc_ptrs, prev, object)
/* ---------------- Other auxiliary structures ---------------- */
@@ -176,53 +252,47 @@ struct pdf_named_object_s {
typedef struct pdf_outline_node_s {
long id, parent_id, prev_id, first_id, last_id;
int count;
- gs_string action_string;
-} pdf_outline_node;
+ cos_dict_t *action;
+} pdf_outline_node_t;
typedef struct pdf_outline_level_s {
- pdf_outline_node first;
- pdf_outline_node last;
+ pdf_outline_node_t first;
+ pdf_outline_node_t last;
int left;
-} pdf_outline_level;
+} pdf_outline_level_t;
+/*
+ * The GC descriptor is implicit, since outline levels occur only in an
+ * embedded array in the gx_device_pdf structure.
+ */
/* Articles */
typedef struct pdf_bead_s {
long id, article_id, prev_id, next_id, page_id;
gs_rect rect;
-} pdf_bead;
-typedef struct pdf_article_s pdf_article;
+} pdf_bead_t;
+typedef struct pdf_article_s pdf_article_t;
struct pdf_article_s {
- pdf_article *next;
- gs_string title;
- gs_string info;
- long id;
- pdf_bead first;
- pdf_bead last;
+ pdf_article_t *next;
+ cos_dict_t *contents;
+ pdf_bead_t first;
+ pdf_bead_t last;
};
#define private_st_pdf_article()\
- gs_private_st_ptrs1_strings2(st_pdf_article, pdf_article, "pdf_article",\
- pdf_article_enum_ptrs, pdf_article_reloc_ptrs, next, title, info)
-
-/* Named destinations */
-typedef struct pdf_named_dest_s pdf_named_dest;
-struct pdf_named_dest_s {
- pdf_named_dest *next;
- gs_string key;
- char dest[max_dest_string];
-};
-
-#define private_st_pdf_named_dest()\
- gs_private_st_ptrs1_strings1(st_pdf_named_dest, pdf_named_dest,\
- "pdf_named_dest", pdf_named_dest_enum_ptrs, pdf_named_dest_reloc_ptrs,\
- next, key)
+ gs_private_st_ptrs2(st_pdf_article, pdf_article_t,\
+ "pdf_article_t", pdf_article_enum_ptrs, pdf_article_reloc_ptrs,\
+ next, contents)
/* ---------------- The device structure ---------------- */
/* Text state */
+typedef struct pdf_std_font_s {
+ gs_matrix orig_matrix;
+ gs_uid uid;
+} pdf_std_font_t;
typedef struct pdf_text_state_s {
/* State parameters */
float character_spacing;
- pdf_font *font;
+ pdf_font_t *font;
floatp size;
float word_spacing;
float horizontal_scaling;
@@ -233,28 +303,32 @@ typedef struct pdf_text_state_s {
#define max_text_buffer 200 /* arbitrary, but overflow costs 5 chars */
byte buffer[max_text_buffer];
int buffer_count;
-} pdf_text_state;
+ pdf_std_font_t std_fonts[PDF_NUM_STD_FONTS]; /* must be last (can't initialize) */
+} pdf_text_state_t;
#define pdf_text_state_default\
0, NULL, 0, 0, 100,\
{ identity_matrix_body }, { 0, 0 }, { 0, 0 }, { 0 }, 0
/* Resource lists */
-#define num_resource_chains 16
+#define NUM_RESOURCE_CHAINS 16
typedef struct pdf_resource_list_s {
- pdf_resource *chains[num_resource_chains];
-} pdf_resource_list;
+ pdf_resource_t *chains[NUM_RESOURCE_CHAINS];
+} pdf_resource_list_t;
/* Define the hash function for gs_ids. */
-#define gs_id_hash(rid) ((rid) + ((rid) / num_resource_chains))
+#define gs_id_hash(rid) ((rid) + ((rid) / NUM_RESOURCE_CHAINS))
+/* Define the accessor for the proper hash chain. */
+#define PDF_RESOURCE_CHAIN(pdev, type, rid)\
+ (&(pdev)->resources[type].chains[gs_id_hash(rid) % NUM_RESOURCE_CHAINS])
/* Define the bookkeeping for an open stream. */
typedef struct pdf_stream_position_s {
long length_id;
long start_pos;
-} pdf_stream_position;
+} pdf_stream_position_t;
-/* Define the device structure. */
+/* Define the mask for which procsets have been used on a page. */
typedef enum {
NoMarks = 0,
ImageB = 1,
@@ -262,13 +336,43 @@ typedef enum {
ImageI = 4,
Text = 8
} pdf_procset;
-typedef enum {
- pdf_in_none,
- pdf_in_stream,
- pdf_in_text,
- pdf_in_string
-} pdf_context;
-typedef struct gx_device_pdf_s {
+
+/*
+ * Define the stored information for a page. Because pdfmarks may add
+ * information to any page anywhere in the document, we have to wait
+ * until the end to write out the page dictionaries.
+ */
+typedef struct pdf_page_s {
+ cos_dict_t *Page;
+ gs_int_point MediaBox;
+ pdf_procset procsets;
+ long contents_id;
+ long resource_ids[resourceFont]; /* resources up to Font, see above */
+ long fonts_id;
+ cos_array_t *Annots;
+} pdf_page_t;
+#define private_st_pdf_page() /* in gdevpdf.c */\
+ gs_private_st_ptrs2(st_pdf_page, pdf_page_t, "pdf_page_t",\
+ pdf_page_enum_ptrs, pdf_page_reloc_ptrs, Page, Annots)
+
+/*
+ * Define the structure for the temporary files used while writing.
+ * There are 4 of these, described below.
+ */
+typedef struct pdf_temp_file_s {
+ char file_name[gp_file_name_sizeof];
+ FILE *file;
+ stream *strm;
+ byte *strm_buf;
+ stream *save_strm; /* save pdev->strm while writing here */
+} pdf_temp_file_t;
+
+/* Define the device structure. */
+#ifndef gx_device_pdf_DEFINED
+# define gx_device_pdf_DEFINED
+typedef struct gx_device_pdf_s gx_device_pdf_t;
+#endif
+struct gx_device_pdf_s {
gx_device_psdf_common;
/* PDF-specific distiller parameters */
float CompatibilityLevel;
@@ -285,27 +389,48 @@ typedef struct gx_device_pdf_s {
pdf_compress_Flate
} compression;
#define pdf_memory v_memory
- char tfname[gp_file_name_sizeof];
- FILE *tfile;
- char rfname[gp_file_name_sizeof];
- FILE *rfile;
- stream *rstrm;
- byte *rstrmbuf;
- stream *rsave_strm;
- pdf_font *open_font;
+ /*
+ * The xref temporary file is logically an array of longs.
+ * xref[id - FirstObjectNumber] is the position in the output file
+ * of the object with the given id.
+ *
+ * Note that xref, unlike the other temporary files, does not have
+ * an associated stream or stream buffer.
+ */
+ pdf_temp_file_t xref;
+ /*
+ * asides holds resources and other "aside" objects. It is
+ * copied verbatim to the output file at the end of the document.
+ */
+ pdf_temp_file_t asides;
+ /*
+ * streams holds data for stream-type Cos objects. The data is
+ * copied to the output file at the end of the document.
+ *
+ * Note that streams.save_strm is not used, since we don't interrupt
+ * normal output when saving stream data.
+ */
+ pdf_temp_file_t streams;
+ /*
+ * pictures holds graphic objects being accumulated between BP and EP.
+ * The object is moved to streams when the EP is reached: since BP and
+ * EP nest, we delete the object from the pictures file at that time.
+ */
+ pdf_temp_file_t pictures;
+ pdf_font_t *open_font;
long embedded_encoding_id;
/* ................ */
long next_id;
- /* The following 2 IDs, and only these, are allocated */
+ /* The following 3 objects, and only these, are allocated */
/* when the file is opened. */
- long root_id;
- long info_id;
-#define pdf_num_initial_ids 2
- long pages_id;
+ cos_dict_t *Catalog;
+ cos_dict_t *Info;
+ cos_dict_t *Pages;
+#define pdf_num_initial_ids 3
long outlines_id;
int next_page;
long contents_id;
- pdf_context context;
+ pdf_context_t context;
long contents_length_id;
long contents_pos;
pdf_procset procsets; /* used on this page */
@@ -315,63 +440,81 @@ typedef struct gx_device_pdf_s {
/* are in default user space units. */
gx_line_params line_params; /* current values */
/****** SHOULD USE state ******/
- pdf_text_state text;
- long space_char_ids[x_space_max - x_space_min + 1];
-#define initial_num_page_ids 50
- long *page_ids;
- int num_page_ids;
- int pages_referenced;
- pdf_resource_list resources[num_resource_types];
- pdf_resource *cs_Pattern;
- pdf_resource *annots; /* rid = page # */
- pdf_resource *last_resource;
- gs_string catalog_string;
- gs_string pages_string;
- gs_string page_string;
- pdf_outline_level outline_levels[max_outline_depth];
+ pdf_text_state_t text;
+ long space_char_ids[X_SPACE_MAX - X_SPACE_MIN + 1];
+#define initial_num_pages 50
+ pdf_page_t *pages;
+ int num_pages;
+ pdf_resource_list_t resources[NUM_RESOURCE_TYPES];
+ pdf_resource_t *cs_Pattern;
+ pdf_resource_t *last_resource;
+ pdf_outline_level_t outline_levels[MAX_OUTLINE_DEPTH];
int outline_depth;
int closed_outline_depth;
int outlines_open;
- pdf_article *articles;
- pdf_named_dest *named_dests;
- pdf_named_object *named_objects;
- pdf_named_object *open_graphics;
-} gx_device_pdf;
+ pdf_article_t *articles;
+ cos_dict_t *Dests;
+ cos_dict_t *named_objects;
+ pdf_graphics_save_t *open_graphics;
+};
#define is_in_page(pdev)\
((pdev)->contents_id != 0)
#define is_in_document(pdev)\
(is_in_page(pdev) || (pdev)->last_resource != 0)
-/* Enumerate the individual pointers in a gx_device_pdf */
+/* Enumerate the individual pointers in a gx_device_pdf. */
#define gx_device_pdf_do_ptrs(m)\
- m(0,rstrm) m(1,rstrmbuf) m(2,rsave_strm) m(3,open_font)\
- m(4,line_params.dash.pattern) m(5,text.font) m(6,page_ids) m(7,annots)\
- m(8,last_resource) m(9,articles) m(10,named_dests)\
- m(11,named_objects) m(12,open_graphics)
-#define gx_device_pdf_num_ptrs 13 /* + num_resource_types */
-#define gx_device_pdf_do_strings(m)\
- m(0,catalog_string) m(1,pages_string) m(2,page_string)
-#define gx_device_pdf_num_strings 3 /* + max_outline_depth * 2 */
+ m(0,asides.strm) m(1,asides.strm_buf) m(2,asides.save_strm)\
+ m(3,streams.strm) m(4,streams.strm_buf)\
+ m(5,pictures.strm) m(6,pictures.strm_buf) m(7,pictures.save_strm)\
+ m(8,open_font)\
+ m(9,Catalog) m(10,Info) m(11,Pages)\
+ m(12,line_params.dash.pattern) m(13,text.font) m(14,pages)\
+ m(15,cs_Pattern) m(16,last_resource)\
+ m(17,articles) m(18,Dests) m(19,named_objects) m(20,open_graphics)
+#define gx_device_pdf_num_ptrs 21
+#define gx_device_pdf_do_strings(m) /* do nothing */
+#define gx_device_pdf_num_strings 0
#define st_device_pdf_max_ptrs\
(st_device_psdf_max_ptrs + gx_device_pdf_num_ptrs +\
- gx_device_pdf_num_strings + num_resource_types * num_resource_chains +\
- max_outline_depth * 2)
+ gx_device_pdf_num_strings + NUM_RESOURCE_TYPES * NUM_RESOURCE_CHAINS +\
+ MAX_OUTLINE_DEPTH * 2)
#define private_st_device_pdfwrite() /* in gdevpdf.c */\
gs_private_st_composite_final(st_device_pdfwrite, gx_device_pdf,\
"gx_device_pdf", device_pdfwrite_enum_ptrs, device_pdfwrite_reloc_ptrs,\
device_pdfwrite_finalize)
+/* ================ Driver procedures ================ */
+
+ /* In gdevpdfd.c */
+dev_proc_fill_rectangle(gdev_pdf_fill_rectangle);
+dev_proc_fill_path(gdev_pdf_fill_path);
+dev_proc_stroke_path(gdev_pdf_stroke_path);
+ /* In gdevpdfi.c */
+dev_proc_copy_mono(gdev_pdf_copy_mono);
+dev_proc_copy_color(gdev_pdf_copy_color);
+dev_proc_fill_mask(gdev_pdf_fill_mask);
+dev_proc_begin_image(gdev_pdf_begin_image);
+dev_proc_strip_tile_rectangle(gdev_pdf_strip_tile_rectangle);
+ /* In gdevpdfp.c */
+dev_proc_get_params(gdev_pdf_get_params);
+dev_proc_put_params(gdev_pdf_put_params);
+ /* In gdevpdft.c */
+dev_proc_text_begin(gdev_pdf_text_begin);
+
/* ================ Utility procedures ================ */
/* ---------------- Exported by gdevpdf.c ---------------- */
-/* ------ Document ------ */
-
/* Initialize the IDs allocated at startup. */
void pdf_initialize_ids(P1(gx_device_pdf * pdev));
+/* ---------------- Exported by gdevpdfu.c ---------------- */
+
+/* ------ Document ------ */
+
/* Open the document if necessary. */
void pdf_open_document(P1(gx_device_pdf * pdev));
@@ -385,9 +528,7 @@ long pdf_stell(P1(gx_device_pdf * pdev));
/* Begin an object, optionally allocating an ID. */
long pdf_open_obj(P2(gx_device_pdf * pdev, long id));
-
-/* Begin an object, allocating an ID. */
-#define pdf_begin_obj(pdev) pdf_open_obj(pdev, 0)
+long pdf_begin_obj(P1(gx_device_pdf * pdev));
/* End an object. */
int pdf_end_obj(P1(gx_device_pdf * pdev));
@@ -412,49 +553,55 @@ void pdf_put_name(P3(const gx_device_pdf * pdev, const byte * nstr, uint size));
void pdf_put_string(P3(const gx_device_pdf * pdev, const byte * str, uint size));
/* Write a value, treating names specially. */
-void pdf_put_value(P3(const gx_device_pdf * pdev, const byte * vstr, uint size));
+void pdf_write_value(P3(const gx_device_pdf * pdev, const byte * vstr, uint size));
/* ------ Page contents ------ */
/* Open a page contents part. */
/* Return an error if the page has too many contents parts. */
-int pdf_open_contents(P2(gx_device_pdf * pdev, pdf_context context));
+int pdf_open_contents(P2(gx_device_pdf * pdev, pdf_context_t context));
/* Close the current contents part if we are in one. */
int pdf_close_contents(P2(gx_device_pdf * pdev, bool last));
/* ------ Resources et al ------ */
+/*
+ * Define the offset that indicates that a file position is in the
+ * asides file rather than the main (contents) file.
+ * Must be a power of 2, and larger than the largest possible output file.
+ */
+#define ASIDES_BASE_POSITION min_long
+
/* Begin an object logically separate from the contents. */
/* (I.e., an object in the resource file.) */
long pdf_open_separate(P2(gx_device_pdf * pdev, long id));
-
-#define pdf_begin_separate(pdev) pdf_open_separate(pdev, 0L)
+long pdf_begin_separate(P1(gx_device_pdf * pdev));
/* Begin an aside (resource, annotation, ...). */
-int pdf_begin_aside(P4(gx_device_pdf * pdev, pdf_resource ** plist,
+int pdf_begin_aside(P4(gx_device_pdf * pdev, pdf_resource_t **plist,
const gs_memory_struct_type_t * pst,
- pdf_resource ** ppres));
+ pdf_resource_t **ppres));
/* Begin a resource of a given type. */
-int pdf_begin_resource(P4(gx_device_pdf * pdev, pdf_resource_type type,
- gs_id rid, pdf_resource ** ppres));
+int pdf_begin_resource(P4(gx_device_pdf * pdev, pdf_resource_type_t rtype,
+ gs_id rid, pdf_resource_t **ppres));
/* Begin a resource body of a given type. */
-int pdf_begin_resource_body(P4(gx_device_pdf * pdev, pdf_resource_type type,
- gs_id rid, pdf_resource ** ppres));
+int pdf_begin_resource_body(P4(gx_device_pdf * pdev, pdf_resource_type_t rtype,
+ gs_id rid, pdf_resource_t **ppres));
/* Allocate a resource, but don't open the stream. */
-int pdf_alloc_resource(P4(gx_device_pdf * pdev, pdf_resource_type type,
- gs_id rid, pdf_resource ** ppres));
+int pdf_alloc_resource(P5(gx_device_pdf * pdev, pdf_resource_type_t rtype,
+ gs_id rid, pdf_resource_t **ppres, long id));
/* Find a resource of a given type by gs_id. */
-pdf_resource *pdf_find_resource_by_gs_id(P3(gx_device_pdf * pdev,
- pdf_resource_type type,
- gs_id rid));
+pdf_resource_t *pdf_find_resource_by_gs_id(P3(gx_device_pdf * pdev,
+ pdf_resource_type_t rtype,
+ gs_id rid));
/* End a separate object. */
-#define pdf_end_separate(pdev) pdf_end_aside(pdev)
+int pdf_end_separate(P1(gx_device_pdf * pdev));
/* End an aside. */
int pdf_end_aside(P1(gx_device_pdf * pdev));
@@ -462,51 +609,48 @@ int pdf_end_aside(P1(gx_device_pdf * pdev));
/* End a resource. */
int pdf_end_resource(P1(gx_device_pdf * pdev));
+/* Copy data from a temporary file to a stream. */
+void pdf_copy_data(P3(stream *s, FILE *file, long count));
+
/* ------ Pages ------ */
/* Get or assign the ID for a page. */
/* Returns 0 if the page number is out of range. */
long pdf_page_id(P2(gx_device_pdf * pdev, int page_num));
+/* Get the dictionary object for the current page. */
+cos_dict_t *pdf_current_page_dict(P1(gx_device_pdf *pdev));
+
/* Open a page for writing. */
-int pdf_open_page(P2(gx_device_pdf * pdev, pdf_context context));
+int pdf_open_page(P2(gx_device_pdf * pdev, pdf_context_t context));
/* Write saved page- or document-level information. */
int pdf_write_saved_string(P2(gx_device_pdf * pdev, gs_string * pstr));
-/* Write the default entries of the Info dictionary. */
-int pdf_write_default_info(P1(gx_device_pdf * pdev));
-
/* ------ Path drawing ------ */
+/* Test whether the clip path needs updating. */
bool pdf_must_put_clip_path(P2(gx_device_pdf * pdev, const gx_clip_path * pcpath));
+/* Write and update the clip path. */
int pdf_put_clip_path(P2(gx_device_pdf * pdev, const gx_clip_path * pcpath));
/* ---------------- Exported by gdevpdfm.c ---------------- */
+/*
+ * Define the type for a pdfmark-processing procedure.
+ * If nameable is false, the objname argument is always NULL.
+ */
+#define pdfmark_proc(proc)\
+ int proc(P5(gx_device_pdf *pdev, gs_param_string *pairs, uint count,\
+ const gs_matrix *pctm, const gs_param_string *objname))
+
/* Compare a C string and a gs_param_string. */
bool pdf_key_eq(P2(const gs_param_string * pcs, const char *str));
/* Scan an integer out of a parameter string. */
int pdfmark_scan_int(P2(const gs_param_string * pstr, int *pvalue));
-/* Define the type for a pdfmark-processing procedure. */
-/* If nameable is false, the objname argument is always NULL. */
-#define pdfmark_proc(proc)\
- int proc(P5(gx_device_pdf *pdev, gs_param_string *pairs, uint count,\
- const gs_matrix *pctm, const gs_param_string *objname))
-/* Define an entry in a table of pdfmark-processing procedures. */
-#define pdfmark_nameable 1 /* allows _objdef */
-#define pdfmark_odd_ok 2 /* OK if odd # of parameters */
-#define pdfmark_keep_name 4 /* don't substitute reference for name */
- /* in 1st argument */
-typedef struct pdfmark_name_s {
- const char *mname;
- pdfmark_proc((*proc));
- byte options;
-} pdfmark_name;
-
/* Process a pdfmark (called from pdf_put_params). */
int pdfmark_process(P2(gx_device_pdf * pdev, const gs_param_string_array * pma));
@@ -514,42 +658,138 @@ int pdfmark_process(P2(gx_device_pdf * pdev, const gs_param_string_array * pma))
int pdfmark_close_outline(P1(gx_device_pdf * pdev));
/* Finish writing an article. */
-int pdfmark_write_article(P2(gx_device_pdf * pdev, const pdf_article * part));
+int pdfmark_write_article(P2(gx_device_pdf * pdev, const pdf_article_t * part));
-/* ---------------- Exported by gdevpdfo.c ---------------- */
+/* ---------------- Exported by gdevpdfr.c ---------------- */
-/* Define the syntax of object names. */
-#define pdfmark_objname_is_valid(data, size)\
- ((size) >= 2 && (data)[0] == '{' &&\
- (const byte *)memchr(data, '}', size) == (data) + (size) - 1)
+/* Test whether an object name has valid syntax, {name}. */
+bool pdf_objname_is_valid(P2(const byte *data, uint size));
-/* Define the table of named-object pdfmark types. */
-extern const pdfmark_name pdfmark_names_named[];
+/*
+ * Look up a named object. Return e_rangecheck if the syntax is invalid,
+ * e_undefined if no object by that name exists.
+ */
+int pdf_find_named(P3(gx_device_pdf * pdev, const gs_param_string * pname,
+ cos_object_t **ppco));
-/* Replace object names with object references in a (parameter) string. */
-int pdfmark_replace_names(P3(gx_device_pdf * pdev, const gs_param_string * from,
- gs_param_string * to));
+/*
+ * Create a named object. id = -1L means do not assign an id. pname = 0
+ * means just create the object, do not name it.
+ */
+int pdf_create_named(P5(gx_device_pdf *pdev, const gs_param_string *pname,
+ cos_type_t cotype, cos_object_t **ppco, long id));
+int pdf_create_named_dict(P4(gx_device_pdf *pdev, const gs_param_string *pname,
+ cos_dict_t **ppcd, long id));
-/* Write and free an entire list of named objects. */
-int pdfmark_write_and_free_named(P2(gx_device_pdf * pdev,
- pdf_named_object ** ppno));
+/*
+ * Look up a named object as for pdf_find_named. If the object does not
+ * exist, create it (as a dictionary if it is one of the predefined names
+ * {ThisPage}, {NextPage}, {PrevPage}, or {Page<#>}, otherwise as a
+ * generic object) and return 1.
+ */
+int pdf_refer_named(P3(gx_device_pdf *pdev, const gs_param_string *pname,
+ cos_object_t **ppco));
-/* ---------------- Exported by gdevpdft.c ---------------- */
+/*
+ * Look up a named object as for pdf_refer_named. If the object already
+ * exists and is not simply a forward reference, return e_rangecheck;
+ * if it exists as a forward reference, set its type and return 0;
+ * otherwise, create the object with the given type and return 1.
+ * pname = 0 is allowed: in this case, simply create the object.
+ */
+int pdf_make_named(P5(gx_device_pdf * pdev, const gs_param_string * pname,
+ cos_type_t cotype, cos_object_t **ppco, bool assign_id));
+int pdf_make_named_dict(P4(gx_device_pdf * pdev, const gs_param_string * pname,
+ cos_dict_t **ppcd, bool assign_id));
-/* Process a show operation (called from pdf_put_params). */
-int pdfshow_process(P3(gx_device_pdf * pdev, gs_param_list * plist,
- const gs_param_string * pts));
+/*
+ * Look up a named object as for pdf_refer_named. If the object does not
+ * exist, or is a forward reference, return e_undefined; if the object
+ * exists has the wrong type, return e_typecheck.
+ */
+int pdf_get_named(P4(gx_device_pdf * pdev, const gs_param_string * pname,
+ cos_type_t cotype, cos_object_t **ppco));
+
+/*
+ * Scan a string for a token. <<, >>, [, and ] are treated as tokens.
+ * Return 1 if a token was scanned, 0 if we reached the end of the string,
+ * or an error. On a successful return, the token extends from *ptoken up
+ * to but not including *pscan.
+ */
+int pdf_scan_token(P3(const byte **pscan, const byte * end,
+ const byte **ptoken));
+
+/*
+ * Scan a possibly composite token: arrays and dictionaries are treated as
+ * single tokens.
+ */
+int pdf_scan_token_composite(P3(const byte **pscan, const byte * end,
+ const byte **ptoken));
+
+/* Replace object names with object references in a (parameter) string. */
+int pdf_replace_names(P3(gx_device_pdf *pdev, const gs_param_string *from,
+ gs_param_string *to));
+
+/* ---------------- Exported by gdevpdft.c ---------------- */
/* Begin a CharProc for an embedded (bitmap) font. */
int pdf_begin_char_proc(P8(gx_device_pdf * pdev, int w, int h, int x_width,
- int y_offset, gs_id id, pdf_char_proc ** ppcp,
- pdf_stream_position * ppos));
+ int y_offset, gs_id id, pdf_char_proc_t **ppcp,
+ pdf_stream_position_t * ppos));
/* End a CharProc. */
-int pdf_end_char_proc(P2(gx_device_pdf * pdev, pdf_stream_position * ppos));
+int pdf_end_char_proc(P2(gx_device_pdf * pdev, pdf_stream_position_t * ppos));
/* Put out a reference to an image as a character in an embedded font. */
-int pdf_do_char_image(P3(gx_device_pdf * pdev, const pdf_char_proc * pcp,
+int pdf_do_char_image(P3(gx_device_pdf * pdev, const pdf_char_proc_t * pcp,
const gs_matrix * pimat));
+/* ---------------- Exported by gdevpdff.c ---------------- */
+
+typedef enum {
+ FONT_EMBED_BASE14,
+ FONT_EMBED_NO,
+ FONT_EMBED_YES
+} pdf_font_embed_t;
+
+typedef struct pdf_standard_font_s {
+ const char *fname;
+ gs_encoding_index_t base_encoding;
+} pdf_standard_font_t;
+extern const pdf_standard_font_t pdf_standard_fonts[];
+
+/* Find an original font corresponding to an arbitrary font, if any. */
+bool pdf_find_orig_font(P4(gx_device_pdf *pdev, gs_font *font,
+ gs_const_string *pfname, gs_matrix *pfmat));
+
+/*
+ * Determine the embedding status of a font. If the font is in the base
+ * 14, store its index (0..13) in *pindex.
+ */
+pdf_font_embed_t pdf_font_embed_status(P3(gx_device_pdf *pdev, gs_font *font,
+ int *pindex));
+
+/* Allocate a font resource. */
+int pdf_alloc_font(P4(gx_device_pdf *pdev, gs_id rid, pdf_font_t **ppfres,
+ bool with_descriptor));
+
+/* Add an encoding difference to a font. */
+int pdf_add_encoding_difference(P5(gx_device_pdf *pdev, pdf_font_t *ppf, int chr,
+ const gs_font_base *bfont, gs_glyph glyph));
+
+/* Get the width of a given character in a (base) font. */
+int pdf_char_width(P5(pdf_font_t *ppf, int ch, gs_font *font,
+ const gs_matrix *pmat, int *pwidth /* may be NULL */));
+
+/* Compute the FontDescriptor for a font or a font subset. */
+int pdf_compute_font_descriptor(P4(gx_device_pdf *pdev,
+ pdf_font_descriptor_t *pfd, gs_font *font,
+ const byte *used /*[32]*/));
+
+/* Register a font for eventual writing (embedded or not). */
+int pdf_register_font(P3(gx_device_pdf *pdev, gs_font *font, pdf_font_t *ppf));
+
+/* Write out the font resources when wrapping up the output. */
+int pdf_write_font_resources(P1(gx_device_pdf *pdev));
+
#endif /* gdevpdfx_INCLUDED */
diff --git a/gs/src/gdevpipe.c b/gs/src/gdevpipe.c
index ec0b60202..fb61972d4 100644
--- a/gs/src/gdevpipe.c
+++ b/gs/src/gdevpipe.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1994, 1997, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1993, 1994, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -25,14 +25,12 @@
#include "gserror.h"
#include "gstypes.h"
#include "gsmemory.h" /* for gxiodev.h */
-#include "stream.h"
#include "gxiodev.h"
/* The pipe IODevice */
private iodev_proc_fopen(pipe_fopen);
private iodev_proc_fclose(pipe_fclose);
-const gx_io_device gs_iodev_pipe =
-{
+const gx_io_device gs_iodev_pipe = {
"%pipe%", "FileSystem",
{iodev_no_init, iodev_no_open_device,
NULL /*iodev_os_open_file */ , pipe_fopen, pipe_fclose,
@@ -47,7 +45,8 @@ const gx_io_device gs_iodev_pipe =
private int
pipe_fopen(gx_io_device * iodev, const char *fname, const char *access,
FILE ** pfile, char *rfname, uint rnamelen)
-{ /* The OSF/1 1.3 library doesn't include const in the */
+{
+ /* The OSF/1 1.3 library doesn't include const in the */
/* prototype for popen.... */
errno = 0;
*pfile = popen((char *)fname, (char *)access);
diff --git a/gs/src/gdevplnx.c b/gs/src/gdevplnx.c
index 4a240a406..4486d65ba 100644
--- a/gs/src/gdevplnx.c
+++ b/gs/src/gdevplnx.c
@@ -41,19 +41,17 @@
#define COPY_ROP_TEXTURE_BUF_SIZE 100
/* GC procedures */
-#define edev ((gx_device_plane_extract *)vptr)
private
-ENUM_PTRS_BEGIN(device_plane_extract_enum_ptrs) ENUM_PREFIX(st_device_forward, 1);
-case 0:
-ENUM_RETURN(gx_device_enum_ptr(edev->target));
+ENUM_PTRS_WITH(device_plane_extract_enum_ptrs, gx_device_plane_extract *edev)
+ ENUM_PREFIX(st_device_forward, 1);
+case 0: ENUM_RETURN(gx_device_enum_ptr(edev->target));
ENUM_PTRS_END
-private RELOC_PTRS_BEGIN(device_plane_extract_reloc_ptrs)
+private RELOC_PTRS_WITH(device_plane_extract_reloc_ptrs, gx_device_plane_extract *edev)
{
RELOC_PREFIX(st_device_forward);
edev->plane_dev = gx_device_reloc_ptr(edev->plane_dev, gcst);
}
RELOC_PTRS_END
-#undef edev
public_st_device_plane_extract();
/* Driver procedures */
diff --git a/gs/src/gdevpng.c b/gs/src/gdevpng.c
index 1c2132b6e..047bfe54c 100644
--- a/gs/src/gdevpng.c
+++ b/gs/src/gdevpng.c
@@ -18,6 +18,8 @@
/* PNG (Portable Network Graphics) Format. Pronounced "ping". */
+/* lpd 1999-07-01: replaced remaining uses of gs_malloc and gs_free with
+ gs_alloc_bytes and gs_free_object. */
/* lpd 1999-03-08: changed png.h to png_.h to allow compiling with only
headers in /usr/include, no source code. */
/* lpd 1997-07-20: changed from using gs_malloc/png_xxx_int to png_create_xxx
@@ -117,10 +119,11 @@ prn_device(png16m_procs, "png16m",
private int
png_print_page(gx_device_printer * pdev, FILE * file)
{
+ gs_memory_t *mem = pdev->memory;
int raster = gdev_prn_raster(pdev);
/* PNG structures */
- byte *row = (byte *) gs_malloc(raster, 1, "png raster buffer");
+ byte *row = gs_alloc_bytes(mem, raster, "png raster buffer");
png_struct *png_ptr =
png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
png_info *info_ptr =
@@ -186,7 +189,9 @@ png_print_page(gx_device_printer * pdev, FILE * file)
int num_colors = 1 << depth;
gx_color_value rgb[3];
- info_ptr->palette = gs_malloc(256 * sizeof(png_color), 1, "png palette");
+ info_ptr->palette =
+ (void *)gs_alloc_bytes(mem, 256 * sizeof(png_color),
+ "png palette");
if (info_ptr->palette == 0) {
code = gs_note_error(gs_error_VMerror);
goto done;
@@ -227,14 +232,13 @@ png_print_page(gx_device_printer * pdev, FILE * file)
/* write the rest of the file */
png_write_end(png_ptr, info_ptr);
- /* if you malloced the palette, free it here */
- if (info_ptr->palette)
- gs_free(info_ptr->palette, 256 * sizeof(png_color), 1, "png palette");
+ /* if you alloced the palette, free it here */
+ gs_free_object(mem, info_ptr->palette, "png palette");
done:
/* free the structures */
png_destroy_write_struct(&png_ptr, &info_ptr);
- gs_free((char *)row, raster, 1, "png raster buffer");
+ gs_free_object(mem, row, "png raster buffer");
return code;
}
diff --git a/gs/src/gdevprn.c b/gs/src/gdevprn.c
index 019f38b6b..ebbda3faf 100644
--- a/gs/src/gdevprn.c
+++ b/gs/src/gdevprn.c
@@ -22,6 +22,7 @@
#include "gdevprn.h"
#include "gp.h"
#include "gsdevice.h" /* for gs_deviceinitialmatrix */
+#include "gsfname.h"
#include "gsparam.h"
#include "gxclio.h"
#include "gxgetbit.h"
@@ -31,14 +32,14 @@
/* GC information */
#define PRINTER_IS_CLIST(pdev) ((pdev)->buffer_space != 0)
-public
+private
ENUM_PTRS_WITH(device_printer_enum_ptrs, gx_device_printer *pdev)
if (PRINTER_IS_CLIST(pdev))
ENUM_PREFIX(st_device_clist, 0);
else
ENUM_PREFIX(st_device_forward, 0);
ENUM_PTRS_END
-public
+private
RELOC_PTRS_WITH(device_printer_reloc_ptrs, gx_device_printer *pdev)
{
if (PRINTER_IS_CLIST(pdev))
@@ -84,14 +85,14 @@ int
gdev_prn_close(gx_device * pdev)
{
gx_device_printer * const ppdev = (gx_device_printer *)pdev;
+ int code = 0;
gdev_prn_free_memory(pdev);
if (ppdev->file != NULL) {
- if (ppdev->file != stdout)
- gp_close_printer(ppdev->file, ppdev->fname);
+ code = gx_device_close_output_file(pdev, ppdev->fname, ppdev->file);
ppdev->file = NULL;
}
- return 0;
+ return code;
}
private int /* returns 0 ok, else -ve error cde */
@@ -490,52 +491,11 @@ gdev_prn_get_params(gx_device * pdev, gs_param_list * plist)
private int
validate_output_file(const gs_param_string * ofs)
{
- const byte *data = ofs->data;
- uint size = ofs->size;
- bool have_format = false;
- uint i;
-
- if (size >= prn_fname_sizeof)
- return_error(gs_error_limitcheck);
- for (i = 0; i < size; ++i)
- if (data[i] == '%') {
- if (i + 1 < size && data[i + 1] == '%')
- continue;
- if (have_format) /* more than one % */
- return_error(gs_error_rangecheck);
- have_format = true;
- sw:if (++i == size)
- return_error(gs_error_rangecheck);
- switch (data[i]) {
- case ' ':
- case '#':
- case '+':
- case '-':
- case '.':
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case 'l':
- goto sw;
- case 'd':
- case 'i':
- case 'u':
- case 'o':
- case 'x':
- case 'X':
- continue;
- default:
- return_error(gs_error_rangecheck);
- }
- }
- return 0;
+ gs_parsed_file_name_t parsed;
+ const char *fmt;
+
+ return gx_parse_output_file_name(&parsed, &fmt, (const char *)ofs->data,
+ ofs->size) >= 0;
}
/* Put parameters. */
@@ -690,8 +650,8 @@ label:\
(const byte *)ppdev->fname, strlen(ppdev->fname))
) {
/* Close the file if it's open. */
- if (ppdev->file != NULL && ppdev->file != stdout)
- gp_close_printer(ppdev->file, ppdev->fname);
+ if (ppdev->file != NULL)
+ gx_device_close_output_file(pdev, ppdev->fname, ppdev->file);
ppdev->file = NULL;
memcpy(ppdev->fname, ofs.data, ofs.size);
ppdev->fname[ofs.size] = 0;
@@ -1180,11 +1140,15 @@ int
gdev_prn_close_printer(gx_device * pdev)
{
gx_device_printer * const ppdev = (gx_device_printer *)pdev;
+ gs_parsed_file_name_t parsed;
+ const char *fmt;
+ int code = gx_parse_output_file_name(&parsed, &fmt, ppdev->fname,
+ strlen(ppdev->fname));
- if (strchr(ppdev->fname, '%') /* file per page */ ||
+ if ((code >= 0 && fmt) /* file per page */ ||
ppdev->ReopenPerPage /* close and reopen for each page */
) {
- gp_close_printer(ppdev->file, ppdev->fname);
+ gx_device_close_output_file(pdev, ppdev->fname, ppdev->file);
ppdev->file = NULL;
}
return 0;
diff --git a/gs/src/gdevps.c b/gs/src/gdevps.c
index 2ae268164..e7ce039da 100644
--- a/gs/src/gdevps.c
+++ b/gs/src/gdevps.c
@@ -32,11 +32,11 @@
#include "gscspace.h"
#include "gxdcolor.h"
#include "gxpath.h"
-#include "gdevpsdf.h"
-#include "gdevpstr.h"
-#include "sstring.h"
+#include "spprint.h"
#include "strimpl.h"
+#include "sstring.h"
#include "sa85x.h"
+#include "gdevpsdf.h"
/****************************************************************
* Notes:
@@ -84,8 +84,8 @@ typedef struct gx_device_pswrite_s {
bool ProduceEPS;
bool first_page;
long bbox_position;
- psdf_binary_writer image_writer;
-#define image_stream image_writer.strm
+ psdf_binary_writer *image_writer;
+#define image_stream image_writer->strm
#define image_cache_size 197
#define image_cache_reprobe_step 121
psw_image_params_t image_cache[image_cache_size];
@@ -94,9 +94,11 @@ typedef struct gx_device_pswrite_s {
psw_path_state_t path_state;
} gx_device_pswrite;
+/* GC descriptor and procedures */
gs_private_st_suffix_add1_final(st_device_pswrite, gx_device_pswrite,
- "gx_device_pswrite", device_pswrite_enum_ptrs, device_pswrite_reloc_ptrs,
- gx_device_finalize, st_device_psdf, image_stream);
+ "gx_device_pswrite", device_pswrite_enum_ptrs,
+ device_pswrite_reloc_ptrs, gx_device_finalize,
+ st_device_psdf, image_writer);
#define psw_procs\
{ psw_open,\
@@ -301,7 +303,6 @@ private const char *const psw_2_prolog[] =
/* <src> X <a85src> */
/* - @X <a85src> */
/* <w> <h> <src> +F <w> <h> <g4src> */
- /* <w> <h> +F <w> <h> <g4src> */
/* <w> <h> @F <w> <h> <g4src> */
/* <w> <h> @C <w> <h> <g4a85src> */
"/X{/ASCII85Decode filter}!/@X{@ X}!/+F{2 index 2 index F}!/@F{@ +F}!/@C{@X +F}!",
@@ -384,12 +385,12 @@ psw_image_stream_setup(gx_device_pswrite * pdev)
int code, encode;
if (pdev->LanguageLevel >= 2 || pdev->binary_ok) {
- code = psdf_begin_binary((gx_device_psdf *)pdev, &pdev->image_writer);
+ code = psdf_begin_binary((gx_device_psdf *)pdev, pdev->image_writer);
encode =
(pdev->image_stream->state->template == &s_A85E_template ? 1 : 0);
} else {
pdev->binary_ok = true;
- code = psdf_begin_binary((gx_device_psdf *)pdev, &pdev->image_writer);
+ code = psdf_begin_binary((gx_device_psdf *)pdev, pdev->image_writer);
pdev->binary_ok = false;
if (code >= 0) {
stream_state *st =
@@ -399,7 +400,7 @@ psw_image_stream_setup(gx_device_pswrite * pdev)
if (st == 0)
code = gs_note_error(gs_error_VMerror);
else {
- code = psdf_encode_binary(&pdev->image_writer,
+ code = psdf_encode_binary(pdev->image_writer,
&s_AXE_template, st);
if (code >= 0)
((stream_AXE_state *)st)->EndOfData = false; /* no > */
@@ -415,8 +416,8 @@ private void
psw_image_cleanup(gx_device_pswrite * pdev)
{
if (pdev->image_stream != 0) {
- psdf_end_binary(&pdev->image_writer);
- pdev->image_stream = 0;
+ psdf_end_binary(pdev->image_writer);
+ memset(pdev->image_writer, 0, sizeof(*pdev->image_writer));
}
}
@@ -470,7 +471,7 @@ psw_image_write(gx_device_pswrite * pdev, const char *imagestr,
* We should really look at the statistics of the image before
* committing to using G4 encoding....
*/
- code = psdf_CFE_binary(&pdev->image_writer, width, height, false);
+ code = psdf_CFE_binary(pdev->image_writer, width, height, false);
if (code < 0)
return code;
encode += 2;
@@ -806,8 +807,9 @@ psw_endpath(gx_device_vector * vdev, gx_path_type_t type)
private int
psw_open(gx_device * dev)
{
- vdev->v_memory = dev->memory;
-/****** WRONG ******/
+ gs_memory_t *mem = gs_memory_stable(dev->memory);
+
+ vdev->v_memory = mem;
vdev->vec_procs = &psw_vector_procs;
{
int code = gdev_vector_open_file_bbox(vdev, 512, true);
@@ -818,6 +820,10 @@ psw_open(gx_device * dev)
gdev_vector_init(vdev);
pdev->first_page = true;
pdev->binary_ok = !pdev->params.ASCII85EncodePages;
+ pdev->image_writer = gs_alloc_struct(mem, psdf_binary_writer,
+ &st_psdf_binary_writer,
+ "psw_open(image_writer)");
+ memset(pdev->image_writer, 0, sizeof(*pdev->image_writer)); /* for GC */
image_cache_reset(pdev);
return 0;
}
@@ -866,6 +872,9 @@ psw_close(gx_device * dev)
}
if (!pdev->ProduceEPS)
fputs("%%EOF\n", f);
+ gs_free_object(pdev->v_memory, pdev->image_writer,
+ "psw_close(image_writer)");
+ pdev->image_writer = 0;
gdev_vector_close_file(vdev);
return 0;
}
diff --git a/gs/src/gdevpsd1.c b/gs/src/gdevpsd1.c
new file mode 100644
index 000000000..a6a81251c
--- /dev/null
+++ b/gs/src/gdevpsd1.c
@@ -0,0 +1,479 @@
+/* Copyright (C) 1998, 1999 Aladdin Enterprises. All rights reserved.
+
+ This file is part of Aladdin Ghostscript.
+
+ Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
+ or distributor accepts any responsibility for the consequences of using it,
+ or for whether it serves any particular purpose or works at all, unless he
+ or she says so in writing. Refer to the Aladdin Ghostscript Free Public
+ License (the "License") for full details.
+
+ Every copy of Aladdin Ghostscript must include a copy of the License,
+ normally in a plain ASCII text file named PUBLIC. The License grants you
+ the right to copy, modify and redistribute Aladdin Ghostscript, but only
+ under certain conditions described in the License. Among other things, the
+ License requires that the copyright notice and this notice be preserved on
+ all copies.
+ */
+
+
+/* Write an embedded Type 1 font */
+#include "memory_.h"
+#include "gx.h"
+#include "gserrors.h"
+#include "gsccode.h"
+#include "gsmatrix.h"
+#include "gxfixed.h"
+#include "gxfont.h"
+#include "gxfont1.h"
+#include "stream.h"
+#include "sfilter.h"
+#include "sstring.h"
+#include "spprint.h"
+#include "gdevpsdf.h"
+
+private int
+write_float_array(gs_param_list *plist, const char *key, const float *values,
+ int count)
+{
+ if (count != 0) {
+ gs_param_float_array fa;
+
+ fa.size = count;
+ fa.data = values;
+ return param_write_float_array(plist, key, &fa);
+ }
+ return 0;
+}
+
+private void
+write_uid(stream *s, const gs_uid *puid)
+{
+ if (uid_is_UniqueID(puid))
+ pprintld1(s, "/UniqueID %ld def\n", puid->id);
+ else if (uid_is_XUID(puid)) {
+ uint i, n = uid_XUID_size(puid);
+
+ pputs(s, "/XUID [");
+ for (i = 0; i < n; ++i)
+ pprintld1(s, "%ld ", uid_XUID_values(puid)[i]);
+ pputs(s, "] def\n");
+ }
+}
+
+/*
+ * Write the Private dictionary. This is a separate procedure only for
+ * readability.
+ */
+private int
+write_Private(stream *s, gs_font_type1 *pfont,
+ gs_glyph *subset_glyphs, uint subset_size,
+ gs_glyph notdef, const param_printer_params_t *ppp)
+{
+ const gs_type1_data *const pdata = &pfont->data;
+ printer_param_list_t rlist;
+ gs_param_list *plist = (gs_param_list *)&rlist;
+ int code = s_init_param_printer(&rlist, ppp, s);
+
+ if (code < 0)
+ return 0;
+ /*
+ * Note: eexec encryption always writes/skips 4 initial bytes, not
+ * the number of initial bytes given by pdata->lenIV.
+ */
+ pputs(s, "****dup /Private 17 dict dup begin\n");
+ pputs(s, "/-|{string currentfile exch readstring pop}executeonly def\n");
+ pputs(s, "/|-{noaccess def}executeonly def\n");
+ pputs(s, "/|{noaccess put}executeonly def\n");
+ {
+ private const gs_param_item_t private_items[] = {
+ {"lenIV", gs_param_type_int,
+ offset_of(gs_type1_data, lenIV)},
+ {"BlueFuzz", gs_param_type_int,
+ offset_of(gs_type1_data, BlueFuzz)},
+ {"BlueScale", gs_param_type_float,
+ offset_of(gs_type1_data, BlueScale)},
+ {"BlueShift", gs_param_type_float,
+ offset_of(gs_type1_data, BlueShift)},
+ {"ExpansionFactor", gs_param_type_float,
+ offset_of(gs_type1_data, ExpansionFactor)},
+ {"ForceBold", gs_param_type_bool,
+ offset_of(gs_type1_data, ForceBold)},
+ {"LanguageGroup", gs_param_type_int,
+ offset_of(gs_type1_data, LanguageGroup)},
+ {"RndStemUp", gs_param_type_bool,
+ offset_of(gs_type1_data, RndStemUp)},
+ gs_param_item_end
+ };
+ gs_type1_data defaults;
+
+ defaults.lenIV = 4;
+ defaults.BlueFuzz = 1;
+ defaults.BlueScale = 0.039625;
+ defaults.BlueShift = 7.0;
+ defaults.ExpansionFactor = 0.06;
+ defaults.ForceBold = false;
+ defaults.LanguageGroup = 0;
+ defaults.RndStemUp = true;
+ code = gs_param_write_items(plist, pdata, &defaults, private_items);
+ if (code < 0)
+ return code;
+ write_float_array(plist, "BlueValues", pdata->BlueValues.values,
+ pdata->BlueValues.count);
+ write_float_array(plist, "OtherBlues", pdata->OtherBlues.values,
+ pdata->OtherBlues.count);
+ write_float_array(plist, "FamilyBlues", pdata->FamilyBlues.values,
+ pdata->FamilyBlues.count);
+ write_float_array(plist, "FamilyOtherBlues", pdata->FamilyOtherBlues.values,
+ pdata->FamilyOtherBlues.count);
+ write_float_array(plist, "StdHW", pdata->StdHW.values,
+ pdata->StdHW.count);
+ write_float_array(plist, "StemSnapH", pdata->StemSnapH.values,
+ pdata->StemSnapH.count);
+ write_float_array(plist, "StemSnapV", pdata->StemSnapV.values,
+ pdata->StemSnapV.count);
+ }
+ write_uid(s, &pfont->UID);
+ pputs(s, "/MinFeature{16 16} def\n");
+ pputs(s, "/password 5839 def\n");
+
+ /* Write the Subrs. We always write them all, even for subsets. */
+
+ {
+ int n, i;
+ gs_const_string str;
+
+ for (n = 0;
+ (*pdata->procs->subr_data)(pfont, n, false, &str) !=
+ gs_error_rangecheck;
+ )
+ ++n;
+ pprintd1(s, "/Subrs %d array\n", n);
+ for (i = 0; i < n; ++i)
+ if ((*pdata->procs->subr_data)(pfont, i, false, &str) >= 0) {
+ char buf[50];
+
+ sprintf(buf, "dup %d %u -| ", i, str.size);
+ pputs(s, buf);
+ pwrite(s, str.data, str.size);
+ pputs(s, " |\n");
+ }
+ pputs(s, "|-\n");
+ }
+
+ /* We don't write OtherSubrs -- there had better not be any! */
+
+ /* Write the CharStrings. */
+
+ {
+ int num_chars = 0;
+ gs_glyph glyph;
+ psdf_glyph_enum_t genum;
+ gs_const_string gdata;
+ int code;
+
+ psdf_enumerate_glyphs_begin(&genum, (gs_font *)pfont, subset_glyphs,
+ (subset_glyphs ? subset_size : 0),
+ GLYPH_SPACE_NAME);
+ for (glyph = gs_no_glyph;
+ (code = psdf_enumerate_glyphs_next(&genum, &glyph)) != 1;
+ )
+ if (code == 0 && (*pdata->procs->glyph_data)(pfont, glyph, &gdata) >= 0)
+ ++num_chars;
+ pprintd1(s, "2 index /CharStrings %d dict dup begin\n", num_chars);
+ psdf_enumerate_glyphs_reset(&genum);
+ for (glyph = gs_no_glyph;
+ (code = psdf_enumerate_glyphs_next(&genum, &glyph)) != 1;
+ )
+ if (code == 0 && (*pdata->procs->glyph_data)(pfont, glyph, &gdata) >= 0) {
+ uint gssize;
+ const char *gstr =
+ (*pfont->procs.callbacks.glyph_name)(glyph, &gssize);
+
+ pputs(s, "/");
+ pwrite(s, gstr, gssize);
+ pprintd1(s, " %d -| ", gdata.size);
+ pwrite(s, gdata.data, gdata.size);
+ pputs(s, " |-\n");
+ }
+ }
+
+ /* Wrap up. */
+
+ pputs(s, "end\nend\nreadonly put\nnoaccess put\n");
+ s_release_param_printer(&rlist);
+ return 0;
+}
+
+/* Write the definition of a Type 1 font. */
+int
+psdf_write_type1_font(stream *s, gs_font_type1 *pfont, int options,
+ gs_glyph *orig_subset_glyphs, uint orig_subset_size,
+ const gs_const_string *alt_font_name, int lengths[3])
+{
+ stream *es = s;
+ long start = stell(s);
+ param_printer_params_t ppp;
+ printer_param_list_t rlist;
+ stream AXE_stream;
+ stream_AXE_state AXE_state;
+ byte AXE_buf[200]; /* arbitrary */
+ stream exE_stream;
+ stream_exE_state exE_state;
+ byte exE_buf[200]; /* arbitrary */
+ gs_glyph notdef = gs_no_glyph;
+ gs_glyph subset_data[256+1]; /* +1 for .notdef */
+ gs_glyph *subset_glyphs = orig_subset_glyphs;
+ uint subset_size = orig_subset_size;
+ int code;
+
+ if (subset_glyphs) {
+ memcpy(subset_data, orig_subset_glyphs,
+ sizeof(gs_glyph) * subset_size);
+ subset_glyphs = subset_data;
+ }
+
+ /*
+ * Before doing anything else, make sure that this font is writable.
+ * In particular, it must have no CharStrings defined by PostScript
+ * procedures, no non-standard OtherSubrs, and no CDevProc.
+ */
+
+ {
+ gs_glyph glyph;
+ psdf_glyph_enum_t genum;
+ gs_glyph_info_t info;
+ gs_const_string gdata;
+ uint members = GLYPH_INFO_WIDTH0 << pfont->WMode;
+ int code;
+
+ psdf_enumerate_glyphs_begin(&genum, (gs_font *)pfont, subset_glyphs,
+ (subset_glyphs ? subset_size : 0),
+ GLYPH_SPACE_NAME);
+ while ((code = psdf_enumerate_glyphs_next(&genum, &glyph)) != 1) {
+ if (code < 0)
+ return code;
+ code = (*pfont->data.procs->glyph_data)(pfont, glyph, &gdata);
+ /*
+ * If the glyph isn't defined by a CharString, glyph_data will
+ * return a typecheck error. But if there's merely a glyph in
+ * in the Encoding that isn't defined, glyph_data will return an
+ * undefined error, which is OK.
+ */
+ if (code < 0) {
+ if (code == gs_error_undefined)
+ continue;
+ return code;
+ }
+ /*
+ * If the font has a CDevProc or calls a non-standard OtherSubr,
+ * glyph_info will return a rangecheck error.
+ */
+ code = pfont->procs.glyph_info((gs_font *)pfont, glyph, NULL,
+ members, &info);
+ if (code < 0)
+ return code;
+ }
+ }
+
+ {
+ /*
+ * Detect the .notdef glyph, needed for subset fonts and to
+ * eliminate unnecessary Encoding assignments.
+ */
+ psdf_glyph_enum_t genum;
+ gs_glyph glyph;
+
+ psdf_enumerate_glyphs_begin(&genum, (gs_font *)pfont, NULL, 0,
+ GLYPH_SPACE_NAME);
+ while ((code = psdf_enumerate_glyphs_next(&genum, &glyph)) != 1) {
+ uint namelen;
+ const char *namestr =
+ (*pfont->procs.callbacks.glyph_name)(glyph, &namelen);
+
+ if (namestr && namelen == 7 && !memcmp(namestr, ".notdef", 7)) {
+ notdef = glyph;
+ break;
+ }
+ }
+ }
+ if (subset_glyphs) {
+ /* Subset fonts require .notdef. */
+ if (notdef == gs_no_glyph)
+ return_error(gs_error_rangecheck);
+ /* Sort the glyphs now. Make sure .notdef is included. */
+ subset_glyphs[subset_size++] = notdef;
+ subset_size = psdf_sort_glyphs(subset_glyphs, subset_size);
+ }
+
+ /* Initialize the parameter printer. */
+
+ ppp = param_printer_params_default;
+ ppp.item_suffix = " def\n";
+ ppp.print_ok =
+ (options & WRITE_TYPE1_ASCIIHEX ? 0 : PRINT_BINARY_OK);
+ code = s_init_param_printer(&rlist, &ppp, s);
+ if (code < 0)
+ return code;
+
+ /* Write the font header. */
+
+ pputs(s, "%!FontType1-1.0: ");
+ pwrite(s, pfont->font_name.chars, pfont->font_name.size);
+ pputs(s, "\n11 dict begin\n");
+
+ /* Write FontInfo. Currently we don't write anything there. */
+
+ pputs(s, "/FontInfo 1 dict dup begin\n");
+ /****** SHOULD USE param_list API FOR ADDITIONAL ELEMENTS ******/
+ pputs(s, "end readonly def\n");
+
+ /* Write the main font dictionary. */
+
+ pputs(s, "/FontName /");
+ if (alt_font_name)
+ pwrite(s, alt_font_name->data, alt_font_name->size);
+ else
+ pwrite(s, pfont->font_name.chars, pfont->font_name.size);
+ pputs(s, " def\n");
+ pputs(s, "/Encoding ");
+ switch (pfont->encoding_index) {
+ case ENCODING_INDEX_STANDARD:
+ pputs(s, "StandardEncoding");
+ break;
+ case ENCODING_INDEX_ISOLATIN1:
+ /* ATM only recognizes StandardEncoding. */
+ if (options & WRITE_TYPE1_POSTSCRIPT) {
+ pputs(s, "ISOLatin1Encoding");
+ break;
+ }
+ default:{
+ gs_char i;
+
+ pputs(s, "256 array\n");
+ pputs(s, "0 1 255 {1 index exch /.notdef put} for\n");
+ for (i = 0; i < 256; ++i) {
+ gs_glyph glyph =
+ (*pfont->procs.encode_char)
+ ((gs_font *)pfont, (gs_char)i, GLYPH_SPACE_NAME);
+ const char *namestr;
+ uint namelen;
+
+ if (subset_glyphs && subset_size) {
+ /*
+ * Only write Encoding entries for glyphs in the
+ * subset. Use binary search to check each glyph,
+ * since subset_glyphs are sorted.
+ */
+ int lo = 0, hi = subset_size - 1;
+
+ if (glyph < subset_glyphs[0] ||
+ glyph > subset_glyphs[subset_size - 1]
+ )
+ continue;
+ /*
+ * Loop invariants: hi > lo;
+ * subset_glyphs[lo] <= glyph <= subset_glyphs[hi].
+ */
+ while (hi - lo > 1) {
+ int mid = (lo + hi) >> 1;
+ if (glyph >= subset_glyphs[mid])
+ lo = mid;
+ else
+ hi = mid;
+ }
+ if (glyph != subset_glyphs[lo] &&
+ glyph != subset_glyphs[hi]
+ )
+ continue;
+ }
+ if (glyph != gs_no_glyph && glyph != notdef &&
+ (namestr = (*pfont->procs.callbacks.glyph_name)
+ (glyph, &namelen)) != 0
+ ) {
+ pprintd1(s, "dup %d /", (int)i);
+ pwrite(s, namestr, namelen);
+ pputs(s, " put\n");
+ }
+ }
+ pputs(s, "readonly");
+ }
+ }
+ pputs(s, " def\n");
+ pprintg6(s, "/FontMatrix [%g %g %g %g %g %g] readonly def\n",
+ pfont->FontMatrix.xx, pfont->FontMatrix.xy,
+ pfont->FontMatrix.yx, pfont->FontMatrix.yy,
+ pfont->FontMatrix.tx, pfont->FontMatrix.ty);
+ write_uid(s, &pfont->UID);
+ pprintg4(s, "/FontBBox {%g %g %g %g} readonly def\n",
+ pfont->FontBBox.p.x, pfont->FontBBox.p.y,
+ pfont->FontBBox.q.x, pfont->FontBBox.q.y);
+ {
+ private const gs_param_item_t font_items[] =
+ {
+ {"FontType", gs_param_type_int,
+ offset_of(gs_font_type1, FontType)},
+ {"PaintType", gs_param_type_int,
+ offset_of(gs_font_type1, PaintType)},
+ {"StrokeWidth", gs_param_type_float,
+ offset_of(gs_font_type1, StrokeWidth)},
+ gs_param_item_end
+ };
+
+ code = gs_param_write_items((gs_param_list *)&rlist, pfont, NULL,
+ font_items);
+ if (code < 0)
+ return code;
+ }
+ pputs(s, "currentdict end\n");
+
+ /* Write the Private dictionary. */
+
+ if (options & WRITE_TYPE1_EEXEC) {
+ pputs(s, "currentfile eexec\n");
+ lengths[0] = stell(s) - start;
+ start = stell(s);
+ if (options & WRITE_TYPE1_ASCIIHEX) {
+ s_init(&AXE_stream, NULL);
+ s_init_state((stream_state *)&AXE_state, &s_AXE_template, NULL);
+ AXE_state.EndOfData = false;
+ s_init_filter(&AXE_stream, (stream_state *)&AXE_state,
+ AXE_buf, sizeof(AXE_buf), es);
+ es = &AXE_stream;
+ }
+ s_init(&exE_stream, NULL);
+ s_init_state((stream_state *)&exE_state, &s_exE_template, NULL);
+ exE_state.cstate = 55665;
+ s_init_filter(&exE_stream, (stream_state *)&exE_state,
+ exE_buf, sizeof(exE_buf), es);
+ es = &exE_stream;
+ }
+ code = write_Private(es, pfont, subset_glyphs, subset_size, notdef, &ppp);
+ if (code < 0)
+ return code;
+ pputs(es, "dup/FontName get exch definefont pop\n");
+ if (options & WRITE_TYPE1_EEXEC) {
+ if (options & (WRITE_TYPE1_EEXEC_PAD | WRITE_TYPE1_EEXEC_MARK))
+ pputs(es, "mark ");
+ pputs(es, "currentfile closefile\n");
+ s_close_filters(&es, s);
+ lengths[1] = stell(s) - start;
+ start = stell(s);
+ if (options & WRITE_TYPE1_EEXEC_PAD) {
+ int i;
+
+ for (i = 0; i < 8; ++i)
+ pputs(s, "\n0000000000000000000000000000000000000000000000000000000000000000");
+ pputs(s, "\ncleartomark\n");
+ }
+ lengths[2] = stell(s) - start;
+ } else {
+ lengths[0] = stell(s) - start;
+ lengths[1] = lengths[2] = 0;
+ }
+
+ /* Wrap up. */
+
+ s_release_param_printer(&rlist);
+ return 0;
+}
diff --git a/gs/src/gdevpsde.c b/gs/src/gdevpsde.c
deleted file mode 100644
index 14f4a58f5..000000000
--- a/gs/src/gdevpsde.c
+++ /dev/null
@@ -1,276 +0,0 @@
-/* Copyright (C) 1998 Aladdin Enterprises. All rights reserved.
-
- This file is part of Aladdin Ghostscript.
-
- Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
- or distributor accepts any responsibility for the consequences of using it,
- or for whether it serves any particular purpose or works at all, unless he
- or she says so in writing. Refer to the Aladdin Ghostscript Free Public
- License (the "License") for full details.
-
- Every copy of Aladdin Ghostscript must include a copy of the License,
- normally in a plain ASCII text file named PUBLIC. The License grants you
- the right to copy, modify and redistribute Aladdin Ghostscript, but only
- under certain conditions described in the License. Among other things, the
- License requires that the copyright notice and this notice be preserved on
- all copies.
- */
-
-
-/* Embedded font writing */
-#include "memory_.h"
-#include "gx.h"
-#include "gserrors.h"
-#include "gsccode.h"
-#include "gsmatrix.h"
-#include "gxfixed.h"
-#include "gxfont.h"
-#include "gxfont1.h"
-#include "stream.h"
-#include "gdevpstr.h"
-#include "gdevpsdf.h"
-
-private int
-embed_table(gs_param_list * plist, const char *key, const float *values,
- int count)
-{
- if (count != 0) {
- gs_param_float_array fa;
-
- fa.size = count;
- fa.data = values;
- return param_write_float_array(plist, key, &fa);
- }
- return 0;
-}
-
-private void
-embed_uid(stream * s, const gs_uid * puid)
-{
- if (uid_is_UniqueID(puid))
- pprintld1(s, "/UniqueID %ld def\n", puid->id);
- else if (uid_is_XUID(puid)) {
- uint i, n = uid_XUID_size(puid);
-
- pputs(s, "/XUID [");
- for (i = 0; i < n; ++i)
- pprintld1(s, "%ld ", uid_XUID_values(puid)[i]);
- pputs(s, "] def\n");
- }
-}
-
-/* Write an embedded Type 1 font. */
-int
-psdf_embed_type1_font(stream * s, gs_font_type1 * pfont)
-{
- const gs_type1_data *const pdata = &pfont->data;
- gs_param_list *plist;
- param_printer_params_t ppp;
- int code;
-
- ppp = param_printer_params_default;
- ppp.item_suffix = " def\n";
- code = psdf_alloc_param_printer(&plist, &ppp, s,
- print_binary_ok, s->memory);
- if (code < 0)
- return 0;
-
- /* Write the font header. */
-
- pputs(s, "%!PS-AdobeFont-1.0: ");
- pwrite(s, pfont->font_name.chars, pfont->font_name.size);
- pputs(s, "\n11 dict begin\n");
-
- /* Write FontInfo. Currently we don't write anything there. */
-
- pputs(s, "/FontInfo 1 dict dup begin\n");
- pputs(s, "end readonly def\n");
-
- /* Write the main font dictionary. */
-
- pputs(s, "/FontName /");
- pwrite(s, pfont->font_name.chars, pfont->font_name.size);
- pputs(s, " def\n");
- pputs(s, "/Encoding ");
- switch (pfont->encoding_index) {
- case 0:
- pputs(s, "StandardEncoding");
- break;
- case 1:
- pputs(s, "ISOLatin1Encoding");
- break;
- default:{
- gs_char i;
-
- pputs(s, "256 array\n");
- pputs(s, "0 1 255 {1 index exch /.notdef put} for\n");
- for (i = 0; i < 256; ++i) {
- gs_glyph glyph =
- (*pfont->procs.encode_char) (NULL, (gs_font *) pfont, &i);
- const char *namestr;
- uint namelen;
-
- if (glyph != gs_no_glyph &&
- (namestr = (*pfont->procs.callbacks.glyph_name) (glyph, &namelen)) != 0 &&
- !(namelen == 7 && !memcmp(namestr, ".notdef", 7))
- ) {
- pprintd1(s, "dup %d /", (int)i);
- pwrite(s, namestr, namelen);
- pputs(s, " put\n");
- }
- }
- pputs(s, "readonly");
- }
- }
- pputs(s, " def\n");
- pprintg6(s, "/FontMatrix [%g %g %g %g %g %g] readonly def\n",
- pfont->FontMatrix.xx, pfont->FontMatrix.xy,
- pfont->FontMatrix.yx, pfont->FontMatrix.yy,
- pfont->FontMatrix.tx, pfont->FontMatrix.ty);
- embed_uid(s, &pfont->UID);
- pprintg4(s, "/FontBBox {%g %g %g %g} readonly def\n",
- pfont->FontBBox.p.x, pfont->FontBBox.p.y,
- pfont->FontBBox.q.x, pfont->FontBBox.q.y);
- {
- private const gs_param_item_t font_items[] =
- {
- {"FontType", gs_param_type_int,
- offset_of(gs_font_type1, FontType)},
- {"PaintType", gs_param_type_int,
- offset_of(gs_font_type1, PaintType)},
- {"StrokeWidth", gs_param_type_float,
- offset_of(gs_font_type1, StrokeWidth)},
- gs_param_item_end
- };
-
- code = gs_param_write_items(plist, pfont, NULL, font_items);
- if (code < 0)
- return code;
- }
- pputs(s, "currentdict end\n");
-
- /* Write the Private dictionary. */
-
- pputs(s, "dup /Private 17 dict dup begin\n");
- pputs(s, "/-|{string currentfile exch readstring pop}executeonly def\n");
- pputs(s, "/|-{noaccess def}executeonly def\n");
- pputs(s, "/|{noaccess put}executeonly def\n");
- {
- private const gs_param_item_t private_items[] =
- {
- {"lenIV", gs_param_type_int,
- offset_of(gs_type1_data, lenIV)},
- {"BlueFuzz", gs_param_type_int,
- offset_of(gs_type1_data, BlueFuzz)},
- {"BlueScale", gs_param_type_float,
- offset_of(gs_type1_data, BlueScale)},
- {"BlueShift", gs_param_type_float,
- offset_of(gs_type1_data, BlueShift)},
- {"ExpansionFactor", gs_param_type_float,
- offset_of(gs_type1_data, ExpansionFactor)},
- {"ForceBold", gs_param_type_bool,
- offset_of(gs_type1_data, ForceBold)},
- {"LanguageGroup", gs_param_type_int,
- offset_of(gs_type1_data, LanguageGroup)},
- {"RndStemUp", gs_param_type_bool,
- offset_of(gs_type1_data, RndStemUp)},
- gs_param_item_end
- };
- gs_type1_data defaults;
-
- defaults.lenIV = 4;
- defaults.BlueFuzz = 1;
- defaults.BlueScale = 0.039625;
- defaults.BlueShift = 7.0;
- defaults.ExpansionFactor = 0.06;
- defaults.ForceBold = false;
- defaults.LanguageGroup = 0;
- defaults.RndStemUp = true;
- code = gs_param_write_items(plist, pdata, &defaults, private_items);
- if (code < 0)
- return code;
- embed_table(plist, "BlueValues", pdata->BlueValues.values,
- pdata->BlueValues.count);
- embed_table(plist, "OtherBlues", pdata->OtherBlues.values,
- pdata->OtherBlues.count);
- embed_table(plist, "FamilyBlues", pdata->FamilyBlues.values,
- pdata->FamilyBlues.count);
- embed_table(plist, "FamilyOtherBlues", pdata->FamilyOtherBlues.values,
- pdata->FamilyOtherBlues.count);
- embed_table(plist, "StdHW", pdata->StdHW.values,
- pdata->StdHW.count);
- embed_table(plist, "StemSnapH", pdata->StemSnapH.values,
- pdata->StemSnapH.count);
- embed_table(plist, "StemSnapV", pdata->StemSnapV.values,
- pdata->StemSnapV.count);
- }
- embed_uid(s, &pfont->UID);
- pputs(s, "/MinFeature{16 16} |-\n");
- pputs(s, "/password 5839 def\n");
-
- /* Write the Subrs. */
-
- {
- int n, i;
- gs_const_string str;
-
- for (n = 0;
- (*pdata->procs->subr_data) (pfont, n, false, &str) !=
- gs_error_rangecheck;
- )
- ++n;
- pprintd1(s, "/Subrs %d array\n", n);
- for (i = 0; i < n; ++i)
- if ((*pdata->procs->subr_data) (pfont, i, false, &str) >= 0) {
- char buf[50];
-
- sprintf(buf, "dup %d %u -| ", i, str.size);
- pputs(s, buf);
- pwrite(s, str.data, str.size);
- pputs(s, " |\n");
- }
- pputs(s, "|-\n");
- }
-
- /* We don't write OtherSubrs -- there had better not be any! */
-
- /* Write the CharStrings. */
-
- {
- int num_chars = 0;
- gs_glyph glyph;
- int index = 0;
- gs_const_string gdata;
- int code;
-
- for (glyph = gs_no_glyph, index = 0;
- code = (*pdata->procs->next_glyph) (pfont, &index, &glyph),
- index != 0;
- )
- if (code == 0 && (*pdata->procs->glyph_data) (pfont, glyph, &gdata) >= 0)
- ++num_chars;
- pprintd1(s, "2 index /CharStrings %d dict dup begin\n", num_chars);
- for (glyph = gs_no_glyph, index = 0;
- code = (*pdata->procs->next_glyph) (pfont, &index, &glyph),
- index != 0;
- )
- if (code == 0 && (*pdata->procs->glyph_data) (pfont, glyph, &gdata) >= 0) {
- uint gssize;
- const char *gstr =
- (*pfont->procs.callbacks.glyph_name) (glyph, &gssize);
-
- pputs(s, "/");
- pwrite(s, gstr, gssize);
- pprintd1(s, " %d -| ", gdata.size);
- pwrite(s, gdata.data, gdata.size);
- pputs(s, " |-\n");
- }
- }
-
- /* Wrap up. */
-
- pputs(s, "end\nend\nreadonly put\nnoaccess put\n");
- pputs(s, "dup/FontName get exch definefont pop\n");
- psdf_free_param_printer(plist);
- return 0;
-}
diff --git a/gs/src/gdevpsdf.c b/gs/src/gdevpsdf.c
index e09d5572c..24a358a08 100644
--- a/gs/src/gdevpsdf.c
+++ b/gs/src/gdevpsdf.c
@@ -18,19 +18,60 @@
/* Common utilities for PostScript and PDF writers */
-#include "string_.h"
+#include "memory_.h"
+#include <stdlib.h> /* for qsort */
#include "gx.h"
#include "gserrors.h"
#include "gdevpsdf.h"
-#include "gdevpstr.h"
+#include "gxfont.h"
#include "scanchar.h"
#include "strimpl.h"
#include "sa85x.h"
#include "scfx.h"
+#include "spprint.h"
#include "sstring.h"
-/* Structure descriptor */
+/* Structure descriptors */
public_st_device_psdf();
+public_st_psdf_binary_writer();
+
+/* GC procedures */
+private
+ENUM_PTRS_WITH(psdf_binary_writer_enum_ptrs, psdf_binary_writer *pbw) {
+ /*
+ * Don't enumerate the stream pointers: they are all either
+ * unused or internal, except for strm.
+ */
+ return 0;
+}
+ case 0: ENUM_RETURN(pbw->target);
+ case 1: ENUM_RETURN((pbw->strm == &pbw->A85E.s ? pbw->A85E.s.strm :
+ pbw->strm));
+ case 2: ENUM_RETURN(pbw->dev);
+ENUM_PTRS_END
+private
+RELOC_PTRS_WITH(psdf_binary_writer_reloc_ptrs, psdf_binary_writer *pbw)
+{
+ RELOC_VAR(pbw->target);
+ RELOC_VAR(pbw->dev);
+ if (pbw->strm == &pbw->A85E.s) {
+ char *relocated = (char *)RELOC_OBJ(pbw);
+ long reloc = relocated - (char *)pbw;
+
+ /* Fix up the internal pointers. */
+ pbw->A85E.s.cbuf += reloc;
+ pbw->A85E.s.srptr += reloc;
+ pbw->A85E.s.srlimit += reloc;
+ pbw->A85E.s.swlimit += reloc;
+ RELOC_VAR(pbw->A85E.s.strm);
+ pbw->A85E.s.state = (stream_state *)
+ (relocated + offset_of(psdf_binary_writer, A85E.state));
+ pbw->strm = (stream *)
+ (relocated + offset_of(psdf_binary_writer, A85E.s));
+ } else
+ RELOC_VAR(pbw->strm);
+}
+RELOC_PTRS_END
/* ---------------- Vector implementation procedures ---------------- */
@@ -195,17 +236,19 @@ psdf_set_color(gx_device_vector * vdev, const gx_drawing_color * pdc,
int
psdf_begin_binary(gx_device_psdf * pdev, psdf_binary_writer * pbw)
{
- pbw->strm = pdev->strm;
+ pbw->target = pdev->strm;
+ pbw->memory = pdev->v_memory;
pbw->dev = pdev;
/* If not binary, set up the encoding stream. */
if (!pdev->binary_ok) {
- stream_state *st =
- s_alloc_state(pdev->v_memory, s_A85E_template.stype,
- "psdf_begin_binary");
-
- if (st == 0)
- return_error(gs_error_VMerror);
- psdf_encode_binary(pbw, &s_A85E_template, st);
+ s_init(&pbw->A85E.s, NULL);
+ s_init_state((stream_state *)&pbw->A85E.state, &s_A85E_template, NULL);
+ s_init_filter(&pbw->A85E.s, (stream_state *)&pbw->A85E.state,
+ pbw->buf, sizeof(pbw->buf), pdev->strm);
+ pbw->strm = &pbw->A85E.s;
+ } else {
+ memset(&pbw->A85E.s, 0, sizeof(pbw->A85E.s)); /* for GC */
+ pbw->strm = pdev->strm;
}
return 0;
}
@@ -216,39 +259,16 @@ int
psdf_encode_binary(psdf_binary_writer * pbw, const stream_template * template,
stream_state * ss)
{
- gx_device_psdf *pdev = pbw->dev;
- gs_memory_t *mem = pdev->v_memory;
- stream *es = s_alloc(mem, "psdf_encode_binary(stream)");
- stream_state *ess = (ss == 0 ? (stream_state *) es : ss);
- uint bsize = max(template->min_out_size, 256); /* arbitrary */
- byte *buf = gs_alloc_bytes(mem, bsize, "psdf_encode_binary(buf)");
-
- if (es == 0 || buf == 0) {
- gs_free_object(mem, buf, "psdf_encode_binary(buf)");
- gs_free_object(mem, es, "psdf_encode_binary(stream)");
- return_error(gs_error_VMerror);
- }
- if (ess == 0)
- ess = (stream_state *) es;
- s_std_init(es, buf, bsize, &s_filter_write_procs, s_mode_write);
- ess->template = template;
- ess->memory = mem;
- es->procs.process = template->process;
- es->memory = mem;
- es->state = ess;
- if (template->init)
- (*template->init) (ess);
- es->strm = pbw->strm;
- pbw->strm = es;
- return 0;
+ return (s_add_filter(&pbw->strm, template, ss, pbw->memory) == 0 ?
+ gs_note_error(gs_error_VMerror) : 0);
}
/* Add a 2-D CCITTFax encoding filter. */
+/* Set EndOfBlock iff the stream is not ASCII85 encoded. */
int
psdf_CFE_binary(psdf_binary_writer * pbw, int w, int h, bool invert)
{
- gx_device_psdf *pdev = pbw->dev;
- gs_memory_t *mem = pdev->v_memory;
+ gs_memory_t *mem = pbw->memory;
const stream_template *template = &s_CFE_template;
stream_CFE_state *st =
gs_alloc_struct(mem, stream_CFE_state, template->stype,
@@ -262,7 +282,7 @@ psdf_CFE_binary(psdf_binary_writer * pbw, int w, int h, bool invert)
st->Columns = w;
st->Rows = 0;
st->BlackIs1 = !invert;
- st->EndOfBlock = true;
+ st->EndOfBlock = pbw->strm->state->template != &s_A85E_template;
code = psdf_encode_binary(pbw, template, (stream_state *) st);
if (code < 0)
gs_free_object(mem, st, "psdf_CFE_binary");
@@ -273,251 +293,93 @@ psdf_CFE_binary(psdf_binary_writer * pbw, int w, int h, bool invert)
int
psdf_end_binary(psdf_binary_writer * pbw)
{
- gx_device_psdf *pdev = pbw->dev;
-
- /* Close the filters in reverse order. */
- /* Stop before we try to close the file stream. */
- while (pbw->strm != pdev->strm) {
- stream *s = pbw->strm;
- gs_memory_t *mem = s->state->memory;
- byte *sbuf = s->cbuf;
- stream *next = s->strm;
-
- sclose(s);
- if (s->state != (stream_state *)s)
- gs_free_object(mem, s->state, "psdf_end_binary(state)");
- gs_free_object(mem, s, "psdf_end_binary(stream)");
- gs_free_object(mem, sbuf, "psdf_end_binary(buf)");
- pbw->strm = next;
- }
- return 0;
+ return s_close_filters(&pbw->strm, pbw->target);
}
-/*
- * Write a string in its shortest form ( () or <> ). Note that
- * this form is different depending on whether binary data are allowed.
- * Currently we don't support ASCII85 strings ( <~ ~> ).
- */
+/* ---------------- Embedded font writing ---------------- */
+
+/* Begin enumerating the glyphs in a font or a font subset. */
void
-psdf_write_string(stream * s, const byte * str, uint size, int print_ok)
+psdf_enumerate_glyphs_begin(psdf_glyph_enum_t *ppge, gs_font *font,
+ gs_glyph *subset_glyphs, uint subset_size,
+ gs_glyph_space_t glyph_space)
{
- uint added = 0;
- uint i;
- const stream_template *template;
- stream_AXE_state state;
- stream_state *st = NULL;
-
- if (print_ok & print_binary_ok) { /* Only need to escape (, ), \, CR, EOL. */
- pputc(s, '(');
- for (i = 0; i < size; ++i) {
- byte ch = str[i];
-
- switch (ch) {
- case char_CR:
- pputs(s, "\\r");
- continue;
- case char_EOL:
- pputs(s, "\\n");
- continue;
- case '(':
- case ')':
- case '\\':
- pputc(s, '\\');
- }
- pputc(s, ch);
- }
- pputc(s, ')');
- return;
- }
- for (i = 0; i < size; ++i) {
- byte ch = str[i];
-
- if (ch == 0 || ch >= 127)
- added += 3;
- else if (strchr("()\\\n\r\t\b\f", ch) != 0)
- ++added;
- else if (ch < 32)
- added += 3;
- }
-
- if (added < size) { /* More efficient to represent as PostScript string. */
- template = &s_PSSE_template;
- pputc(s, '(');
- } else { /* More efficient to represent as hex string. */
- template = &s_AXE_template;
- st = (stream_state *) & state;
- s_AXE_init_inline(&state);
- pputc(s, '<');
- }
-
- {
- byte buf[100]; /* size is arbitrary */
- stream_cursor_read r;
- stream_cursor_write w;
- int status;
-
- r.ptr = str - 1;
- r.limit = r.ptr + size;
- w.limit = buf + sizeof(buf) - 1;
- do {
- w.ptr = buf - 1;
- status = (*template->process) (st, &r, &w, true);
- pwrite(s, buf, (uint) (w.ptr + 1 - buf));
- }
- while (status == 1);
- }
+ ppge->font = font;
+ ppge->subset_glyphs = subset_glyphs;
+ ppge->subset_size = subset_size;
+ ppge->glyph_space = glyph_space;
+ psdf_enumerate_glyphs_reset(ppge);
}
-/* Set up a write stream that just keeps track of the position. */
-int
-psdf_alloc_position_stream(stream ** ps, gs_memory_t * mem)
+/* Reset a glyph enumeration. */
+void
+psdf_enumerate_glyphs_reset(psdf_glyph_enum_t *ppge)
{
- stream *s = *ps = s_alloc(mem, "psdf_alloc_position_stream");
-
- if (s == 0)
- return_error(gs_error_VMerror);
- swrite_position_only(s);
- return 0;
+ ppge->index = 0;
}
-/* ---------------- Parameter printing ---------------- */
-
-typedef struct printer_param_list_s {
- gs_param_list_common;
- stream *strm;
- param_printer_params_t params;
- int print_ok;
- bool any;
-} printer_param_list_t;
-
-gs_private_st_ptrs1(st_printer_param_list, printer_param_list_t,
- "printer_param_list_t", printer_plist_enum_ptrs, printer_plist_reloc_ptrs,
- strm);
-const param_printer_params_t param_printer_params_default =
-{
- param_printer_params_default_values
-};
-
-/* We'll implement the other printers later if we have to. */
-private param_proc_xmit_typed(param_print_typed);
-/*private param_proc_begin_xmit_collection(param_print_begin_collection); */
-/*private param_proc_end_xmit_collection(param_print_end_collection); */
-private const gs_param_list_procs printer_param_list_procs = {
- param_print_typed,
- NULL /* begin_collection */ ,
- NULL /* end_collection */ ,
- NULL /* get_next_key */ ,
- gs_param_request_default,
- gs_param_requested_default
-};
-
+/* Enumerate the next glyph in a font or a font subset. */
+/* Return 0 if more glyphs, 1 if done, <0 if error. */
int
-psdf_alloc_param_printer(gs_param_list ** pplist,
- const param_printer_params_t * ppp, stream * s,
- int print_ok, gs_memory_t * mem)
+psdf_enumerate_glyphs_next(psdf_glyph_enum_t *ppge, gs_glyph *pglyph)
{
- printer_param_list_t *prlist =
- gs_alloc_struct(mem, printer_param_list_t, &st_printer_param_list,
- "psdf_alloc_param_printer");
-
- *pplist = (gs_param_list *) prlist;
- if (prlist == 0)
- return_error(gs_error_VMerror);
- prlist->procs = &printer_param_list_procs;
- prlist->memory = mem;
- prlist->strm = s;
- prlist->params = *ppp;
- prlist->print_ok = print_ok;
- prlist->any = false;
- return 0;
+ if (ppge->subset_size) {
+ if (ppge->index >= ppge->subset_size)
+ return 1;
+ *pglyph =
+ (ppge->subset_glyphs ? ppge->subset_glyphs[ppge->index++] :
+ (gs_glyph)(ppge->index++ + gs_min_cid_glyph));
+ return 0;
+ } else {
+ gs_font *font = ppge->font;
+ int index = (int)ppge->index;
+ int code = font->procs.enumerate_glyph(font, &index,
+ ppge->glyph_space, pglyph);
+
+ ppge->index = index;
+ return (index == 0 ? 1 : code < 0 ? code : 0);
+ }
}
-void
-psdf_free_param_printer(gs_param_list * plist)
+/*
+ * Get the set of referenced glyphs (indices) for writing a subset font.
+ * Does not sort or remove duplicates.
+ */
+int
+psdf_subset_glyphs(gs_glyph glyphs[256], gs_font *font, const byte used[32])
{
- if (plist) {
- printer_param_list_t *prlist = (printer_param_list_t *) plist;
+ int i, n;
- if (prlist->any && prlist->params.suffix)
- pputs(prlist->strm, prlist->params.suffix);
- gs_free_object(prlist->memory, plist, "psdf_free_param_printer");
- }
+ for (i = n = 0; i < 256; ++i)
+ if (used[i >> 3] & (1 << (i & 7))) {
+ gs_glyph glyph = font->procs.encode_char(font, (gs_char)i,
+ GLYPH_SPACE_INDEX);
+
+ if (glyph != gs_no_glyph)
+ glyphs[n++] = glyph;
+ }
+ return n;
}
-#define prlist ((printer_param_list_t *)plist)
+/*
+ * Sort a list of glyphs and remove duplicates. Return the number of glyphs
+ * in the result.
+ */
private int
-param_print_typed(gs_param_list * plist, gs_param_name pkey,
- gs_param_typed_value * pvalue)
+compare_glyphs(const void *pg1, const void *pg2)
{
- stream *s = prlist->strm;
+ gs_glyph g1 = *(const gs_glyph *)pg1, g2 = *(const gs_glyph *)pg2;
- if (!prlist->any) {
- if (prlist->params.prefix)
- pputs(s, prlist->params.prefix);
- prlist->any = true;
- }
- if (prlist->params.item_prefix)
- pputs(s, prlist->params.item_prefix);
- pprints1(s, "/%s", pkey);
- switch (pvalue->type) {
- case gs_param_type_null:
- pputs(s, " null");
- break;
- case gs_param_type_bool:
- pputs(s, (pvalue->value.b ? " true" : " false"));
- break;
- case gs_param_type_int:
- pprintd1(s, " %d", pvalue->value.i);
- break;
- case gs_param_type_long:
- pprintld1(s, " %l", pvalue->value.l);
- break;
- case gs_param_type_float:
- pprintg1(s, " %g", pvalue->value.f);
- break;
- case gs_param_type_string:
- psdf_write_string(s, pvalue->value.s.data, pvalue->value.s.size,
- prlist->print_ok);
- break;
- case gs_param_type_name:
-/****** SHOULD USE #-ESCAPES FOR PDF ******/
- pputc(s, '/');
- pwrite(s, pvalue->value.n.data, pvalue->value.n.size);
- break;
- case gs_param_type_int_array:
- {
- uint i;
- char sepr = (pvalue->value.ia.size <= 10 ? ' ' : '\n');
-
- pputc(s, '[');
- for (i = 0; i < pvalue->value.ia.size; ++i) {
- pprintd1(s, "%d", pvalue->value.ia.data[i]);
- pputc(s, sepr);
- }
- pputc(s, ']');
- }
- break;
- case gs_param_type_float_array:
- {
- uint i;
- char sepr = (pvalue->value.fa.size <= 10 ? ' ' : '\n');
-
- pputc(s, '[');
- for (i = 0; i < pvalue->value.fa.size; ++i) {
- pprintg1(s, "%g", pvalue->value.fa.data[i]);
- pputc(s, sepr);
- }
- pputc(s, ']');
- }
- break;
- /*case gs_param_type_string_array: */
- /*case gs_param_type_name_array: */
- default:
- return_error(gs_error_typecheck);
- }
- if (prlist->params.item_suffix)
- pputs(s, prlist->params.item_suffix);
- return 0;
+ return (g1 < g2 ? -1 : g1 > g2 ? 1 : 0);
}
+int
+psdf_sort_glyphs(gs_glyph *glyphs, int count)
+{
+ int i, n;
-#undef prlist
+ qsort(glyphs, count, sizeof(*glyphs), compare_glyphs);
+ for (i = n = 0; i < count; ++i)
+ if (i == 0 || glyphs[i] != glyphs[i - 1])
+ glyphs[n++] = glyphs[i];
+ return n;
+}
diff --git a/gs/src/gdevpsdf.h b/gs/src/gdevpsdf.h
index d4232248f..c0b094cfe 100644
--- a/gs/src/gdevpsdf.h
+++ b/gs/src/gdevpsdf.h
@@ -25,7 +25,17 @@
#include "gdevvec.h"
#include "gsparam.h"
#include "strimpl.h"
+#include "sa85x.h"
#include "scfx.h"
+#include "spsdf.h"
+
+extern const stream_template s_DCTE_template; /* don't want all of sdct.h */
+
+/*
+ * NOTE: the default filter for color and gray images should be DCTEncode.
+ * We don't currently set this, because the management of the parameters
+ * for this filter simply doesn't work.
+ */
/* ---------------- Distiller parameters ---------------- */
@@ -96,14 +106,14 @@ typedef struct psdf_distiller_params_s {
bool ConvertCMYKImagesToRGB;
bool ConvertImagesToIndexed;
#define psdf_color_image_param_defaults\
- { psdf_image_param_defaults(1/*true*/, 72, 0, 0) },\
- ccs_LeaveColorUnchanged, 1/*true*/, 0 /*false */
+ { psdf_image_param_defaults(1/*true*/, 72, 0/*"DCTEncode"*/, 0/*&s_DCTE_template*/) },\
+ ccs_LeaveColorUnchanged, 1/*true*/, 0/*false */
/* Grayscale sampled image parameters */
psdf_image_params GrayImage;
#define psdf_gray_image_param_defaults\
- { psdf_image_param_defaults(1/*true*/, 72, 0, 0) }
+ { psdf_image_param_defaults(1/*true*/, 72, 0/*"DCTEncode"*/, 0/*&s_DCTE_template*/) }
/* Monochrome sampled image parameters */
@@ -203,9 +213,24 @@ int psdf_closepath(P6(gx_device_vector * vdev, floatp x0, floatp y0,
/* Define the structure for writing binary data. */
typedef struct psdf_binary_writer_s {
- stream *strm;
- gx_device_psdf *dev;
+ /* Preallocate an ASCII85Encode filter. */
+ byte buf[100]; /* arbitrary, but must be first */
+ /* for pointers from A85E.s */
+ struct {
+ stream s;
+ stream_A85E_state state;
+ } A85E;
+ stream *target; /* underlying stream */
+ gs_memory_t *memory;
+ stream *strm; /* may point to A85E.s */
+ gx_device_psdf *dev; /* may be unused */
} psdf_binary_writer;
+extern_st(st_psdf_binary_writer);
+#define public_st_psdf_binary_writer() /* in gdevpsdf.c */\
+ gs_public_st_composite(st_psdf_binary_writer, psdf_binary_writer,\
+ "psdf_binary_writer", psdf_binary_writer_enum_ptrs,\
+ psdf_binary_writer_reloc_ptrs)
+#define psdf_binary_writer_max_ptrs (stream_num_ptrs + 3)
/* Begin writing binary data. */
int psdf_begin_binary(P2(gx_device_psdf * pdev, psdf_binary_writer * pbw));
@@ -216,60 +241,108 @@ int psdf_encode_binary(P3(psdf_binary_writer * pbw,
const stream_template * template, stream_state * ss));
/* Add a 2-D CCITTFax encoding filter. */
+/* Set EndOfBlock iff the stream is not ASCII85 encoded. */
int psdf_CFE_binary(P4(psdf_binary_writer * pbw, int w, int h, bool invert));
/* Set up compression and downsampling filters for an image. */
/* Note that this may modify the image parameters. */
/* If pctm is NULL, downsampling is not used. */
/* pis only provides UCR and BG information for CMYK => RGB conversion. */
-int psdf_setup_image_filters(P5(gx_device_psdf * pdev, psdf_binary_writer * pbw,
- gs_image_t * pim, const gs_matrix * pctm,
+int psdf_setup_image_filters(P5(gx_device_psdf *pdev, psdf_binary_writer *pbw,
+ gs_image_t *pim, const gs_matrix *pctm,
const gs_imager_state * pis));
/* Finish writing binary data. */
int psdf_end_binary(P1(psdf_binary_writer * pbw));
-/* ------ Symbolic data printing ------ */
+/* ---------------- Embedded font writing ---------------- */
+
+typedef struct psdf_glyph_enum_s {
+ gs_font *font;
+ gs_glyph *subset_glyphs;
+ uint subset_size;
+ gs_glyph_space_t glyph_space;
+ ulong index;
+} psdf_glyph_enum_t;
+
+/*
+ * Begin enumerating the glyphs in a font or a font subset. If subset_size
+ * > 0 but subset_glyphs == 0, enumerate all glyphs in [0 .. subset_size-1]
+ * (as integer glyphs, i.e., offset by gs_min_cid_glyph).
+ */
+void psdf_enumerate_glyphs_begin(P5(psdf_glyph_enum_t *ppge, gs_font *font,
+ gs_glyph *subset_glyphs,
+ uint subset_size,
+ gs_glyph_space_t glyph_space));
+
+/* Reset a glyph enumeration. */
+void psdf_enumerate_glyphs_reset(P1(psdf_glyph_enum_t *ppge));
+
+/* Enumerate the next glyph in a font or a font subset. */
+/* Return 0 if more glyphs, 1 if done, <0 if error. */
+int psdf_enumerate_glyphs_next(P2(psdf_glyph_enum_t *ppge, gs_glyph *pglyph));
-/* Print a PostScript string in the most efficient form. */
-#define print_binary_ok 1
-#define print_ASCII85_ok 2
-void psdf_write_string(P4(stream * s, const byte * str, uint size,
- int print_ok));
+/*
+ * Get the set of referenced glyphs (indices) for writing a subset font.
+ * Does not sort or remove duplicates.
+ */
+int psdf_subset_glyphs(P3(gs_glyph glyphs[256], gs_font *font,
+ const byte used[32]));
/*
- * Create a stream that just keeps track of how much has been written
- * to it. We use this for measuring data that will be stored rather
- * than written to an actual stream. This too should probably migrate
- * to stream.c....
+ * Sort a list of glyphs and remove duplicates. Return the number of glyphs
+ * in the result.
*/
-int psdf_alloc_position_stream(P2(stream ** ps, gs_memory_t * mem));
+int psdf_sort_glyphs(P2(gs_glyph *glyphs, int count));
+
+/* ------ Exported by gdevpsd1.c ------ */
/*
- * Create/release a parameter list for printing (non-default) filter
- * parameters. This should probably migrate to a lower level....
+ * Write out a Type 1 font definition. This procedure does not allocate
+ * or free any data.
*/
-typedef struct param_printer_params_s {
- const char *prefix; /* before entire object, if any params */
- const char *suffix; /* after entire object, if any params */
- const char *item_prefix; /* before each param */
- const char *item_suffix; /* after each param */
-} param_printer_params_t;
-
-#define param_printer_params_default_values 0, 0, 0, "\n"
-extern const param_printer_params_t param_printer_params_default;
-int psdf_alloc_param_printer(P5(gs_param_list ** pplist,
- const param_printer_params_t * ppp, stream * s,
- int print_ok, gs_memory_t * mem));
-void psdf_free_param_printer(P1(gs_param_list * plist));
-
-/* Write out a Type 1 font definition. */
#ifndef gs_font_type1_DEFINED
# define gs_font_type1_DEFINED
typedef struct gs_font_type1_s gs_font_type1;
+#endif
+#define WRITE_TYPE1_EEXEC 1
+#define WRITE_TYPE1_ASCIIHEX 2 /* use ASCII hex rather than binary */
+#define WRITE_TYPE1_EEXEC_PAD 4 /* add 512 0s */
+#define WRITE_TYPE1_EEXEC_MARK 8 /* assume 512 0s will be added */
+#define WRITE_TYPE1_POSTSCRIPT 16 /* don't observe ATM restrictions */
+int psdf_write_type1_font(P7(stream *s, gs_font_type1 *pfont, int options,
+ gs_glyph *subset_glyphs, uint subset_size,
+ const gs_const_string *alt_font_name,
+ int lengths[3]));
+
+/* ------ Exported by gdevpsdt.c ------ */
+/*
+ * Write out a TrueType (Type 42) font definition. This procedure does
+ * not allocate or free any data.
+ */
+#ifndef gs_font_type42_DEFINED
+# define gs_font_type42_DEFINED
+typedef struct gs_font_type42_s gs_font_type42;
#endif
-int psdf_embed_type1_font(P2(stream * s, gs_font_type1 * pfont));
+#define WRITE_TRUETYPE_CMAP 1 /* generate cmap from the Encoding */
+#define WRITE_TRUETYPE_NAME 2 /* generate name if missing */
+#define WRITE_TRUETYPE_POST 4 /* generate post if missing */
+int psdf_write_truetype_font(P6(stream *s, gs_font_type42 *pfont, int options,
+ gs_glyph *subset_glyphs, uint subset_size,
+ const gs_const_string *alt_font_name));
+
+/* ---------------- Symbolic data printing ---------------- */
+
+/* Backward compatibility definitions. */
+#define psdf_write_string(s, str, size, print_ok)\
+ s_write_ps_string(s, str, size, print_ok)
+#define psdf_alloc_position_stream(ps, mem)\
+ s_alloc_position_stream(ps, mem)
+#define psdf_alloc_param_printer(pplist, ppp, s, mem)\
+ s_alloc_param_printer(pplist, ppp, s, mem)
+#define psdf_free_param_printer(plist)\
+ s_free_param_printer(plist)
/* ---------------- Other procedures ---------------- */
diff --git a/gs/src/gdevpsdi.c b/gs/src/gdevpsdi.c
index 0ed4ee310..1bb0106ae 100644
--- a/gs/src/gdevpsdi.c
+++ b/gs/src/gdevpsdi.c
@@ -99,7 +99,9 @@ setup_image_compression(psdf_binary_writer *pbw, const psdf_image_params *pdip,
pdev->version >= psdf_version_ll3 ?
&s_zlibE_template : &s_LZWE_template);
}
- if (!pdip->Encode || template == 0) /* no compression */
+ if (!pdip->Encode || template == 0) /* no compression */
+ return 0;
+ if (pim->Width * pim->Height <= 16) /* not worth compressing */
return 0;
/* Only use DCTE for 8-bit data. */
if (template == &s_DCTE_template &&
diff --git a/gs/src/gdevpsdp.c b/gs/src/gdevpsdp.c
index ecd123b20..8c953ea06 100644
--- a/gs/src/gdevpsdp.c
+++ b/gs/src/gdevpsdp.c
@@ -22,17 +22,22 @@
#include "jpeglib_.h" /* for sdct.h */
#include "gx.h"
#include "gserrors.h"
+#include "gsutil.h"
#include "gxdevice.h"
#include "gsparamx.h"
#include "gdevpsdf.h"
-#include "gdevpstr.h"
#include "strimpl.h" /* for short-sighted compilers */
#include "scfx.h"
#include "sdct.h"
#include "slzwx.h"
+#include "spprint.h"
#include "srlx.h"
#include "szlibx.h"
+/* Define a (bogus) GC descriptor for gs_param_string. */
+/****** FIX THIS ******/
+gs_private_st_simple(st_gs_param_string, gs_param_string, "gs_param_string");
+
/* ---------------- Get/put Distiller parameters ---------------- */
/*
@@ -41,6 +46,17 @@
* parameters actually to have any effect.)
*/
+/*
+ * The Always/NeverEmbed parameters are defined as being incremental. Since
+ * this isn't compatible with the general property of page devices that if
+ * you do a getpagedevice, doing a setpagedevice later will restore the same
+ * state, we actually define the parameters in sets of 3:
+ * - AlwaysEmbed is used for incremental additions.
+ * - ~AlwaysEmbed is used for incremental deletions.
+ * - .AlwaysEmbed is used for the complete list.
+ * and analogously for NeverEmbed.
+ */
+
typedef struct psdf_image_filter_name_s {
const char *pname;
const stream_template *template;
@@ -203,6 +219,18 @@ psdf_get_image_params(gs_param_list * plist,
return code;
}
+/* Get a font embedding parameter. */
+private int
+psdf_get_embed_param(gs_param_list *plist, gs_param_name allpname,
+ const gs_param_string_array *psa)
+{
+ int code = param_write_name_array(plist, allpname, psa);
+
+ if (code >= 0)
+ code = param_write_name_array(plist, allpname + 1, psa);
+ return code;
+}
+
/* Get parameters. */
int
gdev_psdf_get_params(gx_device * dev, gs_param_list * plist)
@@ -265,8 +293,8 @@ gdev_psdf_get_params(gx_device * dev, gs_param_list * plist)
/* Font embedding parameters */
- (code = param_write_name_array(plist, "AlwaysEmbed", &pdev->params.AlwaysEmbed)) < 0 ||
- (code = param_write_name_array(plist, "NeverEmbed", &pdev->params.NeverEmbed)) < 0 ||
+ (code = psdf_get_embed_param(plist, ".AlwaysEmbed", &pdev->params.AlwaysEmbed)) < 0 ||
+ (code = psdf_get_embed_param(plist, ".NeverEmbed", &pdev->params.NeverEmbed)) < 0 ||
(code = param_write_bool(plist, "EmbedAllFonts", &pdev->params.EmbedAllFonts)) < 0 ||
(code = param_write_bool(plist, "SubsetFonts", &pdev->params.SubsetFonts)) < 0 ||
(code = param_write_int(plist, "MaxSubsetPct", &pdev->params.MaxSubsetPct)) < 0
@@ -297,17 +325,24 @@ psdf_DCT_put_params(gs_param_list * plist, stream_state * ss)
}
/* Put [~](Always|Never)Embed parameters. */
+private bool
+param_string_eq(const gs_param_string *ps1, const gs_param_string *ps2)
+{
+ return !bytes_compare(ps1->data, ps1->size, ps2->data, ps2->size);
+}
private int
psdf_put_embed_param(gs_param_list * plist, gs_param_name notpname,
- gs_param_string_array * psa, int ecode)
+ gs_param_name allpname, gs_param_string_array * psa,
+ gs_memory_t *mem, int ecode)
{
gs_param_name pname = notpname + 1;
int code;
- gs_param_string_array nsa;
+ gs_param_string_array sa, nsa, asa;
+ bool replace;
-/***** Storage management is incomplete ******/
-/***** Doesn't do incremental add/delete ******/
- switch (code = param_read_name_array(plist, pname, psa)) {
+ /***** Storage management is incomplete ******/
+ sa.data = 0, sa.size = 0;
+ switch (code = param_read_name_array(plist, pname, &sa)) {
default:
ecode = code;
param_signal_error(plist, pname, ecode);
@@ -315,6 +350,7 @@ psdf_put_embed_param(gs_param_list * plist, gs_param_name notpname,
case 1:
break;
}
+ nsa.data = 0, nsa.size = 0;
switch (code = param_read_name_array(plist, notpname, &nsa)) {
default:
ecode = code;
@@ -323,7 +359,87 @@ psdf_put_embed_param(gs_param_list * plist, gs_param_name notpname,
case 1:
break;
}
- return ecode;
+ asa.data = 0, asa.size = 0;
+ switch (code = param_read_name_array(plist, allpname, &asa)) {
+ default:
+ ecode = code;
+ param_signal_error(plist, allpname, ecode);
+ case 0:
+ case 1:
+ break;
+ }
+ if (ecode < 0)
+ return ecode;
+ /*
+ * Figure out whether we're replacing (sa == asa or asa and no sa,
+ * no nsa) or updating (all other cases).
+ */
+ if (asa.data == 0 || nsa.data != 0)
+ replace = false;
+ else if (sa.data == 0)
+ replace = true;
+ else if (sa.size != asa.size)
+ replace = false;
+ else {
+ /* Test whether sa == asa. */
+ uint i;
+
+ replace = true;
+ for (i = 0; i < sa.size; ++i)
+ if (!param_string_eq(&sa.data[i], &asa.data[i])) {
+ replace = false;
+ break;
+ }
+ }
+ if (replace) {
+ /****** FREE OLD ARRAY ******/
+ *psa = asa;
+ } else if (sa.data || nsa.data) {
+ /* Incremental update. */
+ gs_param_string_array rsa;
+ gs_param_string *rdata;
+ uint i;
+ uint count = psa->size;
+
+ rdata = gs_alloc_struct_array(mem, count + sa.size,
+ gs_param_string, &st_gs_param_string,
+ "psdf_put_embed_param");
+ if (rdata == 0)
+ return_error(gs_error_VMerror);
+ memcpy(rdata, psa->data, psa->size * sizeof(*psa->data));
+ /* Add sa to *psa. */
+ for (i = 0; i < sa.size; ++i) {
+ uint j;
+
+ for (j = 0; j < count; ++j)
+ if (param_string_eq(&sa.data[i], &rdata[j]))
+ break;
+ if (j == count)
+ rdata[count++] = sa.data[i];
+ else {
+ /****** FREE sa.data[i] ******/
+ }
+ }
+ /* Delete nsa from *psa. */
+ for (i = 0; i < nsa.size; ++i) {
+ uint j;
+
+ for (j = 0; j < count; ++j)
+ if (param_string_eq(&sa.data[i], &rdata[j]))
+ break;
+ if (j < count) {
+ /****** FREE rdata[j] ******/
+ rdata[j] = rdata[--count];
+ }
+ /****** FREE nsa.data[i] ******/
+ }
+ rdata = gs_resize_object(mem, rdata, count, "psdf_put_embed_param");
+ rsa.data = rdata;
+ rsa.size = count;
+ rsa.persistent = true;
+ *psa = rsa;
+ }
+ return 0;
}
/* Put an image Dict parameter. */
@@ -479,6 +595,8 @@ int
gdev_psdf_put_params(gx_device * dev, gs_param_list * plist)
{
gx_device_psdf *pdev = (gx_device_psdf *) dev;
+ gs_memory_t *mem =
+ (pdev->v_memory ? pdev->v_memory : dev->memory);
int ecode = 0;
int code;
gs_param_name param_name;
@@ -561,10 +679,10 @@ gdev_psdf_put_params(gx_device * dev, gs_param_list * plist)
/* Font embedding parameters */
- ecode = psdf_put_embed_param(plist, "~AlwaysEmbed",
- &params.AlwaysEmbed, ecode);
- ecode = psdf_put_embed_param(plist, "~NeverEmbed",
- &params.NeverEmbed, ecode);
+ ecode = psdf_put_embed_param(plist, "~AlwaysEmbed", ".AlwaysEmbed",
+ &params.AlwaysEmbed, mem, ecode);
+ ecode = psdf_put_embed_param(plist, "~NeverEmbed", ".NeverEmbed",
+ &params.NeverEmbed, mem, ecode);
ecode = param_put_bool(plist, "EmbedAllFonts",
&params.EmbedAllFonts, ecode);
ecode = param_put_bool(plist, "SubsetFonts",
diff --git a/gs/src/gdevpsds.c b/gs/src/gdevpsds.c
index e119a4d62..ccf8fa32f 100644
--- a/gs/src/gdevpsds.c
+++ b/gs/src/gdevpsds.c
@@ -302,6 +302,15 @@ const stream_template s_8_4_template = {
private_st_C2R_state();
+/* Set default parameter values (actually, just clear pointers). */
+private void
+s_C2R_set_defaults(stream_state * st)
+{
+ stream_C2R_state *const ss = (stream_C2R_state *) st;
+
+ ss->pis = 0;
+}
+
/* Process one buffer. */
private int
s_C2R_process(stream_state * st, stream_cursor_read * pr,
@@ -330,7 +339,7 @@ s_C2R_process(stream_state * st, stream_cursor_read * pr,
const stream_template s_C2R_template =
{
- &st_C2R_state, 0 /*NULL */ , s_C2R_process, 4, 3
+ &st_C2R_state, 0 /*NULL */ , s_C2R_process, 4, 3, 0, s_C2R_set_defaults
};
/* ---------------- Downsampling ---------------- */
@@ -411,6 +420,17 @@ const stream_template s_Subsample_template =
private_st_Average_state();
+/* Set default parameter values (actually, just clear pointers). */
+private void
+s_Average_set_defaults(stream_state * st)
+{
+ stream_Average_state *const ss = (stream_Average_state *) st;
+
+ s_Downsample_set_defaults(st);
+ /* Clear pointers */
+ ss->sums = 0;
+}
+
/* Initialize the state. */
private int
s_Average_init(stream_state * st)
@@ -497,5 +517,5 @@ out:
const stream_template s_Average_template =
{
&st_Average_state, s_Average_init, s_Average_process, 4, 4,
- s_Average_release, s_Downsample_set_defaults
+ s_Average_release, s_Average_set_defaults
};
diff --git a/gs/src/gdevpsdt.c b/gs/src/gdevpsdt.c
new file mode 100644
index 000000000..0889a7fdc
--- /dev/null
+++ b/gs/src/gdevpsdt.c
@@ -0,0 +1,776 @@
+/* Copyright (C) 1999 Aladdin Enterprises. All rights reserved.
+
+ This file is part of Aladdin Ghostscript.
+
+ Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
+ or distributor accepts any responsibility for the consequences of using it,
+ or for whether it serves any particular purpose or works at all, unless he
+ or she says so in writing. Refer to the Aladdin Ghostscript Free Public
+ License (the "License") for full details.
+
+ Every copy of Aladdin Ghostscript must include a copy of the License,
+ normally in a plain ASCII text file named PUBLIC. The License grants you
+ the right to copy, modify and redistribute Aladdin Ghostscript, but only
+ under certain conditions described in the License. Among other things, the
+ License requires that the copyright notice and this notice be preserved on
+ all copies.
+ */
+
+
+/* Write an embedded TrueType font */
+#include "memory_.h"
+#include <stdlib.h> /* for qsort */
+#include "gx.h"
+#include "gserrors.h"
+#include "gsmatrix.h"
+#include "gsutil.h"
+#include "gxfont.h"
+#include "gxfont42.h"
+#include "stream.h"
+#include "spprint.h"
+#include "gdevpsdf.h"
+
+#define ACCESS(base, length, vptr)\
+ BEGIN\
+ code = string_proc(pfont, (ulong)(base), length, &vptr);\
+ if ( code < 0 ) return code;\
+ END
+
+/* Pad to a multiple of 4 bytes. */
+private void
+put_pad(stream *s, uint length)
+{
+ static const byte pad_to_4[3] = {0, 0, 0};
+
+ pwrite(s, pad_to_4, (uint)(-length & 3));
+}
+
+/* Put short and long values on a stream. */
+private void
+put_ushort(stream *s, uint v)
+{
+ pputc(s, (byte)(v >> 8));
+ pputc(s, (byte)v);
+}
+private void
+put_ulong(stream *s, ulong v)
+{
+ put_ushort(s, (uint)(v >> 16));
+ put_ushort(s, (uint)v);
+}
+private void
+put_loca(stream *s, ulong offset, int indexToLocFormat)
+{
+ if (indexToLocFormat)
+ put_ulong(s, offset);
+ else
+ put_ushort(s, (uint)(offset >> 1));
+}
+
+/* Get or put 2- or 4-byte quantities from/into a table. */
+#define U8(p) ((uint)((p)[0]))
+#define S8(p) (int)((U8(p) ^ 0x80) - 0x80)
+#define U16(p) (((uint)((p)[0]) << 8) + (p)[1])
+#define S16(p) (int)((U16(p) ^ 0x8000) - 0x8000)
+private ulong
+u32(const byte *p)
+{
+ return ((ulong)U16(p) << 16) + U16((p) + 2);
+}
+private void
+put_u16(byte *p, uint v)
+{
+ p[0] = (byte)(v >> 8);
+ p[1] = (byte)v;
+}
+private void
+put_u32(byte *p, ulong v)
+{
+ p[0] = (byte)(v >> 24);
+ p[1] = (byte)(v >> 16);
+ p[2] = (byte)(v >> 8);
+ p[3] = (byte)v;
+}
+private ulong
+put_table(byte tab[16], const char *tname, ulong checksum, ulong offset,
+ uint length)
+{
+ memcpy(tab, (const byte *)tname, 4);
+ put_u32(tab + 4, checksum);
+ put_u32(tab + 8, offset + 0x40000000);
+ put_u32(tab + 12, (ulong)length);
+ return offset + round_up(length, 4);
+}
+
+/* Write one range of a TrueType font. */
+private int
+write_range(stream *s, gs_font_type42 *pfont, ulong start, uint length)
+{
+ ulong base = start;
+ ulong limit = base + length;
+ int (*string_proc)(P4(gs_font_type42 *, ulong, uint, const byte **)) =
+ pfont->data.string_proc;
+
+ if_debug3('l', "[l]write_range pos = %ld, start = %lu, length = %u\n",
+ stell(s), start, length);
+ while (base < limit) {
+ uint size = limit - base;
+ const byte *ptr;
+ int code;
+
+ /* Write the largest block we can access consecutively. */
+ while ((code = string_proc(pfont, base, size, &ptr)) < 0) {
+ if (size <= 1)
+ return code;
+ size >>= 1;
+ }
+ pwrite(s, ptr, size);
+ base += size;
+ }
+ return 0;
+}
+
+/*
+ * Determine the Macintosh glyph number for a given character, if any.
+ * If no glyph can be found, return -1 and store the name in *pstr.
+ */
+private int
+mac_glyph_index(gs_font *font, int ch, gs_const_string *pstr)
+{
+ gs_glyph glyph = font->procs.encode_char(font, (gs_char)ch,
+ GLYPH_SPACE_NAME);
+
+ if (glyph == gs_no_glyph)
+ return 0; /* .notdef */
+ pstr->data = (const byte *)
+ font->procs.callbacks.glyph_name(glyph, &pstr->size);
+ if (glyph < gs_min_cid_glyph) {
+ gs_char mac_char;
+ gs_glyph mac_glyph;
+ gs_const_string mstr;
+
+ /* Look (not very hard) for a match in the Mac glyph space. */
+ if (ch >= 32 && ch <= 126)
+ mac_char = ch - 29;
+ else if (ch >= 128 && ch <= 255)
+ mac_char = ch - 30;
+ else
+ return -1;
+ mac_glyph =
+ font->procs.callbacks.known_encode(mac_char,
+ ENCODING_INDEX_MACGLYPH);
+ if (mac_glyph == gs_no_glyph)
+ return -1;
+ mstr.data =(const byte *)
+ font->procs.callbacks.glyph_name(mac_glyph, &mstr.size);
+ if (!bytes_compare(pstr->data, pstr->size, mstr.data, mstr.size))
+ return (int)mac_char;
+ }
+ return -1;
+}
+
+/* Write a generated cmap table. */
+static const byte cmap_initial[] = {
+ 0, 0, /* table version # = 0 */
+ 0, 2, /* # of encoding tables = 2 */
+
+ 0, 1, /* platform ID = Macintosh */
+ 0, 0, /* platform encoding ID = ??? */
+ 0, 0, 0, 4+8+8, /* offset to table start */
+
+ 0, 3, /* platform ID = Microsoft */
+ 0, 0, /* platform encoding ID = unknown */
+ 0, 0, 0, 4+8+8+6, /* offset to table start */
+ /****** VARIABLE, add 2 x # of glyphs ******/
+
+ 0, 0, /* format = 0, byte encoding table */
+ 0, 6, /****** VARIABLE, add 2 x # of glyphs ******/
+ 0, 0
+};
+static const byte cmap_sub_initial[] = {
+ 0, 4, /* format = 4, segment mapping */
+ 0, 32, /* length **VARIABLE, add 2 x # of glyphs ** */
+ 0, 0, /* version # */
+ 0, 4, /* 2 x segCount */
+ 0, 4, /* searchRange = 2 x 2 ^ floor(log2(segCount)) */
+ 0, 1, /* floor(log2(segCount)) */
+ 0, 0, /* 2 x segCount - searchRange */
+
+ 0, 0, /* endCount[0] **VARIABLE** */
+ 255, 255, /* endCount[1] */
+ 0, 0, /* reservedPad */
+ 0, 0, /* startCount[0] **VARIABLE** */
+ 255, 255, /* startCount[1] */
+ 0, 0, /* idDelta[0] */
+ 0, 1, /* idDelta[1] */
+ 0, 4, /* idRangeOffset[0] */
+ 0, 0 /* idRangeOffset[1] */
+};
+private uint
+size_cmap(int num_glyphs)
+{
+ return sizeof(cmap_initial) + sizeof(cmap_sub_initial) + num_glyphs * 4;
+}
+private void
+write_cmap(stream *s, gs_font *font, uint first_glyph, int num_glyphs,
+ gs_glyph max_glyph)
+{
+ byte cmap[sizeof(cmap_initial)];
+ byte cmap_sub[sizeof(cmap_sub_initial)];
+ byte entries[256 * 2];
+ int i;
+
+ /* Collect the table entries. */
+
+ for (i = 0; i < num_glyphs; ++i) {
+ gs_glyph glyph =
+ font->procs.encode_char(font, (gs_char)i, GLYPH_SPACE_INDEX);
+
+ if (glyph == gs_no_glyph || glyph < gs_min_cid_glyph ||
+ glyph > max_glyph
+ )
+ glyph = gs_min_cid_glyph;
+ put_u16(entries + 2 * i, (uint)(glyph - gs_min_cid_glyph));
+ }
+
+ /* Write the table header and Macintosh sub-table. */
+
+ memcpy(cmap, cmap_initial, sizeof(cmap_initial));
+ put_u16(cmap + 18, U16(cmap + 18) + num_glyphs * 2); /* length */
+ put_u16(cmap + 22, U16(cmap + 22) + num_glyphs * 2); /* length */
+ pwrite(s, cmap, sizeof(cmap));
+ pwrite(s, entries, num_glyphs * 2);
+
+ /* Write the Windows sub-table. */
+
+ memcpy(cmap_sub, cmap_sub_initial, sizeof(cmap_sub_initial));
+ put_u16(cmap_sub + 2, U16(cmap_sub + 2) + num_glyphs * 2); /* length */
+ put_u16(cmap_sub + 14, first_glyph + num_glyphs - 1); /* endCount[0] */
+ put_u16(cmap_sub + 20, first_glyph); /* startCount[0] */
+ pwrite(s, cmap_sub, sizeof(cmap_sub));
+ pwrite(s, entries, num_glyphs * 2);
+
+ put_pad(s, size_cmap(num_glyphs));
+}
+
+/* Write a generated name table. */
+static const byte name_initial[] = {
+ 0, 0, /* format */
+ 0, 1, /* # of records = 1 */
+ 0, 18, /* start of string storage */
+
+ 0, 2, /* platform ID = ISO */
+ 0, 2, /* encoding ID = ISO 8859-1 */
+ 0, 0, /* language ID (none) */
+ 0, 6, /* name ID = PostScript name */
+ 0, 0, /* length ****** VARIABLE ****** */
+ 0, 0 /* start of string within string storage */
+};
+private uint
+size_name(const gs_const_string *font_name)
+{
+ return sizeof(name_initial) + font_name->size;
+}
+private void
+write_name(stream *s, const gs_const_string *font_name)
+{
+ byte name_bytes[sizeof(name_initial)];
+
+ memcpy(name_bytes, name_initial, sizeof(name_initial));
+ put_u16(name_bytes + 14, font_name->size);
+ pwrite(s, name_bytes, sizeof(name_bytes));
+ pwrite(s, font_name->data, font_name->size);
+ put_pad(s, size_name(font_name));
+}
+
+/* Write a generated OS/2 table. */
+typedef struct OS_2_s {
+ byte
+ version[2], /* version 0, see below */
+ xAvgCharWidth[2],
+ usWeightClass[2],
+ usWidthClass[2],
+ fsType[2],
+ ySubscriptXSize[2],
+ ySubscriptYSize[2],
+ ySubscriptXOffset[2],
+ ySubscriptYOffset[2],
+ ySuperscriptXSize[2],
+ ySuperscriptYSize[2],
+ ySuperscriptXOffset[2],
+ ySuperscriptYOffset[2],
+ yStrikeoutSize[2],
+ yStrikeoutPosition[2],
+ sFamilyClass[2],
+ /*panose:*/
+ bFamilyType, bSerifStyle, bWeight, bProportion, bContrast,
+ bStrokeVariation, bArmStyle, bLetterform, bMidline, bXHeight,
+ ulUnicodeRanges[16],
+ achVendID[4],
+ fsSelection[2],
+ usFirstCharIndex[2],
+ usLastCharIndex[2],
+ sTypoAscender[2],
+ sTypoDescender[2],
+ sTypoLineGap[2],
+ usWinAscent[2],
+ usWinDescent[2];
+ /*ulCodePageRanges[8];*/ /* not used in OS/2 version 0 */
+} OS_2_t;
+#define OS_2_LENGTH sizeof(OS_2_t)
+private void
+write_OS_2(stream *s, gs_font *font, uint first_glyph, int num_glyphs)
+{
+ OS_2_t os2;
+
+ /*
+ * We don't bother to set most of the fields. The really important
+ * ones, which affect character mapping, are usFirst/LastCharIndex.
+ */
+ memset(&os2, 0, sizeof(os2));
+ put_u16(os2.usFirstCharIndex, first_glyph);
+ put_u16(os2.usLastCharIndex, first_glyph + num_glyphs - 1);
+ pwrite(s, &os2, sizeof(os2));
+ put_pad(s, sizeof(os2));
+}
+
+/* Construct and then write the post table. */
+typedef struct post_glyph_s {
+ byte char_index;
+ byte size;
+ ushort glyph_index;
+} post_glyph_t;
+private int
+compare_post_glyphs(const void *pg1, const void *pg2)
+{
+ gs_glyph g1 = ((const post_glyph_t *)pg1)->glyph_index,
+ g2 = ((const post_glyph_t *)pg2)->glyph_index;
+
+ return (g1 < g2 ? -1 : g1 > g2 ? 1 : 0);
+}
+typedef struct post_s {
+ post_glyph_t glyphs[256 + 1];
+ int count, glyph_count;
+ uint length;
+} post_t;
+
+/*
+ * If necessary, compute the length of the post table. Note that we
+ * only generate post entries for characters in the Encoding.
+ */
+private void
+compute_post(gs_font *font, post_t *post)
+{
+ int i;
+
+ for (i = 0, post->length = 32 + 2; i <= 255; ++i) {
+ gs_const_string str;
+ gs_glyph glyph = font->procs.encode_char(font, (gs_char)i,
+ GLYPH_SPACE_INDEX);
+ int mac_index = mac_glyph_index(font, i, &str);
+
+ if (mac_index != 0) {
+ post->glyphs[post->count].char_index = i;
+ post->glyphs[post->count].size =
+ (mac_index < 0 ? str.size + 1 : 0);
+ post->glyphs[post->count].glyph_index = glyph - gs_min_cid_glyph;
+ post->count++;
+ }
+ }
+ if (post->count) {
+ int j;
+
+ qsort(post->glyphs, post->count, sizeof(post->glyphs[0]),
+ compare_post_glyphs);
+ /* Eliminate duplicate references to the same glyph. */
+ for (i = j = 0; i < post->count; ++i) {
+ if (i == 0 ||
+ post->glyphs[i].glyph_index !=
+ post->glyphs[i - 1].glyph_index
+ ) {
+ post->length += post->glyphs[i].size;
+ post->glyphs[j++] = post->glyphs[i];
+ }
+ }
+ post->count = j;
+ post->glyph_count = post->glyphs[post->count - 1].glyph_index + 1;
+ }
+ post->length += post->glyph_count * 2;
+}
+
+/* Write the post table */
+private void
+write_post(stream *s, gs_font *font, post_t *post)
+{
+ byte post_initial[32 + 2];
+ uint name_index;
+ uint glyph_index;
+ int i;
+
+ memset(post_initial, 0, 32);
+ put_u32(post_initial, 0x00020000);
+ put_u16(post_initial + 32, post->glyph_count);
+ pwrite(s, post_initial, sizeof(post_initial));
+
+ /* Write the name index table. */
+
+ for (i = 0, name_index = 258, glyph_index = 0; i < post->count; ++i) {
+ gs_const_string str;
+ int ch = post->glyphs[i].char_index;
+ int mac_index = mac_glyph_index(font, ch, &str);
+
+ for (; glyph_index < post->glyphs[i].glyph_index; ++glyph_index)
+ put_ushort(s, 0);
+ glyph_index++;
+ if (mac_index >= 0)
+ put_ushort(s, mac_index);
+ else {
+ put_ushort(s, name_index);
+ name_index++;
+ }
+ }
+
+ /* Write the string names of the glyphs. */
+
+ for (i = 0; i < post->count; ++i) {
+ gs_const_string str;
+ int ch = post->glyphs[i].char_index;
+ int mac_index = mac_glyph_index(font, ch, &str);
+
+ if (mac_index < 0) {
+ spputc(s, str.size);
+ pwrite(s, str.data, str.size);
+ }
+ }
+ put_pad(s, post->length);
+}
+
+/* ---------------- Main program ---------------- */
+
+/* Write the definition of a TrueType font. */
+private int
+compare_table_tags(const void *pt1, const void *pt2)
+{
+ ulong t1 = u32(pt1), t2 = u32(pt2);
+
+ return (t1 < t2 ? -1 : t1 > t2 ? 1 : 0);
+}
+int
+psdf_write_truetype_font(stream *s, gs_font_type42 *pfont, int options,
+ gs_glyph *subset_glyphs, uint subset_size,
+ const gs_const_string *alt_font_name)
+{
+ gs_font *const font = (gs_font *)pfont;
+ gs_const_string font_name;
+ int (*string_proc)(P4(gs_font_type42 *, ulong, uint, const byte **)) =
+ pfont->data.string_proc;
+ const byte *OffsetTable;
+ uint numTables_stored, numTables, numTables_out;
+#define MAX_NUM_TABLES 40
+ byte tables[MAX_NUM_TABLES * 16];
+ uint i;
+ psdf_glyph_enum_t genum;
+ ulong offset;
+ gs_glyph glyph, glyph_prev;
+ ulong max_glyph;
+ uint glyf_length, glyf_checksum = 0 /****** BOGUS ******/;
+ uint loca_length, loca_checksum[2];
+ byte head[56]; /* 0 mod 4 */
+ post_t post;
+ ulong head_checksum, file_checksum = 0;
+ int indexToLocFormat;
+ bool have_cmap = false,
+ have_name = !(options & WRITE_TRUETYPE_NAME),
+ have_OS_2 = false,
+ have_post = false;
+ int code;
+
+ if (alt_font_name)
+ font_name = *alt_font_name;
+ else
+ font_name.data = font->font_name.chars,
+ font_name.size = font->font_name.size;
+
+ /* Sort the subset glyphs, if any. */
+
+ if (subset_glyphs)
+ subset_size = psdf_sort_glyphs(subset_glyphs, subset_size);
+
+ /*
+ * Count the number of tables, including the eventual glyf and loca
+ * (which may not actually be present in the font), and copy the
+ * table directory.
+ */
+
+ ACCESS(0, 12, OffsetTable);
+ numTables_stored = U16(OffsetTable + 4);
+ for (i = numTables = 0; i < numTables_stored; ++i) {
+ const byte *tab;
+
+ ACCESS(12 + i * 16, 16, tab);
+ if (!memcmp(tab, "head", 4)) {
+ const byte *head_data;
+ uint length = u32(tab + 12);
+
+ if (length != 54)
+ return_error(gs_error_invalidfont);
+ ACCESS(u32(tab + 8), length, head_data);
+ memcpy(head, head_data, length);
+ } else if (
+ !memcmp(tab, "gly", 3) /*glyf=synthesized, glyx=Adobe bogus*/ ||
+ !memcmp(tab, "loc", 3) /*loca=synthesized, locx=Adobe bogus*/ ||
+ !memcmp(tab, "gdir", 4) /*Adobe marker*/ ||
+ ((options & WRITE_TRUETYPE_CMAP) && !memcmp(tab, "cmap", 4))
+ )
+ DO_NOTHING;
+ else {
+ if (numTables == MAX_NUM_TABLES)
+ return_error(gs_error_limitcheck);
+ memcpy(&tables[numTables++ * 16], tab, 16);
+ if (!memcmp(tab, "cmap", 4))
+ have_cmap = true;
+ else if (!memcmp(tab, "name", 4))
+ have_name = true;
+ else if (!memcmp(tab, "OS/2", 4))
+ have_OS_2 = true;
+ else if (!memcmp(tab, "post", 4))
+ have_post = true;
+ }
+ }
+
+ /*
+ * Enumerate the glyphs to get the size of glyf and loca,
+ * and to compute the checksums for these tables.
+ */
+
+ /****** NO CHECKSUMS YET ******/
+ psdf_enumerate_glyphs_begin(&genum, font, subset_glyphs,
+ (subset_glyphs ? subset_size : 0),
+ GLYPH_SPACE_INDEX);
+ for (max_glyph = 0, glyf_length = 0;
+ (code = psdf_enumerate_glyphs_next(&genum, &glyph)) != 1;
+ ) {
+ gs_const_string glyph_string;
+ uint glyph_index;
+
+ if (glyph < gs_min_cid_glyph)
+ return_error(gs_error_invalidfont);
+ glyph_index = glyph - gs_min_cid_glyph;
+ if_debug1('L', "[L]glyph_index %u\n", glyph_index);
+ if (pfont->data.get_outline(pfont, glyph_index, &glyph_string) >= 0) {
+ max_glyph = max(max_glyph, glyph_index);
+ glyf_length += glyph_string.size;
+ if_debug1('L', "[L] size %u\n", glyph_string.size);
+ }
+ }
+ if_debug2('l', "[l]max_glyph = %lu, glyf_length = %lu\n",
+ (ulong)max_glyph, (ulong)glyf_length);
+ loca_length = (max_glyph + 2) << 2;
+ indexToLocFormat = (glyf_length > 0x1fffc);
+ if (!indexToLocFormat)
+ loca_length >>= 1;
+
+ /*
+ * If necessary, compute the length of the post table. Note that we
+ * only generate post entries for characters in the Encoding.
+ */
+
+ if (!have_post) {
+ memset(&post, 0, sizeof(post));
+ if (options & WRITE_TRUETYPE_POST)
+ compute_post(font, &post);
+ else
+ post.length = 32; /* dummy table */
+ }
+
+ /* Fix up the head table. */
+
+ memset(head + 8, 0, 4);
+ head[51] = (byte)indexToLocFormat;
+ memset(head + 54, 0, 2);
+ for (head_checksum = 0, i = 0; i < 56; i += 4)
+ head_checksum += u32(&head[i]);
+
+ /*
+ * Construct the table directory, except for glyf, loca, and head,
+ * and, if necessary, generated cmap, name, OS/2, and post tables.
+ * Note that the existing directory is already sorted by tag.
+ */
+
+ numTables_out = numTables + 3 +
+ !have_cmap + !have_name + !have_OS_2 + !have_post;
+ offset = 12 + numTables_out * 16;
+ for (i = 0; i < numTables; ++i) {
+ byte *tab = &tables[i * 16];
+ ulong length = u32(tab + 12);
+
+ offset += round_up(length, 4);
+ }
+
+ /* Make the table directory entries for generated tables. */
+
+ {
+ byte *tab = &tables[numTables * 16];
+
+ offset = put_table(tab, "glyf", glyf_checksum, offset, glyf_length);
+ tab += 16;
+
+ offset = put_table(tab, "loca", loca_checksum[indexToLocFormat],
+ offset, loca_length);
+ tab += 16;
+
+ if (!have_cmap) {
+ uint cmap_length = size_cmap(256);
+
+ offset = put_table(tab, "cmap", 0L /****** NO CHECKSUM ******/,
+ offset, cmap_length);
+ tab += 16;
+ }
+
+ if (!have_name) {
+ offset = put_table(tab, "name", 0L /****** NO CHECKSUM ******/,
+ offset, size_name(&font_name));
+ tab += 16;
+ }
+
+ if (!have_OS_2) {
+ offset = put_table(tab, "OS/2", 0L /****** NO CHECKSUM ******/,
+ offset, OS_2_LENGTH);
+ tab += 16;
+ }
+
+ if (!have_post) {
+ offset = put_table(tab, "post", 0L /****** NO CHECKSUM ******/,
+ offset, post.length);
+ tab += 16;
+ }
+
+ offset = put_table(tab, "head", head_checksum, offset, 56);
+ tab += 16;
+ }
+ numTables = numTables_out;
+
+ /* Write the font header. */
+
+ {
+ static const byte version[4] = {0, 1, 0, 0};
+
+ pwrite(s, version, 4);
+ }
+ put_ushort(s, numTables);
+ for (i = 0; 1 << i <= numTables; ++i)
+ DO_NOTHING;
+ --i;
+ put_ushort(s, 16 << i); /* searchRange */
+ put_ushort(s, i); /* entrySelectors */
+ put_ushort(s, numTables * 16 - (16 << i)); /* rangeShift */
+
+ /* Write the table directory. */
+
+ qsort(tables, numTables, 16, compare_table_tags);
+ offset = 12 + numTables * 16;
+ for (i = 0; i < numTables; ++i) {
+ const byte *tab = &tables[i * 16];
+ byte entry[16];
+
+ memcpy(entry, tab, 16);
+ if (entry[8] < 0x40) {
+ /* Not a generated table. */
+ uint length = u32(tab + 12);
+
+ put_u32(entry + 8, offset);
+ offset += round_up(length, 4);
+ } else {
+ entry[8] -= 0x40;
+ }
+ pwrite(s, entry, 16);
+ }
+
+ /* Write tables other than the ones we generate here. */
+
+ for (i = 0; i < numTables; ++i) {
+ const byte *tab = &tables[i * 16];
+
+ if (tab[8] < 0x40) {
+ uint length = u32(tab + 12);
+
+ write_range(s, pfont, u32(tab + 8), length);
+ put_pad(s, length);
+ }
+ }
+
+ /* Write glyf. */
+
+ psdf_enumerate_glyphs_begin(&genum, font, subset_glyphs,
+ (subset_glyphs ? subset_size : max_glyph + 1),
+ GLYPH_SPACE_INDEX);
+ for (offset = 0; psdf_enumerate_glyphs_next(&genum, &glyph) != 1; ) {
+ gs_const_string glyph_string;
+
+ if (pfont->data.get_outline(pfont, glyph, &glyph_string) >= 0) {
+ pwrite(s, glyph_string.data, glyph_string.size);
+ offset += glyph_string.size;
+ if_debug2('L', "[L]glyf index = %u, size = %u\n",
+ i, glyph_string.size);
+ }
+ }
+ if_debug1('l', "[l]glyf final offset = %lu\n", offset);
+ put_pad(s, (uint)offset);
+
+ /* Write loca. */
+
+ psdf_enumerate_glyphs_reset(&genum);
+ glyph_prev = gs_min_cid_glyph;
+ for (offset = 0; psdf_enumerate_glyphs_next(&genum, &glyph) != 1; ) {
+ gs_const_string glyph_string;
+
+ for (; glyph_prev <= glyph; ++glyph_prev)
+ put_loca(s, offset, indexToLocFormat);
+ if (pfont->data.get_outline(pfont, glyph, &glyph_string) >= 0)
+ offset += glyph_string.size;
+ }
+ /* Write the trailing loca entry. */
+ put_loca(s, offset, indexToLocFormat);
+ put_pad(s, loca_length);
+
+ /* If necessary, write cmap, name, and OS/2. */
+
+ if (!have_cmap)
+ write_cmap(s, font, 0xf000, 256, gs_min_cid_glyph + max_glyph);
+ if (!have_name)
+ write_name(s, &font_name);
+ if (!have_OS_2)
+ write_OS_2(s, font, 0xf000, 256);
+
+ /* If necessary, write post. */
+
+ if (!have_post) {
+ if (options & WRITE_TRUETYPE_POST)
+ write_post(s, font, &post);
+ else {
+ byte post_initial[32 + 2];
+
+ memset(post_initial, 0, 32);
+ put_u32(post_initial, 0x00030000);
+ pwrite(s, post_initial, 32);
+ }
+ }
+
+ /* Write head. */
+
+ /****** CHECKSUM WAS NEVER COMPUTED ******/
+ /*
+ * The following nonsense is to avoid warnings about the constant
+ * 0xb1b0afbaL being "unsigned in ANSI C, signed with -traditional".
+ */
+#if ARCH_SIZEOF_LONG > ARCH_SIZEOF_INT
+# define HEAD_MAGIC 0xb1b0afbaL
+#else
+# define HEAD_MAGIC ((ulong)~0x4e4f5045)
+#endif
+ put_u32(head + 8, HEAD_MAGIC - file_checksum); /* per spec */
+#undef HEAD_MAGIC
+ pwrite(s, head, 56);
+
+ return 0;
+}
diff --git a/gs/src/gdevpsim.c b/gs/src/gdevpsim.c
index e131425a1..4c4ea174d 100644
--- a/gs/src/gdevpsim.c
+++ b/gs/src/gdevpsim.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1994, 1995, 1996, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1994, 1995, 1996, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -134,7 +134,7 @@ psmono_print_page(gx_device_printer * pdev, FILE * prn_stream)
{
int line_size = gdev_mem_bytes_per_scan_line((gx_device *) pdev);
int lnum;
- byte *line = (byte *) gs_malloc(line_size, 1, "psmono_print_page");
+ byte *line = gs_alloc_bytes(pdev->memory, line_size, "psmono_print_page");
byte invert = (pdev->color_info.depth == 1 ? 0xff : 0);
if (line == 0)
@@ -206,7 +206,7 @@ psmono_print_page(gx_device_printer * pdev, FILE * prn_stream)
/* Clean up and return. */
fputs("\r\n", prn_stream);
- gs_free((char *)line, line_size, 1, "psmono_print_page");
+ gs_free_object(pdev->memory, line, "psmono_print_page");
return 0;
}
diff --git a/gs/src/gdevtfax.c b/gs/src/gdevtfax.c
index 5bb1e224c..6f38c0ac8 100644
--- a/gs/src/gdevtfax.c
+++ b/gs/src/gdevtfax.c
@@ -22,6 +22,7 @@
#include "gdevtifs.h" /* for TIFF output only */
#include "strimpl.h"
#include "scfx.h"
+#include "gdevtfax.h" /* prototypes */
/* Define the device parameters. */
#define X_DPI 204
@@ -204,12 +205,12 @@ gdev_fax_init_fax_state(stream_CFE_state * ss, const gx_device_printer * pdev)
/* Send the page to the printer. */
/* Print a page with a specified width, which may differ from the */
/* width stored in the device. */
-int
+private int
gdev_stream_print_page_width(gx_device_printer * pdev, FILE * prn_stream,
const stream_template * temp, stream_state * ss,
int width)
{
- gs_memory_t *mem = &gs_memory_default;
+ gs_memory_t *mem = pdev->memory;
int code;
stream_cursor_read r;
stream_cursor_write w;
@@ -300,7 +301,7 @@ gdev_stream_print_page_width(gx_device_printer * pdev, FILE * prn_stream,
(*temp->release) (ss);
return code;
}
-int
+private int
gdev_stream_print_page(gx_device_printer * pdev, FILE * prn_stream,
const stream_template * temp, stream_state * ss)
{
diff --git a/gs/src/t b/gs/src/gdevtfax.h
index aa5d7f1b4..f029f9d18 100644
--- a/gs/src/t
+++ b/gs/src/gdevtfax.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998, 1999 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -17,13 +17,13 @@
*/
-/* Type 1 / Type 2 character rendering operator entry */
+/* Entry points to the TIFF/fax writing driver */
-#ifndef ichar1_INCLUDED
-# define ichar1_INCLUDED
+#ifndef gdevtfax_INCLUDED
+# define gdevtfax_INCLUDED
-/* Render a Type 1 or Type 2 outline. */
-/* This is the entire implementation of the .type1/2execchar operators. */
-int charstring_execchar(P2(op_args_t *op_args_p, int font_type_mask));
+int gdev_fax_open(P1(gx_device *));
+void gdev_fax_init_state(P2(stream_CFE_state *, const gx_device_printer *));
+int gdev_fax_print_page(P3(gx_device_printer *, FILE *, stream_CFE_state *));
-#endif /* ichar1_INCLUDED */
+#endif /* gdevtfax_INCLUDED */
diff --git a/gs/src/gdevtfnx.c b/gs/src/gdevtfnx.c
index 718e834b6..ee61dd30b 100644
--- a/gs/src/gdevtfnx.c
+++ b/gs/src/gdevtfnx.c
@@ -120,7 +120,7 @@ tiff12_print_page(gx_device_printer * pdev, FILE * file)
{
int y;
int raster = gdev_prn_raster(pdev);
- byte *line = (byte *) gs_malloc(raster, 1, "tiff12_print_page");
+ byte *line = gs_alloc_bytes(pdev->memory, raster, "tiff12_print_page");
byte *row;
if (line == 0)
@@ -146,7 +146,7 @@ tiff12_print_page(gx_device_printer * pdev, FILE * file)
}
gdev_tiff_end_page(&tfdev->tiff, file);
- gs_free(line, raster, 1, "tiff12_print_page");
+ gs_free_object(pdev->memory, line, "tiff12_print_page");
}
return code;
@@ -170,7 +170,7 @@ tiff24_print_page(gx_device_printer * pdev, FILE * file)
{
int y;
int raster = gdev_prn_raster(pdev);
- byte *line = (byte *) gs_malloc(raster, 1, "tiff24_print_page");
+ byte *line = gs_alloc_bytes(pdev->memory, raster, "tiff24_print_page");
byte *row;
if (line == 0)
@@ -182,7 +182,7 @@ tiff24_print_page(gx_device_printer * pdev, FILE * file)
fwrite((char *)row, raster, 1, file);
}
gdev_tiff_end_page(&tfdev->tiff, file);
- gs_free(line, raster, 1, "tiff24_print_page");
+ gs_free_object(pdev->memory, line, "tiff24_print_page");
}
return code;
diff --git a/gs/src/gdevupd.c b/gs/src/gdevupd.c
index 82236ca86..05498e34d 100644
--- a/gs/src/gdevupd.c
+++ b/gs/src/gdevupd.c
@@ -16,7 +16,7 @@
all copies.
*/
-
+/* gdevupd.c $Revision$ */
/* "uniprint" -- Ugly Printer Driver by Gunther Hess (gunther@elmos.de) */
/* Revision-History:
@@ -881,7 +881,7 @@ Here are several Macros, named "UPD_MM_*" to deal with that.
/** Version-String */
-
+static const char rcsid[] = "$Revision$";
/** Default-Transfer-curve */
@@ -1341,7 +1341,6 @@ upd_get_params(gx_device *pdev, gs_param_list *plist)
/** Export the version */
if(upd_version) { /* Version-Export enabled */
- const byte *rcsid = "1.0";
udev->upd_version.data = (const byte *) rcsid;
udev->upd_version.size = strlen(rcsid);
udev->upd_version.persistent = true;
@@ -2398,7 +2397,8 @@ upd_expand(upd_pc upd,int i,uint32 ci)
/* ------------------------------------------------------------------- */
private uint32
-upd_truncate(upd_pc upd,int i,gx_color_value v) {
+upd_truncate(upd_pc upd,int i,gx_color_value v)
+{
const updcmap_pc cmap = upd->cmap + i;
int32 s; /* step size */
gx_color_value *p; /* value-pointer */
diff --git a/gs/src/gdevvec.c b/gs/src/gdevvec.c
index c6f398527..20811f824 100644
--- a/gs/src/gdevvec.c
+++ b/gs/src/gdevvec.c
@@ -866,6 +866,10 @@ gdev_vector_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
if (code < 0)
return code;
+ /* Make sure we aren't being clipped. */
+ code = gdev_vector_update_clip_path(vdev, NULL);
+ if (code < 0)
+ return code;
}
if (vdev->bbox_device) {
int code = (*dev_proc(vdev->bbox_device, fill_rectangle))
@@ -952,6 +956,10 @@ gdev_vector_fill_trapezoid(gx_device * dev, const gs_fixed_edge * left,
if (code < 0)
return gx_default_fill_trapezoid(dev, left, right, ybot, ytop,
swap_axes, pdevc, lop);
+ /* Make sure we aren't being clipped. */
+ code = gdev_vector_update_clip_path(vdev, NULL);
+ if (code < 0)
+ return code;
if (swap_axes)
points[0].y = x0l, points[1].y = x0r,
points[0].x = points[1].x = y0,
@@ -988,6 +996,10 @@ gdev_vector_fill_parallelogram(gx_device * dev,
if (code < 0)
return gx_default_fill_parallelogram(dev, px, py, ax, ay, bx, by,
pdevc, lop);
+ /* Make sure we aren't being clipped. */
+ code = gdev_vector_update_clip_path(vdev, NULL);
+ if (code < 0)
+ return code;
if (vdev->bbox_device) {
code = (*dev_proc(vdev->bbox_device, fill_parallelogram))
((gx_device *) vdev->bbox_device, px, py, ax, ay, bx, by,
@@ -1014,6 +1026,10 @@ gdev_vector_fill_triangle(gx_device * dev,
if (code < 0)
return gx_default_fill_triangle(dev, px, py, ax, ay, bx, by,
pdevc, lop);
+ /* Make sure we aren't being clipped. */
+ code = gdev_vector_update_clip_path(vdev, NULL);
+ if (code < 0)
+ return code;
if (vdev->bbox_device) {
code = (*dev_proc(vdev->bbox_device, fill_triangle))
((gx_device *) vdev->bbox_device, px, py, ax, ay, bx, by,
diff --git a/gs/src/gdevwpr2.c b/gs/src/gdevwpr2.c
index aa25dae4a..e7fdeaa2a 100644
--- a/gs/src/gdevwpr2.c
+++ b/gs/src/gdevwpr2.c
@@ -538,7 +538,6 @@ win_pr2_print_page(gx_device_printer * pdev, FILE * file)
ShowWindow(hDlgModeless, SW_HIDE);
}
- bmp_done:
GlobalUnlock(hrow);
GlobalFree(hrow);
diff --git a/gs/src/gdevx.c b/gs/src/gdevx.c
index e97af25b9..6a0bfdecf 100644
--- a/gs/src/gdevx.c
+++ b/gs/src/gdevx.c
@@ -18,9 +18,6 @@
/* X Windows driver for Ghostscript library */
-/* The X include files include <sys/types.h>, which, on some machines */
-/* at least, define uint, ushort, and ulong, which std.h also defines. */
-/* std.h has taken care of this. */
#include "gx.h" /* for gx_bitmap; includes std.h */
#include "math_.h"
#include "memory_.h"
@@ -35,117 +32,105 @@
#include "gxgetbit.h"
#include "gxiparam.h"
#include "gsiparm2.h"
+#include "gxdevmem.h"
#include "gdevx.h"
-/* Define whether to update after every write, for debugging. */
-bool X_ALWAYS_UPDATE = false;
-
-/* Define the maximum size of the temporary pixmap for copy_mono */
-/* that we are willing to leave lying around in the server */
-/* between uses. (Assume 32-bit ints here!) */
-private int X_MAX_TEMP_PIXMAP = 20000;
-
-/* Define the maximum size of the temporary image created in memory */
-/* for get_bits_rectangle. */
-private int X_MAX_TEMP_IMAGE = 5000;
-
/* Define whether to try to read back exposure events after XGetImage. */
/****** THIS IS USELESS. XGetImage DOES NOT GENERATE EXPOSURE EVENTS. ******/
#define GET_IMAGE_EXPOSURES 0
+/* GC descriptors */
+private_st_device_X();
+
/* Forward references */
+private int x_copy_image(P8(gx_device_X * xdev, const byte * base, int sourcex,
+ int raster, int x, int y, int w, int h));
private int set_tile(P2(gx_device *, const gx_strip_bitmap *));
private void free_cp(P1(gx_device *));
-private void x_send_event(P2(gx_device *, Atom));
/* Screen updating machinery */
-#define update_init(dev)\
- ((gx_device_X *)(dev))->up_area = 0,\
- ((gx_device_X *)(dev))->up_count = 0
-#define update_flush(dev)\
- if ( ((gx_device_X *)(dev))->up_area != 0 ) update_do_flush(dev)
-private void update_do_flush(P1(gx_device *));
-
-#define flush_text(dev)\
- if ( IN_TEXT((gx_device_X *)(dev)) ) do_flush_text(dev)
-private void do_flush_text(P1(gx_device *));
+private void update_init(P1(gx_device_X *));
+private void update_do_flush(P1(gx_device_X *));
-/* Procedures */
+#define flush_text(xdev)\
+ if (IN_TEXT(xdev)) do_flush_text(xdev)
+private void do_flush_text(P1(gx_device_X *));
-extern int gdev_x_open(P1(gx_device_X *));
+/* Driver procedures */
+/* (External procedures are declared in gdevx.h.) */
+/*extern int gdev_x_open(P1(gx_device_X *));*/
private dev_proc_open_device(x_open);
private dev_proc_get_initial_matrix(x_get_initial_matrix);
private dev_proc_sync_output(x_sync);
private dev_proc_output_page(x_output_page);
-extern void gdev_x_free_dynamic_colors(P1(gx_device_X *));
-extern void gdev_x_free_colors(P1(gx_device_X *));
+/*extern int gdev_x_close(P1(gx_device_X *));*/
private dev_proc_close_device(x_close);
-extern dev_proc_map_rgb_color(gdev_x_map_rgb_color);
-extern dev_proc_map_color_rgb(gdev_x_map_color_rgb);
+/*extern dev_proc_map_rgb_color(gdev_x_map_rgb_color);*/
+/*extern dev_proc_map_color_rgb(gdev_x_map_color_rgb);*/
private dev_proc_fill_rectangle(x_fill_rectangle);
private dev_proc_copy_mono(x_copy_mono);
private dev_proc_copy_color(x_copy_color);
-private dev_proc_get_params(x_get_params);
-private dev_proc_put_params(x_put_params);
-dev_proc_get_xfont_procs(x_get_xfont_procs);
+/*extern dev_proc_get_params(gdev_x_get_params);*/
+/*extern dev_proc_put_params(gdev_x_put_params);*/
+/*extern dev_proc_get_xfont_procs(gdev_x_get_xfont_procs);*/
private dev_proc_get_page_device(x_get_page_device);
private dev_proc_strip_tile_rectangle(x_strip_tile_rectangle);
private dev_proc_begin_typed_image(x_begin_typed_image);
private dev_proc_get_bits_rectangle(x_get_bits_rectangle);
/* The device descriptor */
-private const gx_device_procs x_procs =
-{
- x_open,
- x_get_initial_matrix,
- x_sync,
- x_output_page,
- x_close,
- gdev_x_map_rgb_color,
- gdev_x_map_color_rgb,
- x_fill_rectangle,
- NULL, /* tile_rectangle */
- x_copy_mono,
- x_copy_color,
- NULL, /* draw_line */
- NULL, /* get_bits */
- x_get_params,
- x_put_params,
- NULL, /* map_cmyk_color */
- x_get_xfont_procs,
- NULL, /* get_xfont_device */
- NULL, /* map_rgb_alpha_color */
- x_get_page_device,
- NULL, /* get_alpha_bits */
- NULL, /* copy_alpha */
- NULL, /* get_band */
- NULL, /* copy_rop */
- NULL, /* fill_path */
- NULL, /* stroke_path */
- NULL, /* fill_mask */
- NULL, /* fill_trapezoid */
- NULL, /* fill_parallelogram */
- NULL, /* fill_triangle */
- NULL, /* draw_thin_line */
- NULL, /* begin_image */
- NULL, /* image_data */
- NULL, /* end_image */
- x_strip_tile_rectangle,
- NULL, /* strip_copy_rop */
- NULL, /* get_clipping_box */
- x_begin_typed_image,
- x_get_bits_rectangle
-};
-
-/* The instance is public. */
-const gx_device_X gs_x11_device =
-{
- std_device_color_body(gx_device_X, &x_procs, "x11",
- FAKE_RES * DEFAULT_WIDTH_10THS / 10, FAKE_RES * DEFAULT_HEIGHT_10THS / 10, /* x and y extent (nominal) */
+const gx_device_X gs_x11_device = {
+ std_device_color_stype_body(gx_device_X, 0, "x11", &st_device_X,
+ FAKE_RES * DEFAULT_WIDTH_10THS / 10,
+ FAKE_RES * DEFAULT_HEIGHT_10THS / 10, /* x and y extent (nominal) */
FAKE_RES, FAKE_RES, /* x and y density (nominal) */
/*dci_color( */ 24, 255, 256 /*) */ ),
- {0}, /* std_procs */
- 1 /*true */ , /* IsPageDevice */
+ { /* std_procs */
+ x_open,
+ x_get_initial_matrix,
+ x_sync,
+ x_output_page,
+ x_close,
+ gdev_x_map_rgb_color,
+ gdev_x_map_color_rgb,
+ x_fill_rectangle,
+ NULL, /* tile_rectangle */
+ x_copy_mono,
+ x_copy_color,
+ NULL, /* draw_line */
+ NULL, /* get_bits */
+ gdev_x_get_params,
+ gdev_x_put_params,
+ NULL, /* map_cmyk_color */
+ gdev_x_get_xfont_procs,
+ NULL, /* get_xfont_device */
+ NULL, /* map_rgb_alpha_color */
+ x_get_page_device,
+ NULL, /* get_alpha_bits */
+ NULL, /* copy_alpha */
+ NULL, /* get_band */
+ NULL, /* copy_rop */
+ NULL, /* fill_path */
+ NULL, /* stroke_path */
+ NULL, /* fill_mask */
+ NULL, /* fill_trapezoid */
+ NULL, /* fill_parallelogram */
+ NULL, /* fill_triangle */
+ NULL, /* draw_thin_line */
+ NULL, /* begin_image */
+ NULL, /* image_data */
+ NULL, /* end_image */
+ x_strip_tile_rectangle,
+ NULL, /* strip_copy_rop */
+ NULL, /* get_clipping_box */
+ x_begin_typed_image,
+ x_get_bits_rectangle
+ },
+ gx_device_bbox_common_initial(0 /*false*/, 1 /*true*/, 1 /*true*/),
+ 1 /*true*/, /* IsPageDevice */
+ 0, /* MaxBitmap */
+ NULL, /* buffer */
+ 0, /* buffer_size */
{ /* image */
0, 0, /* width, height */
0, XYBitmap, NULL, /* xoffset, format, data */
@@ -174,9 +159,17 @@ const gx_device_X gs_x11_device =
(Window) None, /* mwin */
{identity_matrix_body}, /* initial matrix (filled in) */
(Atom) 0, (Atom) 0, (Atom) 0, /* Atoms: NEXT, PAGE, DONE */
- {0, 0, 0, 0}, 0, 0, /* update, up_area, up_count */
+ { /* update */
+ { /* box */
+ {max_int_in_fixed, max_int_in_fixed},
+ {min_int_in_fixed, min_int_in_fixed}
+ },
+ 0, /* area */
+ 0, /* total */
+ 0 /* count */
+ },
(Pixmap) 0, /* dest */
- 0L, (ulong) ~ 0L, /* colors_or, colors_and */
+ 0L, (ulong)~0L, /* colors_or, colors_and */
{ /* cp */
(Pixmap) 0, /* pixmap */
NULL, /* gc */
@@ -206,6 +199,14 @@ const gx_device_X gs_x11_device =
0.0, 0.0, /* xResolution, yResolution */
1, /* useBackingPixmap */
1, 1, /* useXPutImage, useXSetTile */
+
+ 0 /*false*/, /* AlwaysUpdate */
+ 20000, /* MaxTempPixmap */
+ 5000, /* MaxTempImage */
+ 100000, /* MaxBufferedTotal */
+ 100000, /* MaxBufferedArea */
+ max_int, /* MaxBufferedCount */
+
{ /* text */
0, /* item_count */
0, /* char_count */
@@ -242,56 +243,24 @@ x_open(gx_device * dev)
if (code < 0)
return code;
- update_init(dev);
+ update_init(xdev);
return 0;
}
-/* Free fonts when closing the device. */
-private void
-free_x_fontmaps(x11fontmap **pmaps)
-{
- while (*pmaps) {
- x11fontmap *font = *pmaps;
-
- *pmaps = font->next;
- if (font->std.names)
- XFreeFontNames(font->std.names);
- if (font->iso.names)
- XFreeFontNames(font->iso.names);
- gs_free(font->x11_name, sizeof(char), strlen(font->x11_name) + 1,
- "x11_font_x11name");
- gs_free(font->ps_name, sizeof(char), strlen(font->ps_name) + 1,
- "x11_font_psname");
-
- gs_free(font, sizeof(x11fontmap), 1, "x11_fontmap");
- }
-}
-
/* Close the device. */
private int
x_close(gx_device * dev)
{
gx_device_X *xdev = (gx_device_X *) dev;
- if (xdev->ghostview)
- x_send_event(dev, xdev->DONE);
- if (xdev->vinfo) {
- XFree((char *)xdev->vinfo);
- xdev->vinfo = NULL;
- }
- gdev_x_free_colors(xdev);
- free_x_fontmaps(&xdev->dingbat_fonts);
- free_x_fontmaps(&xdev->symbol_fonts);
- free_x_fontmaps(&xdev->regular_fonts);
- XCloseDisplay(xdev->dpy);
- return 0;
+ return gdev_x_close(xdev);
}
/* Get initial matrix for X device. */
/* This conflicts seriously with the code for page devices; */
/* we only do it if Ghostview is active. */
private void
-x_get_initial_matrix(register gx_device * dev, register gs_matrix * pmat)
+x_get_initial_matrix(gx_device * dev, gs_matrix * pmat)
{
gx_device_X *xdev = (gx_device_X *) dev;
@@ -307,23 +276,21 @@ x_get_initial_matrix(register gx_device * dev, register gs_matrix * pmat)
pmat->ty = xdev->initial_matrix.ty;
}
-/* Synchronize the display with the commands already given */
+/* Synchronize the display with the commands already given. */
private int
-x_sync(register gx_device * dev)
+x_sync(gx_device * dev)
{
gx_device_X *xdev = (gx_device_X *) dev;
- flush_text(dev);
- update_flush(dev);
+ update_do_flush(xdev);
XFlush(xdev->dpy);
return 0;
}
/* Send event to ghostview process */
-private void
-x_send_event(gx_device * dev, Atom msg)
+void
+gdev_x_send_event(gx_device_X *xdev, Atom msg)
{
- gx_device_X *xdev = (gx_device_X *) dev;
XEvent event;
event.xclient.type = ClientMessage;
@@ -349,7 +316,7 @@ x_output_page(gx_device * dev, int num_copies, int flush)
if (xdev->ghostview) {
XEvent event;
- x_send_event(dev, xdev->PAGE);
+ gdev_x_send_event(xdev, xdev->PAGE);
XNextEvent(xdev->dpy, &event);
while (event.type != ClientMessage ||
event.xclient.message_type != xdev->NEXT) {
@@ -361,16 +328,16 @@ x_output_page(gx_device * dev, int num_copies, int flush)
/* Fill a rectangle with a color. */
private int
-x_fill_rectangle(register gx_device * dev,
+x_fill_rectangle(gx_device * dev,
int x, int y, int w, int h, gx_color_index color)
{
gx_device_X *xdev = (gx_device_X *) dev;
fit_fill(dev, x, y, w, h);
- flush_text(dev);
- set_fill_style(FillSolid);
- set_fore_color(color);
- set_function(GXcopy);
+ flush_text(xdev);
+ X_SET_FILL_STYLE(xdev, FillSolid);
+ X_SET_FORE_COLOR(xdev, color);
+ X_SET_FUNCTION(xdev, GXcopy);
XFillRectangle(xdev->dpy, xdev->dest, xdev->gc, x, y, w, h);
/* If we are filling the entire screen, reset */
/* colors_or and colors_and. It's wasteful to test this */
@@ -382,7 +349,7 @@ x_fill_rectangle(register gx_device * dev,
xdev->colors_or = xdev->colors_and = color;
}
if (xdev->bpixmap != (Pixmap) 0) {
- x_update_add(dev, x, y, w, h);
+ x_update_add(xdev, x, y, w, h);
}
if_debug5('F', "[F] fill (%d,%d):(%d,%d) %ld\n",
x, y, w, h, (long)color);
@@ -391,7 +358,7 @@ x_fill_rectangle(register gx_device * dev,
/* Copy a monochrome bitmap. */
private int
-x_copy_mono(register gx_device * dev,
+x_copy_mono(gx_device * dev,
const byte * base, int sourcex, int raster, gx_bitmap_id id,
int x, int y, int w, int h,
gx_color_index zero, gx_color_index one)
@@ -425,13 +392,13 @@ x_copy_mono(register gx_device * dev,
fc = one;
fit_copy(dev, base, sourcex, raster, id, x, y, w, h);
- flush_text(dev);
+ flush_text(xdev);
xdev->image.width = sourcex + w;
xdev->image.height = h;
xdev->image.data = (char *)base;
xdev->image.bytes_per_line = raster;
- set_fill_style(FillSolid);
+ X_SET_FILL_STYLE(xdev, FillSolid);
/* Check for null, easy 1-color, hard 1-color, and 2-color cases. */
if (zero != gx_no_color_index) {
@@ -461,7 +428,7 @@ x_copy_mono(register gx_device * dev,
}
}
xdev->image.format = XYBitmap;
- set_function(function);
+ X_SET_FUNCTION(xdev, function);
if (bc != xdev->back_color) {
XSetBackground(xdev->dpy, xdev->gc, (xdev->back_color = bc));
}
@@ -469,9 +436,9 @@ x_copy_mono(register gx_device * dev,
XSetForeground(xdev->dpy, xdev->gc, (xdev->fore_color = fc));
}
if (zero != gx_no_color_index)
- note_color(zero);
+ NOTE_COLOR(xdev, zero);
if (one != gx_no_color_index)
- note_color(one);
+ NOTE_COLOR(xdev, one);
put_image(xdev->dpy, xdev->dest, xdev->gc, &xdev->image,
sourcex, 0, x, y, w, h);
@@ -500,17 +467,17 @@ x_copy_mono(register gx_device * dev,
}
/* Initialize static mask image params */
xdev->image.format = XYBitmap;
- set_function(GXcopy);
+ X_SET_FUNCTION(xdev, GXcopy);
/* Select polarity based on fg/bg transparency. */
if (one == gx_no_color_index) { /* invert */
XSetBackground(xdev->dpy, xdev->cp.gc, (x_pixel) 1);
XSetForeground(xdev->dpy, xdev->cp.gc, (x_pixel) 0);
- set_fore_color(zero);
+ X_SET_FORE_COLOR(xdev, zero);
} else {
XSetBackground(xdev->dpy, xdev->cp.gc, (x_pixel) 0);
XSetForeground(xdev->dpy, xdev->cp.gc, (x_pixel) 1);
- set_fore_color(one);
+ X_SET_FORE_COLOR(xdev, one);
}
put_image(xdev->dpy, xdev->cp.pixmap, xdev->cp.gc,
&xdev->image, sourcex, 0, 0, 0, w, h);
@@ -527,19 +494,19 @@ x_copy_mono(register gx_device * dev,
/* Tidy up. Free the pixmap if it's big. */
XSetClipMask(xdev->dpy, xdev->gc, None);
- if (raster * h > X_MAX_TEMP_PIXMAP)
+ if (raster * h > xdev->MaxTempPixmap)
free_cp(dev);
out:if (xdev->bpixmap != (Pixmap) 0) {
/* We wrote to the pixmap, so update the display now. */
- x_update_add(dev, x, y, w, h);
+ x_update_add(xdev, x, y, w, h);
}
return 0;
}
/* Internal routine to free the GC and pixmap used for copying. */
private void
-free_cp(register gx_device * dev)
+free_cp(gx_device * dev)
{
gx_device_X *xdev = (gx_device_X *) dev;
@@ -556,17 +523,13 @@ free_cp(register gx_device * dev)
/* Copy a color bitmap. */
private int
-x_copy_color(register gx_device * dev,
- const byte * base, int sourcex, int raster, gx_bitmap_id id,
+x_copy_image(gx_device_X * xdev, const byte * base, int sourcex, int raster,
int x, int y, int w, int h)
{
- gx_device_X *xdev = (gx_device_X *) dev;
- int depth = dev->color_info.depth;
+ int depth = xdev->color_info.depth;
- fit_copy(dev, base, sourcex, raster, id, x, y, w, h);
- flush_text(dev);
- set_fill_style(FillSolid);
- set_function(GXcopy);
+ X_SET_FILL_STYLE(xdev, FillSolid);
+ X_SET_FUNCTION(xdev, GXcopy);
/* Filling with a colored halftone often gives rise to */
/* copy_color calls for a single pixel. Check for this now. */
@@ -583,7 +546,7 @@ x_copy_color(register gx_device * dev,
while ((depth -= 8) > 0)
pixel = (pixel << 8) + *ptr++;
}
- set_fore_color(pixel);
+ X_SET_FORE_COLOR(xdev, pixel);
XDrawPoint(xdev->dpy, xdev->dest, xdev->gc, x, y);
} else {
xdev->image.width = sourcex + w;
@@ -599,128 +562,26 @@ x_copy_color(register gx_device * dev,
sourcex, 0, x, y, w, h);
xdev->image.depth = xdev->image.bits_per_pixel = 1;
}
- if (xdev->bpixmap != (Pixmap) 0)
- x_update_add(dev, x, y, w, h);
- if_debug4('F', "[F] copy_color (%d,%d):(%d,%d)\n",
- x, y, w, h);
return 0;
}
-
-/* Get the device parameters. See below. */
private int
-x_get_params(gx_device * dev, gs_param_list * plist)
+x_copy_color(gx_device * dev,
+ const byte * base, int sourcex, int raster, gx_bitmap_id id,
+ int x, int y, int w, int h)
{
gx_device_X *xdev = (gx_device_X *) dev;
- int code = gx_default_get_params(dev, plist);
- long id = (long)xdev->pwin;
+ int code;
- if (code < 0 ||
- (code = param_write_long(plist, "WindowID", &id)) < 0 ||
- (code = param_write_bool(plist, ".IsPageDevice", &xdev->IsPageDevice)) < 0
- )
- DO_NOTHING;
+ fit_copy(dev, base, sourcex, raster, id, x, y, w, h);
+ flush_text(xdev);
+ code = x_copy_image(xdev, base, sourcex, raster, x, y, w, h);
+ if (xdev->bpixmap != (Pixmap) 0)
+ x_update_add(xdev, x, y, w, h);
+ if_debug4('F', "[F] copy_color (%d,%d):(%d,%d)\n",
+ x, y, w, h);
return code;
}
-/* Set the device parameters. We reimplement this so we can resize */
-/* the window and avoid closing and reopening the device, and to add */
-/* .IsPageDevice. */
-private int
-x_put_params(gx_device * dev, gs_param_list * plist)
-{
- gx_device_X *xdev = (gx_device_X *) dev;
- bool is_open = dev->is_open;
- int width = dev->width;
- int height = dev->height;
- float xres = dev->HWResolution[0];
- float yres = dev->HWResolution[1];
- long pwin = (long)xdev->pwin;
- bool is_page = xdev->IsPageDevice;
- bool save_is_page = xdev->IsPageDevice;
- int ecode = 0, code;
-
- /* Handle extra parameters */
- switch (code = param_read_long(plist, "WindowID", &pwin)) {
- case 0:
- case 1:
- break;
- default:
- ecode = code;
- param_signal_error(plist, "GSVIEW", ecode);
- }
-
- switch (code = param_read_bool(plist, ".IsPageDevice", &is_page)) {
- case 0:
- case 1:
- break;
- default:
- ecode = code;
- param_signal_error(plist, "GSVIEW", ecode);
- }
-
- if (ecode < 0)
- return ecode;
-
- /* Unless we specified a new window ID, */
- /* prevent gx_default_put_params from closing the device. */
- if (pwin == (long)xdev->pwin)
- dev->is_open = false;
- xdev->IsPageDevice = is_page;
- code = gx_default_put_params(dev, plist);
- dev->is_open = is_open;
- if (code < 0) { /* Undo setting of .IsPageDevice */
- xdev->IsPageDevice = save_is_page;
- return code;
- }
- if (pwin != (long)xdev->pwin) {
- if (xdev->is_open)
- gs_closedevice(dev);
- xdev->pwin = (Window) pwin;
- }
- /* If the device is open, resize the window. */
- /* Don't do this if Ghostview is active. */
- if (xdev->is_open && !xdev->ghostview &&
- (dev->width != width || dev->height != height ||
- dev->HWResolution[0] != xres || dev->HWResolution[1] != yres)
- ) {
- int dw = dev->width - width;
- int dh = dev->height - height;
- double qx = dev->HWResolution[0] / xres;
- double qy = dev->HWResolution[1] / xres;
-
- if (dw != 0 || dh != 0) {
- XResizeWindow(xdev->dpy, xdev->win,
- dev->width, dev->height);
- if (xdev->bpixmap != (Pixmap) 0) {
- XFreePixmap(xdev->dpy, xdev->bpixmap);
- xdev->bpixmap = (Pixmap) 0;
- }
- xdev->dest = 0;
- gdev_x_clear_window(xdev);
- }
- /* Attempt to update the initial matrix in a sensible way. */
- /* The whole handling of the initial matrix is a hack! */
- if (xdev->initial_matrix.xy == 0) {
- if (xdev->initial_matrix.xx < 0) { /* 180 degree rotation */
- xdev->initial_matrix.tx += dw;
- } else { /* no rotation */
- xdev->initial_matrix.ty += dh;
- }
- } else {
- if (xdev->initial_matrix.xy < 0) { /* 90 degree rotation */
- xdev->initial_matrix.tx += dh;
- xdev->initial_matrix.ty += dw;
- } else { /* 270 degree rotation */
- }
- }
- xdev->initial_matrix.xx *= qx;
- xdev->initial_matrix.xy *= qx;
- xdev->initial_matrix.yx *= qy;
- xdev->initial_matrix.yy *= qy;
- }
- return 0;
-}
-
/* Get the page device. We reimplement this so that we can make this */
/* device be a page device conditionally. */
private gx_device *
@@ -731,7 +592,7 @@ x_get_page_device(gx_device * dev)
/* Tile a rectangle. */
private int
-x_strip_tile_rectangle(register gx_device * dev, const gx_strip_bitmap * tiles,
+x_strip_tile_rectangle(gx_device * dev, const gx_strip_bitmap * tiles,
int x, int y, int w, int h,
gx_color_index zero, gx_color_index one,
int px, int py)
@@ -751,7 +612,7 @@ x_strip_tile_rectangle(register gx_device * dev, const gx_strip_bitmap * tiles,
zero, one, px, py);
fit_fill(dev, x, y, w, h);
- flush_text(dev);
+ flush_text(xdev);
/* Imaging with a halftone often gives rise to very small */
/* tile_rectangle calls. Check for this now. */
@@ -759,8 +620,8 @@ x_strip_tile_rectangle(register gx_device * dev, const gx_strip_bitmap * tiles,
if (h <= 2 && w <= 2) {
int j;
- set_fill_style(FillSolid);
- set_function(GXcopy);
+ X_SET_FILL_STYLE(xdev, FillSolid);
+ X_SET_FUNCTION(xdev, GXcopy);
for (j = y + h; --j >= y;) {
const byte *ptr =
tiles->data + (j % tiles->rep_height) * tiles->raster;
@@ -771,12 +632,12 @@ x_strip_tile_rectangle(register gx_device * dev, const gx_strip_bitmap * tiles,
byte mask = 0x80 >> (tx & 7);
x_pixel pixel = (ptr[tx >> 3] & mask ? one : zero);
- set_fore_color(pixel);
+ X_SET_FORE_COLOR(xdev, pixel);
XDrawPoint(xdev->dpy, xdev->dest, xdev->gc, i, j);
}
}
if (xdev->bpixmap != (Pixmap) 0) {
- x_update_add(dev, x, y, w, h);
+ x_update_add(xdev, x, y, w, h);
}
return 0;
}
@@ -791,18 +652,18 @@ x_strip_tile_rectangle(register gx_device * dev, const gx_strip_bitmap * tiles,
if ((zero != xdev->ht.back_c) || (one != xdev->ht.fore_c))
xdev->ht.id = ~tiles->id; /* force reload */
- set_back_color(zero);
- set_fore_color(one);
+ X_SET_BACK_COLOR(xdev, zero);
+ X_SET_FORE_COLOR(xdev, one);
if (!set_tile(dev, tiles)) { /* Bad news. Fall back to the default algorithm. */
return gx_default_strip_tile_rectangle(dev, tiles, x, y, w, h,
zero, one, px, py);
}
/* Use the tile to fill the rectangle */
- set_fill_style(FillTiled);
- set_function(GXcopy);
+ X_SET_FILL_STYLE(xdev, FillTiled);
+ X_SET_FUNCTION(xdev, GXcopy);
XFillRectangle(xdev->dpy, xdev->dest, xdev->gc, x, y, w, h);
if (xdev->bpixmap != (Pixmap) 0) {
- x_update_add(dev, x, y, w, h);
+ x_update_add(xdev, x, y, w, h);
}
if_debug6('F', "[F] tile (%d,%d):(%d,%d) %ld,%ld\n",
x, y, w, h, (long)zero, (long)one);
@@ -837,7 +698,7 @@ x_begin_typed_image(gx_device * dev,
sizeof(dev->color_info))
)
goto punt;
- flush_text(dev);
+ flush_text(xdev);
gs_currentmatrix(pgs, &smat);
/*
* Figure 7.2 of the Adobe 3010 Supplement says that we should
@@ -873,15 +734,15 @@ x_begin_typed_image(gx_device * dev,
rect.q.y += (rect.p.y = pim->YOrigin);
gs_bbox_transform(&rect, &smat, &src);
(*pic->type->source_size) (pis, pic, &size);
- set_fill_style(FillSolid);
- set_function(GXcopy);
+ X_SET_FILL_STYLE(xdev, FillSolid);
+ X_SET_FUNCTION(xdev, GXcopy);
srcx = (int)(src.p.x + 0.5);
srcy = (int)(src.p.y + 0.5);
destx = (int)(dest.p.x + 0.5);
desty = (int)(dest.p.y + 0.5);
XCopyArea(xdev->dpy, xdev->bpixmap, xdev->bpixmap, xdev->gc,
srcx, srcy, size.x, size.y, destx, desty);
- x_update_add(dev, destx, desty, size.x, size.y);
+ x_update_add(xdev, destx, desty, size.x, size.y);
}
return 0;
punt:return gx_default_begin_typed_image(dev, pis, pmat, pic, prect,
@@ -897,7 +758,7 @@ x_get_bits_rectangle(gx_device * dev, const gs_int_rect * prect,
int depth = dev->color_info.depth;
int x0 = prect->p.x, y0 = prect->p.y, x1 = prect->q.x, y1 = prect->q.y;
uint width_bytes = ((x1 - x0) * depth + 7) >> 3;
- uint band = X_MAX_TEMP_IMAGE / width_bytes;
+ uint band = xdev->MaxTempImage / width_bytes;
uint default_raster = bitmap_raster((x1 - x0) * depth);
gs_get_bits_options_t options = params->options;
uint raster =
@@ -932,7 +793,16 @@ x_get_bits_rectangle(gx_device * dev, const gs_int_rect * prect,
GB_RASTER_STANDARD);
if (x0 >= x1 || y0 >= y1)
return 0;
- flush_text(dev);
+ if (x1 <= xdev->update.box.p.x || x0 >= xdev->update.box.q.x ||
+ y1 <= xdev->update.box.p.y || y0 >= xdev->update.box.q.y
+ ) {
+ /*
+ * The area being read back doesn't overlap the pending update:
+ * just flush text.
+ */
+ flush_text(xdev);
+ } else
+ update_do_flush(xdev);
/*
* If we want a list of unread rectangles, turn on graphics
* exposures, and accept exposure events.
@@ -1074,7 +944,7 @@ x_get_bits_rectangle(gx_device * dev, const gs_int_rect * prect,
/* Set up with a specified tile. */
/* Return false if we can't do it for some reason. */
private int
-set_tile(register gx_device * dev, register const gx_strip_bitmap * tile)
+set_tile(gx_device * dev, const gx_strip_bitmap * tile)
{
gx_device_X *xdev = (gx_device_X *) dev;
@@ -1106,7 +976,7 @@ set_tile(register gx_device * dev, register const gx_strip_bitmap * tile)
xdev->image.height = tile->size.y;
xdev->image.bytes_per_line = tile->raster;
xdev->image.format = XYBitmap;
- set_fill_style(FillSolid);
+ X_SET_FILL_STYLE(xdev, FillSolid);
#ifdef DEBUG
if (gs_debug['H']) {
int i;
@@ -1120,7 +990,7 @@ set_tile(register gx_device * dev, register const gx_strip_bitmap * tile)
}
#endif
XSetTile(xdev->dpy, xdev->gc, xdev->ht.no_pixmap); /* *** X bug *** */
- set_function(GXcopy);
+ X_SET_FUNCTION(xdev, GXcopy);
put_image(xdev->dpy, xdev->ht.pixmap, xdev->gc, &xdev->image,
0, 0, 0, 0, tile->size.x, tile->size.y);
XSetTile(xdev->dpy, xdev->gc, xdev->ht.pixmap);
@@ -1128,92 +998,141 @@ set_tile(register gx_device * dev, register const gx_strip_bitmap * tile)
return xdev->useXSetTile;
}
-
/* ------ Screen update procedures ------ */
-/* Flush updates to the screen if needed. */
+/* Initialize the update machinery. */
private void
-update_do_flush(register gx_device * dev)
+update_init(gx_device_X *xdev)
{
- gx_device_X *xdev = (gx_device_X *) dev;
+ xdev->update.box.p.x = xdev->update.box.p.y = max_int_in_fixed;
+ xdev->update.box.q.x = xdev->update.box.q.y = min_int_in_fixed;
+ xdev->update.area = xdev->update.total = xdev->update.count = 0;
+}
- flush_text(dev);
- if (xdev->up_area != 0) {
- int xo = xdev->update.xo, yo = xdev->update.yo;
+/* Flush updates to the screen if needed. */
+private void
+update_do_flush(gx_device_X * xdev)
+{
+ flush_text(xdev);
+ if (xdev->update.count != 0) {
+ int x = xdev->update.box.p.x, y = xdev->update.box.p.y;
+ int w = xdev->update.box.q.x - x, h = xdev->update.box.q.y - y;
+
+ fit_fill_xywh(xdev, x, y, w, h);
+ if (w > 0 && h > 0) {
+ if (IS_BUFFERED(xdev)) {
+ /* Copy from memory image to X server. */
+ const gx_device_memory *mdev =
+ (const gx_device_memory *)xdev->target;
+
+ x_copy_image(xdev, mdev->line_ptrs[y], x, mdev->raster,
+ x, y, w, h);
+ }
+ if (xdev->bpixmap) {
+ /* Copy from X backing pixmap to screen. */
- set_function(GXcopy);
- XCopyArea(xdev->dpy, xdev->bpixmap, xdev->win, xdev->gc,
- xo, yo, xdev->update.xe - xo, xdev->update.ye - yo,
- xo, yo);
- update_init(dev);
+ X_SET_FUNCTION(xdev, GXcopy);
+ XCopyArea(xdev->dpy, xdev->bpixmap, xdev->win, xdev->gc,
+ x, y, w, h, x, y);
+ }
+ }
+ update_init(xdev);
}
}
-/* Add a region to be updated. */
-/* This is only called if xdev->bpixmap != 0. */
+/* Add a region to be updated, after writing to that region. */
void
-x_update_add(gx_device * dev, int xo, int yo, int w, int h)
+x_update_add(gx_device_X * xdev, int xo, int yo, int w, int h)
{
- register gx_device_X *xdev = (gx_device_X *) dev;
int xe = xo + w, ye = yo + h;
- long new_area;
-
- if (X_ALWAYS_UPDATE) { /* Update the screen now. */
- update_do_flush(dev);
- new_area = (long)w *h;
- } else { /* Only update the screen if it's worthwhile. */
- if ((++xdev->up_count >= 200 && xdev->up_area > 1000) ||
- xdev->up_area == 0
- ) {
- if (xdev->up_area != 0)
- update_do_flush(dev);
- new_area = (long)w *h;
- } else { /* See whether adding this rectangle */
- /* would result in too much being copied unnecessarily. */
- long old_area = xdev->up_area;
- long new_up_area;
- x_rect u;
-
- u.xo = min(xo, xdev->update.xo);
- u.yo = min(yo, xdev->update.yo);
- u.xe = max(xe, xdev->update.xe);
- u.ye = max(ye, xdev->update.ye);
- new_up_area = (long)(u.xe - u.xo) * (u.ye - u.yo);
- /* The fraction of new_up_area used in the following test */
- /* is not particularly critical; using a denominator */
- /* that is a power of 2 eliminates a divide. */
- if (u.xe - u.xo >= 10 && u.ye - u.yo >= 10 &&
- old_area + (new_area = (long)w * h) <
- new_up_area - (new_up_area >> 2)
- )
- update_do_flush(dev);
- else {
- xdev->update = u;
- xdev->up_area = new_up_area;
- return;
- }
- }
+ long added = (long)w * h;
+ long old_area = xdev->update.area;
+ gs_int_rect u;
+ int nw, nh;
+ long new_up_area;
+
+ u.p.x = min(xo, xdev->update.box.p.x);
+ u.p.y = min(yo, xdev->update.box.p.y);
+ u.q.x = max(xe, xdev->update.box.q.x);
+ u.q.y = max(ye, xdev->update.box.q.y);
+ nw = u.q.x - u.p.x;
+ nh = u.q.y - u.p.y;
+ new_up_area = (long)nw * nh;
+ xdev->update.box = u;
+ xdev->update.count++;
+ xdev->update.area = new_up_area;
+ xdev->update.total += added;
+ if (!xdev->AlwaysUpdate &&
+ xdev->update.count < xdev->MaxBufferedCount &&
+ xdev->update.area < xdev->MaxBufferedArea &&
+ xdev->update.total < xdev->MaxBufferedTotal
+ ) {
+ /*
+ * Test whether adding this rectangle would result in too much being
+ * copied unnecessarily. The fraction of new_up_area used in the
+ * following test is not particularly critical; using a denominator
+ * that is a power of 2 eliminates a divide.
+ */
+ if (nw + nh >= 70 && (nw | nh) >= 16 &&
+ old_area + added < new_up_area - (new_up_area >> 2)
+ )
+ DO_NOTHING;
+ else
+ return;
}
-
- xdev->update.xo = xo;
- xdev->update.yo = yo;
- xdev->update.xe = xe;
- xdev->update.ye = ye;
- xdev->up_area = new_area;
+ update_do_flush(xdev);
}
/* Flush buffered text to the screen. */
private void
-do_flush_text(gx_device * dev)
+do_flush_text(gx_device_X * xdev)
{
- gx_device_X *xdev = (gx_device_X *) dev;
-
if (!IN_TEXT(xdev))
return;
DRAW_TEXT(xdev);
xdev->text.item_count = xdev->text.char_count = 0;
}
+/* Bounding box device procedures (only used when buffering) */
+private bool
+x_bbox_init_box(void *pdata)
+{
+ gx_device_X *const xdev = pdata;
+
+ update_init(xdev);
+ return true;
+}
+private void
+x_bbox_get_box(const void *pdata, gs_fixed_rect *pbox)
+{
+ const gx_device_X *const xdev = pdata;
+
+ pbox->p.x = int2fixed(xdev->update.box.p.x);
+ pbox->p.y = int2fixed(xdev->update.box.p.y);
+ pbox->q.x = int2fixed(xdev->update.box.q.x);
+ pbox->q.y = int2fixed(xdev->update.box.q.y);
+}
+private void
+x_bbox_add_rect(void *pdata, fixed x0, fixed y0, fixed x1, fixed y1)
+{
+ gx_device_X *const xdev = pdata;
+ int x = fixed2int(x0), y = fixed2int(y0);
+
+ x_update_add(xdev, x, y, fixed2int_ceiling(x1) - x,
+ fixed2int_ceiling(y1) - y);
+}
+private bool
+x_bbox_in_rect(const void *pdata, const gs_fixed_rect *pbox)
+{
+ gs_fixed_rect box;
+
+ x_bbox_get_box(pdata, &box);
+ return rect_within(*pbox, box);
+}
+const gx_device_bbox_procs_t gdev_x_box_procs = {
+ x_bbox_init_box, x_bbox_get_box, x_bbox_add_rect, x_bbox_in_rect
+};
+
/* ------ Internal procedures ------ */
/* Substitute for XPutImage using XFillRectangle. */
@@ -1258,9 +1177,9 @@ alt_put_image(gx_device * dev, Display * dpy, Drawable win, GC gc,
}
for (yi = 0; yi < h; yi++, data += raster) {
- register int mask = init_mask;
- register byte *dp = data;
- register int xi = 0;
+ int mask = init_mask;
+ byte *dp = data;
+ int xi = 0;
while (xi < w) {
if ((*dp ^ invert) & mask) {
diff --git a/gs/src/gdevx.h b/gs/src/gdevx.h
index 266d77191..e1f6df2c4 100644
--- a/gs/src/gdevx.h
+++ b/gs/src/gdevx.h
@@ -25,6 +25,7 @@
/* Define the type of an X pixel. */
typedef unsigned long x_pixel;
+#include "gdevbbox.h"
#include "gdevxcmp.h"
/* Declare the X resource tables compiled separately in gdevxres.c. */
@@ -32,12 +33,11 @@ extern XtResource gdev_x_resources[];
extern const int gdev_x_resource_count;
extern String gdev_x_fallback_resources[];
-/* Define a rectangle structure for update bookkeeping */
-typedef struct x_rect_s {
- int xo, yo, xe, ye;
-} x_rect;
-
/* Define PostScript to X11 font name mapping */
+/*
+ * x11fontlist is only used within x11fontmap.
+ * The names array is managed by Xlib, so the structure is simple.
+ */
typedef struct x11fontlist_s {
char **names;
int count;
@@ -49,11 +49,18 @@ struct x11fontmap_s {
x11fontlist std, iso;
x11fontmap *next;
};
+#define private_st_x11fontmap() /* in gdevxini.c */\
+ gs_private_st_ptrs3(st_x11fontmap, x11fontmap, "x11fontmap",\
+ x11fontmap_enum_ptrs, x11fontmap_reloc_ptrs, ps_name, x11_name, next)
/* Define the X Windows device */
typedef struct gx_device_X_s {
- gx_device_common;
+ gx_device_bbox_common; /* if target != 0, is image buffer */
+#define IS_BUFFERED(xdev) ((xdev)->target != 0)
bool IsPageDevice;
+ long MaxBitmap;
+ byte *buffer; /* full-window image */
+ long buffer_size;
/* An XImage object for writing bitmap images to the screen */
XImage image;
@@ -71,16 +78,18 @@ typedef struct gx_device_X_s {
/* A backing pixmap so X will handle exposure automatically */
Pixmap bpixmap; /* 0 if useBackingPixmap is false, */
- /* or if it can't be allocated */
+ /* or if it can't be allocated */
int ghostview; /* flag to tell if ghostview is in control */
Window mwin; /* window to receive ghostview messages */
gs_matrix initial_matrix; /* the initial transformation */
Atom NEXT, PAGE, DONE; /* Atoms used to talk to ghostview */
- x_rect update; /* region needing updating */
- long up_area; /* total area of update */
- /* (always 0 if no backing pixmap) */
- int up_count; /* # of updates since flush */
- Pixmap dest; /* bpixmap if non-0, else win */
+ struct {
+ gs_int_rect box; /* region needing updating */
+ long area; /* total area of update */
+ long total; /* total of individual area updates */
+ int count; /* # of updates since flush */
+ } update;
+ Pixmap dest; /* bpixmap if non-0, else use win */
x_pixel colors_or; /* 'or' of all device colors used so far */
x_pixel colors_and; /* 'and' ditto */
@@ -106,15 +115,21 @@ typedef struct gx_device_X_s {
int fill_style;
Font fid;
-#define set_fill_style(style)\
- if ( xdev->fill_style != style )\
- XSetFillStyle(xdev->dpy, xdev->gc, (xdev->fill_style = style))
-#define set_function(func)\
- if ( xdev->function != func )\
- XSetFunction(xdev->dpy, xdev->gc, (xdev->function = func))
-#define set_font(font)\
- if ( xdev->fid != font )\
- XSetFont(xdev->dpy, xdev->gc, (xdev->fid = font))
+#define X_SET_FILL_STYLE(xdev, style)\
+ BEGIN\
+ if (xdev->fill_style != (style))\
+ XSetFillStyle(xdev->dpy, xdev->gc, (xdev->fill_style = (style)));\
+ END
+#define X_SET_FUNCTION(xdev, func)\
+ BEGIN\
+ if (xdev->function != (func))\
+ XSetFunction(xdev->dpy, xdev->gc, (xdev->function = (func)));\
+ END
+#define X_SET_FONT(xdev, font)\
+ BEGIN\
+ if (xdev->fid != (font))\
+ XSetFont(xdev->dpy, xdev->gc, (xdev->fid = (font)));\
+ END
x_pixel back_color, fore_color;
@@ -126,21 +141,25 @@ typedef struct gx_device_X_s {
*/
x11_cman_t cman;
-#define note_color(pixel)\
- xdev->colors_or |= pixel,\
- xdev->colors_and &= pixel
-#define set_back_color(pixel)\
- if ( xdev->back_color != pixel )\
- { xdev->back_color = pixel;\
- note_color(pixel);\
- XSetBackground(xdev->dpy, xdev->gc, pixel);\
- }
-#define set_fore_color(pixel)\
- if ( xdev->fore_color != pixel )\
- { xdev->fore_color = pixel;\
- note_color(pixel);\
- XSetForeground(xdev->dpy, xdev->gc, pixel);\
- }
+#define NOTE_COLOR(xdev, pixel)\
+ (xdev->colors_or |= (pixel),\
+ xdev->colors_and &= (pixel))
+#define X_SET_BACK_COLOR(xdev, pixel)\
+ BEGIN\
+ if (xdev->back_color != (pixel)) {\
+ xdev->back_color = (pixel);\
+ NOTE_COLOR(xdev, pixel);\
+ XSetBackground(xdev->dpy, xdev->gc, (pixel));\
+ }\
+ END
+#define X_SET_FORE_COLOR(xdev, pixel)\
+ BEGIN\
+ if (xdev->fore_color != (pixel)) {\
+ xdev->fore_color = (pixel);\
+ NOTE_COLOR(xdev, pixel);\
+ XSetForeground(xdev->dpy, xdev->gc, (pixel));\
+ }\
+ END
/* Defaults set by resources */
Pixel borderColor;
@@ -162,7 +181,36 @@ typedef struct gx_device_X_s {
Boolean useXPutImage;
Boolean useXSetTile;
- /* Buffered text awaiting display */
+ /*
+ * Parameters for the screen update algorithms.
+ */
+
+ /*
+ * Define whether to update after every write, for debugging.
+ * Note that one can obtain the same effect by setting any of
+ */
+ bool AlwaysUpdate;
+ /*
+ * Define the maximum size of the temporary pixmap for copy_mono
+ * that we are willing to leave lying around in the server
+ * between uses.
+ */
+ int MaxTempPixmap;
+ /*
+ * Define the maximum size of the temporary image created in memory
+ * for get_bits_rectangle.
+ */
+ int MaxTempImage;
+ /*
+ * Define the maximum buffered updates before doing a screen write.
+ */
+ int MaxBufferedTotal; /* sum of individual areas */
+ int MaxBufferedArea; /* area of merged bounding box */
+ int MaxBufferedCount; /* number of writes */
+
+ /*
+ * Buffered text awaiting display.
+ */
struct {
int item_count;
#define IN_TEXT(xdev) ((xdev)->text.item_count != 0)
@@ -184,13 +232,39 @@ typedef struct gx_device_X_s {
xdev->text.origin.y, xdev->text.items, xdev->text.item_count)
} gx_device_X;
+#define private_st_device_X() /* in gdevx.c */\
+ gs_public_st_suffix_add4_final(st_device_X, gx_device_X,\
+ "gx_device_X", device_x_enum_ptrs, device_x_reloc_ptrs,\
+ gx_device_finalize, st_device_bbox, buffer, regular_fonts,\
+ symbol_fonts, dingbat_fonts)
+
+/* Send an event to the Ghostview process */
+void gdev_x_send_event(P2(gx_device_X *xdev, Atom msg));
/* function to keep track of screen updates */
-void x_update_add(P5(gx_device *, int, int, int, int));
+void x_update_add(P5(gx_device_X *, int, int, int, int));
void gdev_x_clear_window(P1(gx_device_X *));
int x_catch_free_colors(P2(Display *, XErrorEvent *));
/* Number used to distinguish when resolution was set from the command line */
#define FAKE_RES (16*72)
+/* ------ Inter-module procedures ------ */
+
+/* Exported by gdevxcmp.c for gdevxini.c */
+int gdev_x_setup_colors(P1(gx_device_X *));
+void gdev_x_free_colors(P1(gx_device_X *));
+void gdev_x_free_dynamic_colors(P1(gx_device_X *));
+
+/* Exported by gdevxini.c for gdevx.c */
+int gdev_x_open(P1(gx_device_X *));
+int gdev_x_close(P1(gx_device_X *));
+
+/* Driver procedures exported for gdevx.c */
+dev_proc_map_rgb_color(gdev_x_map_rgb_color); /* gdevxcmp.c */
+dev_proc_map_color_rgb(gdev_x_map_color_rgb); /* gdevxcmp.c */
+dev_proc_get_params(gdev_x_get_params); /* gdevxini.c */
+dev_proc_put_params(gdev_x_put_params); /* gdevxini.c */
+dev_proc_get_xfont_procs(gdev_x_get_xfont_procs); /* gdevxxf.c */
+
#endif /* gdevx_INCLUDED */
diff --git a/gs/src/gdevxalt.c b/gs/src/gdevxalt.c
index 9e93b885d..3fd84e1a3 100644
--- a/gs/src/gdevxalt.c
+++ b/gs/src/gdevxalt.c
@@ -24,10 +24,10 @@
#include "x_.h"
#include "gserrors.h"
#include "gsparam.h"
+#include "gsstruct.h"
#include "gxdevice.h"
#include "gsdevice.h" /* for gs_copydevice */
#include "gdevx.h"
-#include "gdevdcrd.h"
extern const gx_device_X gs_x11_device;
@@ -40,6 +40,9 @@ typedef struct {
gx_device_forward_common;
gx_color_index color_cache[16];
} gx_device_X_wrapper;
+gs_private_st_suffix_add0_final(st_device_X_wrapper, gx_device_X_wrapper,
+ "gx_device_X_wrapper", gdevx_wrapper_enum_ptrs, gdevx_wrapper_reloc_ptrs,
+ gx_device_finalize, st_device_forward);
/* ---------------- Generic procedures ---------------- */
@@ -101,22 +104,14 @@ x_forward_output_page(gx_device * dev, int num_copies, int flush)
private int
x_wrap_close(gx_device * dev)
{
- gx_device *tdev;
-
- /* If Ghostscript is exiting, we might have closed the */
- /* underlying x11 device already.... */
- int code;
-
- set_dev_target(tdev, dev);
- if (tdev->is_open) {
- code = (*dev_proc(tdev, close_device)) (tdev);
- x_clear_color_cache(dev);
- if (code < 0)
- return code;
- tdev->is_open = false;
- } else
- code = 0;
- return code;
+ /*
+ * The underlying x11 device will be closed and freed as soon as there
+ * are no more pointers to it, which normally occurs in the next
+ * statement.
+ */
+ gx_device_set_target((gx_device_forward *)dev, NULL);
+ x_clear_color_cache(dev);
+ return 0;
}
private int
@@ -256,8 +251,7 @@ x_wrap_get_bits(gx_device * dev, int y, byte * str, byte ** actual_data)
int sdepth;
byte smask;
uint dsize;
- gs_memory_t *mem =
- (dev->memory == 0 ? &gs_memory_default : dev->memory);
+ gs_memory_t *mem = dev->memory;
byte *row;
byte *base;
int code;
@@ -330,7 +324,7 @@ x_wrap_get_params(gx_device * dev, gs_param_list * plist)
gx_device *tdev;
/* We assume that a get_params call has no side effects.... */
gx_device_X save_dev;
- int ecode, code;
+ int ecode;
set_dev_target(tdev, dev);
save_dev = *(gx_device_X *) tdev;
@@ -339,9 +333,6 @@ x_wrap_get_params(gx_device * dev, gs_param_list * plist)
tdev->dname = dev->dname;
ecode = (*dev_proc(tdev, get_params)) (tdev, plist);
*(gx_device_X *) tdev = save_dev;
- code = sample_device_crd_get_params(dev, plist, "CRDDefault");
- if (code < 0)
- ecode = code;
return ecode;
}
@@ -518,7 +509,8 @@ private const gx_device_procs x_cmyk_procs =
/* The instances are public. */
const gx_device_X_wrapper gs_x11cmyk_device = {
- std_device_dci_body(gx_device_X_wrapper, &x_cmyk_procs, "x11cmyk",
+ std_device_dci_type_body(gx_device_X_wrapper, &x_cmyk_procs, "x11cmyk",
+ &st_device_X_wrapper,
FAKE_RES * 85 / 10, FAKE_RES * 11, /* x and y extent (nominal) */
FAKE_RES, FAKE_RES, /* x and y density (nominal) */
4, 4, 1, 1, 2, 2),
@@ -526,7 +518,8 @@ const gx_device_X_wrapper gs_x11cmyk_device = {
0 /* target */
};
const gx_device_X_wrapper gs_x11cmyk2_device = {
- std_device_dci_body(gx_device_X_wrapper, &x_cmyk_procs, "x11cmyk2",
+ std_device_dci_type_body(gx_device_X_wrapper, &x_cmyk_procs, "x11cmyk2",
+ &st_device_X_wrapper,
FAKE_RES * 85 / 10, FAKE_RES * 11, /* x and y extent (nominal) */
FAKE_RES, FAKE_RES, /* x and y density (nominal) */
4, 8, 3, 3, 4, 4),
@@ -534,7 +527,8 @@ const gx_device_X_wrapper gs_x11cmyk2_device = {
0 /* target */
};
const gx_device_X_wrapper gs_x11cmyk4_device = {
- std_device_dci_body(gx_device_X_wrapper, &x_cmyk_procs, "x11cmyk4",
+ std_device_dci_type_body(gx_device_X_wrapper, &x_cmyk_procs, "x11cmyk4",
+ &st_device_X_wrapper,
FAKE_RES * 85 / 10, FAKE_RES * 11, /* x and y extent (nominal) */
FAKE_RES, FAKE_RES, /* x and y density (nominal) */
4, 16, 15, 15, 16, 16),
@@ -542,7 +536,8 @@ const gx_device_X_wrapper gs_x11cmyk4_device = {
0 /* target */
};
const gx_device_X_wrapper gs_x11cmyk8_device = {
- std_device_dci_body(gx_device_X_wrapper, &x_cmyk_procs, "x11cmyk8",
+ std_device_dci_type_body(gx_device_X_wrapper, &x_cmyk_procs, "x11cmyk8",
+ &st_device_X_wrapper,
FAKE_RES * 85 / 10, FAKE_RES * 11, /* x and y extent (nominal) */
FAKE_RES, FAKE_RES, /* x and y density (nominal) */
4, 32, 255, 255, 256, 256),
@@ -628,10 +623,11 @@ private const gx_device_procs x_mono_procs =
/* The instance is public. */
const gx_device_X_wrapper gs_x11mono_device =
{
- std_device_dci_body(gx_device_X_wrapper, &x_mono_procs, "x11mono",
- FAKE_RES * 85 / 10, FAKE_RES * 11, /* x and y extent (nominal) */
- FAKE_RES, FAKE_RES, /* x and y density (nominal) */
- 1, 1, 1, 0, 2, 0),
+ std_device_dci_type_body(gx_device_X_wrapper, &x_mono_procs, "x11mono",
+ &st_device_X_wrapper,
+ FAKE_RES * 85 / 10, FAKE_RES * 11, /* x and y extent (nominal) */
+ FAKE_RES, FAKE_RES, /* x and y density (nominal) */
+ 1, 1, 1, 0, 2, 0),
{0}, /* std_procs */
0 /* target */
};
@@ -668,20 +664,22 @@ private const gx_device_procs x_gray_procs =
/* The instances are public. */
const gx_device_X_wrapper gs_x11gray2_device =
{
- std_device_dci_body(gx_device_X_wrapper, &x_gray_procs, "x11gray2",
- FAKE_RES * 85 / 10, FAKE_RES * 11, /* x and y extent (nominal) */
- FAKE_RES, FAKE_RES, /* x and y density (nominal) */
- 1, 2, 3, 0, 4, 0),
+ std_device_dci_type_body(gx_device_X_wrapper, &x_gray_procs, "x11gray2",
+ &st_device_X_wrapper,
+ FAKE_RES * 85 / 10, FAKE_RES * 11, /* x and y extent (nominal) */
+ FAKE_RES, FAKE_RES, /* x and y density (nominal) */
+ 1, 2, 3, 0, 4, 0),
{0}, /* std_procs */
0 /* target */
};
const gx_device_X_wrapper gs_x11gray4_device =
{
- std_device_dci_body(gx_device_X_wrapper, &x_gray_procs, "x11gray4",
- FAKE_RES * 85 / 10, FAKE_RES * 11, /* x and y extent (nominal) */
- FAKE_RES, FAKE_RES, /* x and y density (nominal) */
- 1, 4, 15, 0, 16, 0),
+ std_device_dci_type_body(gx_device_X_wrapper, &x_gray_procs, "x11gray4",
+ &st_device_X_wrapper,
+ FAKE_RES * 85 / 10, FAKE_RES * 11, /* x and y extent (nominal) */
+ FAKE_RES, FAKE_RES, /* x and y density (nominal) */
+ 1, 4, 15, 0, 16, 0),
{0}, /* std_procs */
0 /* target */
};
@@ -724,10 +722,10 @@ private const gx_device_procs x_alpha_procs =
const gx_device_X_wrapper gs_x11alpha_device =
{
std_device_dci_alpha_type_body(gx_device_X_wrapper, &x_alpha_procs,
- "x11alpha", 0,
- FAKE_RES * 85 / 10, FAKE_RES * 11, /* x and y extent (nominal) */
- FAKE_RES, FAKE_RES, /* x and y density (nominal) */
- 3, 32, 255, 255, 256, 256, 4, 4),
+ "x11alpha", &st_device_X_wrapper,
+ FAKE_RES * 85 / 10, FAKE_RES * 11, /* x and y extent (nominal) */
+ FAKE_RES, FAKE_RES, /* x and y density (nominal) */
+ 3, 32, 255, 255, 256, 256, 4, 4),
{0}, /* std_procs */
0 /* target */
};
diff --git a/gs/src/gdevxcmp.c b/gs/src/gdevxcmp.c
index 6d042a248..b466fe64c 100644
--- a/gs/src/gdevxcmp.c
+++ b/gs/src/gdevxcmp.c
@@ -36,6 +36,36 @@ gs_x_free(void *obj, client_name_t cname)
/* ---------------- Color mapping setup / cleanup ---------------- */
#if HaveStdCMap
+
+/* Install a standard color map in the device. */
+/* Sets std_cmap.* except for free_map. */
+private bool
+set_cmap_values(x11_cmap_values_t *values, int maxv, int mult)
+{
+ int i;
+
+ if (maxv < 1 || maxv > 63 || (maxv & (maxv + 1)) ||
+ (mult & (mult - 1))
+ )
+ return false;
+ values->cv_shift = 16 - small_exact_log2(maxv + 1);
+ for (i = 0; i <= maxv; ++i)
+ values->nearest[i] = X_max_color_value * i / maxv;
+ for (i = 0; mult != (1 << i); ++i)
+ DO_NOTHING;
+ values->pixel_shift = i;
+ return true;
+}
+private void
+set_std_cmap(gx_device_X *xdev, XStandardColormap *map)
+{
+ xdev->cman.std_cmap.map = map;
+ xdev->cman.std_cmap.fast =
+ set_cmap_values(&xdev->cman.std_cmap.red, map->red_max, map->red_mult) &&
+ set_cmap_values(&xdev->cman.std_cmap.green, map->green_max, map->green_mult) &&
+ set_cmap_values(&xdev->cman.std_cmap.blue, map->blue_max, map->blue_mult);
+}
+
/* Get the Standard colormap if available. */
/* Uses: dpy, scr, cmap. */
private XStandardColormap *
@@ -56,7 +86,7 @@ x_get_std_cmap(gx_device_X * xdev, Atom prop)
/* Create a Standard colormap for a TrueColor or StaticGray display. */
/* Return true if the allocation was successful. */
-/* Uses: vinfo. Sets: std_cmap, free_std_cmap. */
+/* Uses: vinfo. Sets: std_cmap.*. */
private bool
alloc_std_cmap(gx_device_X *xdev, bool colored)
{
@@ -91,10 +121,11 @@ alloc_std_cmap(gx_device_X *xdev, bool colored)
cmap->blue_mult <<= 1;
}
}
- xdev->cman.std_cmap = cmap;
- xdev->cman.free_std_cmap = true;
+ set_std_cmap(xdev, cmap);
+ xdev->cman.std_cmap.free_map = true;
return true;
}
+
#endif
/* Allocate the dynamic color table, if needed and possible. */
@@ -260,8 +291,8 @@ gdev_x_setup_colors(gx_device_X * xdev)
xdev->cman.num_rgb = 1 << xdev->vinfo->bits_per_rgb;
#if HaveStdCMap
- xdev->cman.std_cmap = NULL;
- xdev->cman.free_std_cmap = false;
+ xdev->cman.std_cmap.map = NULL;
+ xdev->cman.std_cmap.free_map = false;
#endif
xdev->cman.dither_ramp = NULL;
xdev->cman.dynamic.colors = NULL;
@@ -278,6 +309,21 @@ gdev_x_setup_colors(gx_device_X * xdev)
eprintf1("Unsupported X visual depth: %d\n", xdev->vinfo->depth);
return_error(gs_error_rangecheck);
}
+ { /* Set up the reverse map from pixel values to RGB. */
+ int count = 1 << min(xdev->color_info.depth, 8);
+
+ xdev->cman.color_to_rgb.values =
+ (x11_rgb_t *)gs_malloc(sizeof(x11_rgb_t), count,
+ "gdevx color_to_rgb");
+ if (xdev->cman.color_to_rgb.values) {
+ int i;
+
+ for (i = 0; i < count; ++i)
+ xdev->cman.color_to_rgb.values[i].defined = false;
+ xdev->cman.color_to_rgb.size = count;
+ } else
+ xdev->cman.color_to_rgb.size = 0;
+ }
switch ((int)palette) {
case 'C':
xdev->color_info.num_components = 3;
@@ -286,17 +332,19 @@ gdev_x_setup_colors(gx_device_X * xdev)
#if HaveStdCMap
/* Get a standard color map if available */
if (xdev->vinfo->visual == DefaultVisualOfScreen(xdev->scr)) {
- xdev->cman.std_cmap = x_get_std_cmap(xdev, XA_RGB_DEFAULT_MAP);
+ xdev->cman.std_cmap.map = x_get_std_cmap(xdev, XA_RGB_DEFAULT_MAP);
} else {
- xdev->cman.std_cmap = x_get_std_cmap(xdev, XA_RGB_BEST_MAP);
+ xdev->cman.std_cmap.map = x_get_std_cmap(xdev, XA_RGB_BEST_MAP);
}
- if (xdev->cman.std_cmap ||
+ if (xdev->cman.std_cmap.map ||
(xdev->vinfo->class == TrueColor && alloc_std_cmap(xdev, true))
) {
xdev->color_info.dither_grays = xdev->color_info.dither_colors =
- min(xdev->cman.std_cmap->red_max,
- min(xdev->cman.std_cmap->green_max,
- xdev->cman.std_cmap->blue_max)) + 1;
+ min(xdev->cman.std_cmap.map->red_max,
+ min(xdev->cman.std_cmap.map->green_max,
+ xdev->cman.std_cmap.map->blue_max)) + 1;
+ if (xdev->cman.std_cmap.map)
+ set_std_cmap(xdev, xdev->cman.std_cmap.map);
} else
#endif
/* Otherwise set up a rgb cube of our own */
@@ -340,11 +388,14 @@ grayscale:
xdev->color_info.max_gray = xdev->cman.num_rgb - 1;
#if HaveStdCMap
/* Get a standard color map if available */
- xdev->cman.std_cmap = x_get_std_cmap(xdev, XA_RGB_GRAY_MAP);
- if (xdev->cman.std_cmap ||
+ xdev->cman.std_cmap.map = x_get_std_cmap(xdev, XA_RGB_GRAY_MAP);
+ if (xdev->cman.std_cmap.map ||
(xdev->vinfo->class == StaticGray && alloc_std_cmap(xdev, false))
) {
- xdev->color_info.dither_grays = xdev->cman.std_cmap->red_max + 1;
+ xdev->color_info.dither_grays =
+ xdev->cman.std_cmap.map->red_max + 1;
+ if (xdev->cman.std_cmap.map)
+ set_std_cmap(xdev, xdev->cman.std_cmap.map);
} else
#endif
/* Otherwise set up a gray ramp of our own */
@@ -383,22 +434,11 @@ monochrome:
break;
default:
eprintf1("Unknown palette: %s\n", xdev->palette);
- return_error(gs_error_rangecheck);
- }
- { /* Set up the reverse map from pixel values to RGB. */
- int count = 1 << min(xdev->color_info.depth, 8);
-
- xdev->cman.color_to_rgb.values =
- (x11_rgb_t *)gs_malloc(sizeof(x11_rgb_t), count,
- "gdevx color_to_rgb");
if (xdev->cman.color_to_rgb.values) {
- int i;
-
- for (i = 0; i < count; ++i)
- xdev->cman.color_to_rgb.values[i].defined = false;
- xdev->cman.color_to_rgb.size = count;
- } else
- xdev->cman.color_to_rgb.size = 0;
+ gs_x_free(xdev->cman.color_to_rgb.values, "gdevx color_to_rgb");
+ xdev->cman.color_to_rgb.values = 0;
+ }
+ return_error(gs_error_rangecheck);
}
return 0;
}
@@ -426,18 +466,20 @@ gdev_x_free_dynamic_colors(gx_device_X *xdev)
}
}
-/* Free storage and color map entries when closing the device. */
-/* Uses and sets: cman.{std_cmap, dither_ramp, dynamic.colors, color_to_rgb.*}. */
-/* Uses: cman.free_std_cmap. */
+/*
+ * Free storage and color map entries when closing the device.
+ * Uses and sets: cman.{std_cmap.map, dither_ramp, dynamic.colors,
+ * color_to_rgb}. Uses: cman.std_cmap.free_map.
+ */
void
gdev_x_free_colors(gx_device_X *xdev)
{
- if (xdev->cman.free_std_cmap) {
+ if (xdev->cman.std_cmap.free_map) {
/* XFree is declared as taking a char *, not a void *! */
- XFree((void *)xdev->cman.std_cmap);
- xdev->cman.free_std_cmap = false;
+ XFree((void *)xdev->cman.std_cmap.map);
+ xdev->cman.std_cmap.free_map = false;
}
- xdev->cman.std_cmap = 0;
+ xdev->cman.std_cmap.map = 0;
if (xdev->cman.dither_ramp)
gs_x_free(xdev->cman.dither_ramp, "x11 dither_colors");
if (xdev->cman.dynamic.colors) {
@@ -527,25 +569,38 @@ gdev_x_map_rgb_color(gx_device * dev,
#if HaveStdCMap
/* check the standard colormap first */
- if (xdev->cman.std_cmap) {
- const XStandardColormap *cmap = xdev->cman.std_cmap;
+ if (xdev->cman.std_cmap.map) {
+ const XStandardColormap *cmap = xdev->cman.std_cmap.map;
if (gx_device_has_color(xdev)) {
uint cr, cg, cb; /* rgb cube indices */
X_color_value cvr, cvg, cvb; /* color value on cube */
- cr = r * (cmap->red_max + 1) / CV_DENOM;
- cg = g * (cmap->green_max + 1) / CV_DENOM;
- cb = b * (cmap->blue_max + 1) / CV_DENOM;
- cvr = X_max_color_value * cr / cmap->red_max;
- cvg = X_max_color_value * cg / cmap->green_max;
- cvb = X_max_color_value * cb / cmap->blue_max;
+ if (xdev->cman.std_cmap.fast) {
+ cr = r >> xdev->cman.std_cmap.red.cv_shift;
+ cvr = xdev->cman.std_cmap.red.nearest[cr];
+ cg = g >> xdev->cman.std_cmap.green.cv_shift;
+ cvg = xdev->cman.std_cmap.green.nearest[cg];
+ cb = b >> xdev->cman.std_cmap.blue.cv_shift;
+ cvb = xdev->cman.std_cmap.blue.nearest[cb];
+ } else {
+ cr = r * (cmap->red_max + 1) / CV_DENOM;
+ cg = g * (cmap->green_max + 1) / CV_DENOM;
+ cb = b * (cmap->blue_max + 1) / CV_DENOM;
+ cvr = X_max_color_value * cr / cmap->red_max;
+ cvg = X_max_color_value * cg / cmap->green_max;
+ cvb = X_max_color_value * cb / cmap->blue_max;
+ }
if ((iabs((int)r - (int)cvr) & xdev->cman.color_mask.red) == 0 &&
(iabs((int)g - (int)cvg) & xdev->cman.color_mask.green) == 0 &&
(iabs((int)b - (int)cvb) & xdev->cman.color_mask.blue) == 0) {
gx_color_index pixel =
- cr * cmap->red_mult + cg * cmap->green_mult +
- cb * cmap->blue_mult + cmap->base_pixel;
+ (xdev->cman.std_cmap.fast ?
+ (cr << xdev->cman.std_cmap.red.pixel_shift) +
+ (cg << xdev->cman.std_cmap.green.pixel_shift) +
+ (cb << xdev->cman.std_cmap.blue.pixel_shift) :
+ cr * cmap->red_mult + cg * cmap->green_mult +
+ cb * cmap->blue_mult) + cmap->base_pixel;
if_debug4('C', "[cX]%u,%u,%u (std cmap) => %lu\n",
r, g, b, pixel);
@@ -691,7 +746,7 @@ gdev_x_map_color_rgb(gx_device * dev, gx_color_index color,
{
const gx_device_X *const xdev = (const gx_device_X *) dev;
#if HaveStdCMap
- const XStandardColormap *cmap = xdev->cman.std_cmap;
+ const XStandardColormap *cmap = xdev->cman.std_cmap.map;
#endif
if (color == xdev->foreground) {
diff --git a/gs/src/gdevxcmp.h b/gs/src/gdevxcmp.h
index 6d0eb5636..2d09493b6 100644
--- a/gs/src/gdevxcmp.h
+++ b/gs/src/gdevxcmp.h
@@ -45,12 +45,23 @@ struct x11_color_s {
/*
* Define X color values. Fortuitously, these are the same as Ghostscript
- * color values; in gdevxcmap.c, we are pretty sloppy about aliasing the
+ * color values; in gdevxcmp.c, we are pretty sloppy about aliasing the
* two.
*/
typedef ushort X_color_value;
#define X_max_color_value 0xffff
+#if HaveStdCMap /* Standard colormap stuff is only in X11R4 and later. */
+
+/* Define the structure for values computed from a standard cmap component. */
+typedef struct x11_cmap_values_s {
+ int cv_shift; /* 16 - log2(max_value + 1) */
+ X_color_value nearest[64]; /* [i] = i * 0xffff / max_value */
+ int pixel_shift; /* log2(mult) */
+} x11_cmap_values_t;
+
+#endif
+
typedef struct x11_cman_s {
/*
@@ -70,19 +81,29 @@ typedef struct x11_cman_s {
#if HaveStdCMap /* Standard colormap stuff is only in X11R4 and later. */
- /*
- * std_cmap is the X standard colormap for the display and screen,
- * if one is available.
- */
-
- XStandardColormap *std_cmap;
-
- /*
- * If free_std_cmap is true, we allocated std_cmap ourselves (to
- * represent a TrueColor or Static Gray visual), and must free it when
- * closing the device.
- */
- bool free_std_cmap;
+ struct {
+
+ /*
+ * map is the X standard colormap for the display and screen,
+ * if one is available.
+ */
+ XStandardColormap *map;
+
+ /*
+ * When possible, we precompute shift values and tables that replace
+ * some multiplies and divides.
+ */
+ bool fast;
+ x11_cmap_values_t red, green, blue;
+
+ /*
+ * If free_map is true, we allocated the map ourselves (to
+ * represent a TrueColor or Static Gray visual), and must free it
+ * when closing the device.
+ */
+ bool free_map;
+
+ } std_cmap;
#endif /* HaveStdCmap */
diff --git a/gs/src/gdevxini.c b/gs/src/gdevxini.c
index abf4132db..dba19c746 100644
--- a/gs/src/gdevxini.c
+++ b/gs/src/gdevxini.c
@@ -17,16 +17,24 @@
*/
-/* X Windows driver initialization for Ghostscript library */
+/* X Windows driver initialization/finalization */
#include "memory_.h"
#include "x_.h"
#include "gx.h"
#include "gserrors.h"
#include "gxdevice.h"
+#include "gxdevmem.h"
+#include "gsparamx.h"
+#include "gdevbbox.h"
#include "gdevx.h"
extern char *getenv(P1(const char *));
+extern const gx_device_bbox gs_bbox_device;
+extern const gx_device_X gs_x11_device;
+
+extern const gx_device_bbox_procs_t gdev_x_box_procs;
+
/* Define constants for orientation from ghostview */
/* Number represents clockwise rotation of the paper in degrees */
typedef enum {
@@ -36,8 +44,12 @@ typedef enum {
Seascape = 270 /* Landscape rotated the wrong way */
} orientation;
-/* Forward/external references */
-int gdev_x_setup_colors(P1(gx_device_X *));
+/* GC descriptors */
+private_st_x11fontmap();
+
+/* ---------------- Opening/initialization ---------------- */
+
+/* Forward references */
private void gdev_x_setup_fontmap(P1(gx_device_X *));
/* Catch the alloc error when there is not enough resources for the
@@ -74,7 +86,7 @@ x_catch_free_colors(Display * dpy, XErrorEvent * err)
/* Open the X device */
int
-gdev_x_open(register gx_device_X * xdev)
+gdev_x_open(gx_device_X * xdev)
{
XSizeHints sizehints;
char *window_id;
@@ -476,6 +488,117 @@ gdev_x_open(register gx_device_X * xdev)
return 0;
}
+/* Set up or take down buffering in a RAM image. */
+private int
+x_set_buffer(gx_device_X * xdev)
+{
+ gs_memory_t *mem = xdev->memory;
+ bool buffered = xdev->MaxBitmap > 0;
+ const gx_device_procs *procs;
+
+ setup:
+ if (buffered) {
+ /* We want to buffer. */
+ /* Check that we can set up a memory device. */
+ gx_device_memory *mdev = (gx_device_memory *)xdev->target;
+
+ if (mdev == 0 || mdev->color_info.depth != xdev->color_info.depth) {
+ const gx_device_memory *mdproto =
+ gdev_mem_device_for_bits(xdev->color_info.depth);
+
+ if (!mdproto) {
+ buffered = false;
+ goto setup;
+ }
+ if (mdev) {
+ /* Update the pointer we're about to overwrite. */
+ gx_device_set_target((gx_device_forward *)mdev, NULL);
+ } else {
+ mdev = gs_alloc_struct(mem, gx_device_memory,
+ &st_device_memory, "memory device");
+ if (mdev == 0) {
+ buffered = false;
+ goto setup;
+ }
+ }
+ /*
+ * We want to forward image drawing to the memory device.
+ * That requires making the memory device forward its color
+ * mapping operations back to the X device, creating a circular
+ * pointer structure. This is not a disaster, we just need to
+ * be aware that this is going on.
+ */
+ gs_make_mem_device(mdev, mdproto, mem, 0, (gx_device *)xdev);
+ gx_device_set_target((gx_device_forward *)xdev, (gx_device *)mdev);
+ }
+ if (mdev->width != xdev->width || mdev->height != xdev->height) {
+ byte *buffer;
+ ulong space;
+
+ space = gdev_mem_data_size(mdev, xdev->width, xdev->height);
+ if (space > xdev->MaxBitmap) {
+ buffered = false;
+ goto setup;
+ }
+ buffer =
+ (xdev->buffer ?
+ (byte *)gs_resize_object(mem, xdev->buffer, space, "buffer") :
+ gs_alloc_bytes(mem, space, "buffer"));
+ if (!buffer) {
+ buffered = false;
+ goto setup;
+ }
+ xdev->buffer_size = space;
+ xdev->buffer = buffer;
+ mdev->width = xdev->width;
+ mdev->height = xdev->height;
+ mdev->color_info = xdev->color_info;
+ mdev->base = xdev->buffer;
+ gdev_mem_open_scan_lines(mdev, xdev->height);
+ }
+ xdev->white = gx_device_white((gx_device *)xdev);
+ xdev->black = gx_device_black((gx_device *)xdev);
+ procs = &gs_bbox_device.procs;
+ } else {
+ /* Not buffering. Release the buffer and memory device. */
+ gs_free_object(mem, xdev->buffer, "buffer");
+ xdev->buffer = 0;
+ xdev->buffer_size = 0;
+ if (!IS_BUFFERED(xdev))
+ return 0;
+ gx_device_set_target((gx_device_forward *)xdev->target, NULL);
+ gx_device_set_target((gx_device_forward *)xdev, NULL);
+ procs = &gs_x11_device.procs;
+ }
+ if (dev_proc(xdev, fill_rectangle) != procs->fill_rectangle) {
+#define COPY_PROC(p) set_dev_proc(xdev, p, procs->p)
+ COPY_PROC(fill_rectangle);
+ COPY_PROC(copy_mono);
+ COPY_PROC(copy_color);
+ COPY_PROC(copy_alpha);
+ COPY_PROC(fill_path);
+ COPY_PROC(stroke_path);
+ COPY_PROC(fill_mask);
+ COPY_PROC(fill_trapezoid);
+ COPY_PROC(fill_parallelogram);
+ COPY_PROC(fill_triangle);
+ COPY_PROC(draw_thin_line);
+ COPY_PROC(strip_tile_rectangle);
+ COPY_PROC(strip_copy_rop);
+ COPY_PROC(begin_typed_image);
+ COPY_PROC(create_compositor);
+ COPY_PROC(text_begin);
+#undef COPY_PROC
+ if (IS_BUFFERED(xdev)) {
+ gx_device_forward_fill_in_procs((gx_device_forward *)xdev);
+ xdev->box_procs = gdev_x_box_procs;
+ xdev->box_proc_data = xdev;
+ } else
+ gx_device_fill_in_procs((gx_device *)xdev);
+ }
+ return 0;
+}
+
/* Allocate the backing pixmap, if any, and clear the window. */
void
gdev_x_clear_window(gx_device_X * xdev)
@@ -505,6 +628,7 @@ gdev_x_clear_window(gx_device_X * xdev)
} else
xdev->bpixmap = (Pixmap) 0;
}
+ x_set_buffer(xdev);
/* Clear the destination pixmap to avoid initializing with garbage. */
if (xdev->dest != (Pixmap) 0) {
XSetForeground(xdev->dpy, xdev->gc, xdev->background);
@@ -593,7 +717,7 @@ get_x11_name(const char **cpp, int *len)
/* Scan one resource and build font map records. */
private void
-scan_font_resource(const char *resource, x11fontmap ** pmaps)
+scan_font_resource(const char *resource, x11fontmap **pmaps, gs_memory_t *mem)
{
const char *ps_name;
const char *x11_name;
@@ -605,27 +729,26 @@ scan_font_resource(const char *resource, x11fontmap ** pmaps)
while ((ps_name = get_ps_name(&cp, &ps_name_len)) != 0) {
x11_name = get_x11_name(&cp, &x11_name_len);
if (x11_name) {
- font = (x11fontmap *) gs_malloc(sizeof(x11fontmap), 1,
- "x11_setup_fontmap");
+ font = gs_alloc_struct(mem, x11fontmap, &st_x11fontmap,
+ "scan_font_resource(font)");
if (font == NULL)
continue;
- font->ps_name = (char *)gs_malloc(sizeof(char), ps_name_len + 1,
- "x11_setup_fontmap");
-
+ font->ps_name = (char *)
+ gs_alloc_byte_array(mem, ps_name_len + 1, sizeof(char),
+ "scan_font_resource(ps_name)");
if (font->ps_name == NULL) {
- gs_free((char *)font, sizeof(x11fontmap), 1, "x11_fontmap");
+ gs_free_object(mem, font, "scan_font_resource(font)");
continue;
}
strncpy(font->ps_name, ps_name, ps_name_len);
font->ps_name[ps_name_len] = '\0';
- font->x11_name = (char *)gs_malloc(sizeof(char), x11_name_len,
- "x11_setup_fontmap");
-
+ font->x11_name = (char *)
+ gs_alloc_byte_array(mem, x11_name_len, sizeof(char),
+ "scan_font_resource(x11_name)");
if (font->x11_name == NULL) {
- gs_free(font->ps_name, sizeof(char), strlen(font->ps_name) + 1,
- "x11_font_psname");
-
- gs_free((char *)font, sizeof(x11fontmap), 1, "x11_fontmap");
+ gs_free_object(mem, font->ps_name,
+ "scan_font_resource(ps_name)");
+ gs_free_object(mem, font, "scan_font_resource(font)");
continue;
}
strncpy(font->x11_name, x11_name, x11_name_len - 1);
@@ -655,7 +778,172 @@ gdev_x_setup_fontmap(gx_device_X * xdev)
if (!xdev->useXFonts)
return; /* If no external fonts, don't bother */
- scan_font_resource(xdev->regularFonts, &xdev->regular_fonts);
- scan_font_resource(xdev->symbolFonts, &xdev->symbol_fonts);
- scan_font_resource(xdev->dingbatFonts, &xdev->dingbat_fonts);
+ scan_font_resource(xdev->regularFonts, &xdev->regular_fonts, xdev->memory);
+ scan_font_resource(xdev->symbolFonts, &xdev->symbol_fonts, xdev->memory);
+ scan_font_resource(xdev->dingbatFonts, &xdev->dingbat_fonts, xdev->memory);
+}
+
+/* ---------------- Get/put parameters ---------------- */
+
+/* Get the device parameters. See below. */
+int
+gdev_x_get_params(gx_device * dev, gs_param_list * plist)
+{
+ gx_device_X *xdev = (gx_device_X *) dev;
+ int code = gx_default_get_params(dev, plist);
+ long id = (long)xdev->pwin;
+
+ if (code < 0 ||
+ (code = param_write_long(plist, "WindowID", &id)) < 0 ||
+ (code = param_write_bool(plist, ".IsPageDevice", &xdev->IsPageDevice)) < 0 ||
+ (code = param_write_long(plist, "MaxBitmap", &xdev->MaxBitmap)) < 0 ||
+ (code = param_write_int(plist, "MaxTempPixmap", &xdev->MaxTempPixmap)) < 0 ||
+ (code = param_write_int(plist, "MaxTempImage", &xdev->MaxTempImage)) < 0 ||
+ (code = param_write_int(plist, "MaxBufferedTotal", &xdev->MaxBufferedTotal)) < 0 ||
+ (code = param_write_int(plist, "MaxBufferedArea", &xdev->MaxBufferedArea)) < 0 ||
+ (code = param_write_int(plist, "MaxBufferedCount", &xdev->MaxBufferedCount)) < 0
+ )
+ DO_NOTHING;
+ return code;
+}
+
+/* Set the device parameters. We reimplement this so we can resize */
+/* the window and avoid closing and reopening the device, and to add */
+/* .IsPageDevice. */
+int
+gdev_x_put_params(gx_device * dev, gs_param_list * plist)
+{
+ gx_device_X *xdev = (gx_device_X *) dev;
+ /*
+ * Provide copies of values of parameters being set:
+ * is_open, width, height, HWResolution, IsPageDevice, Max*.
+ */
+ gx_device_X values;
+
+ long pwin = (long)xdev->pwin;
+ bool save_is_page = xdev->IsPageDevice;
+ int ecode = 0, code;
+
+ values = *xdev;
+
+ /* Handle extra parameters */
+
+ ecode = param_put_long(plist, "WindowID", &pwin, ecode);
+ ecode = param_put_bool(plist, ".IsPageDevice", &values.IsPageDevice, ecode);
+ ecode = param_put_long(plist, "MaxBitmap", &values.MaxBitmap, ecode);
+ ecode = param_put_int(plist, "MaxTempPixmap", &values.MaxTempPixmap, ecode);
+ ecode = param_put_int(plist, "MaxTempImage", &values.MaxTempImage, ecode);
+ ecode = param_put_int(plist, "MaxBufferedTotal", &values.MaxBufferedTotal, ecode);
+ ecode = param_put_int(plist, "MaxBufferedArea", &values.MaxBufferedArea, ecode);
+ ecode = param_put_int(plist, "MaxBufferedCount", &values.MaxBufferedCount, ecode);
+
+ if (ecode < 0)
+ return ecode;
+
+ /* Unless we specified a new window ID, */
+ /* prevent gx_default_put_params from closing the device. */
+ if (pwin == (long)xdev->pwin)
+ dev->is_open = false;
+ xdev->IsPageDevice = values.IsPageDevice;
+ code = gx_default_put_params(dev, plist);
+ dev->is_open = values.is_open; /* saved value */
+ if (code < 0) { /* Undo setting of .IsPageDevice */
+ xdev->IsPageDevice = save_is_page;
+ return code;
+ }
+ if (pwin != (long)xdev->pwin) {
+ if (xdev->is_open)
+ gs_closedevice(dev);
+ xdev->pwin = (Window) pwin;
+ }
+ /****** DO MORE FOR RESETTING MaxBitmap ******/
+ xdev->MaxBitmap = values.MaxBitmap;
+ /* If the device is open, resize the window. */
+ /* Don't do this if Ghostview is active. */
+ if (xdev->is_open && !xdev->ghostview &&
+ (dev->width != values.width || dev->height != values.height ||
+ dev->HWResolution[0] != values.HWResolution[0] ||
+ dev->HWResolution[1] != values.HWResolution[1] ||
+ xdev->MaxBitmap != values.MaxBitmap)
+ ) {
+ int dw = dev->width - values.width;
+ int dh = dev->height - values.height;
+ double qx = dev->HWResolution[0] / values.HWResolution[0];
+ double qy = dev->HWResolution[1] / values.HWResolution[1];
+
+ if (dw || dh) {
+ XResizeWindow(xdev->dpy, xdev->win,
+ dev->width, dev->height);
+ if (xdev->bpixmap != (Pixmap) 0) {
+ XFreePixmap(xdev->dpy, xdev->bpixmap);
+ xdev->bpixmap = (Pixmap) 0;
+ }
+ xdev->dest = 0;
+ }
+ xdev->MaxTempPixmap = values.MaxTempPixmap;
+ xdev->MaxTempImage = values.MaxTempImage;
+ xdev->MaxBufferedTotal = values.MaxBufferedTotal;
+ xdev->MaxBufferedArea = values.MaxBufferedArea;
+ xdev->MaxBufferedCount = values.MaxBufferedCount;
+ if (dw || dh || xdev->MaxBitmap != values.MaxBitmap)
+ gdev_x_clear_window(xdev);
+ /* Attempt to update the initial matrix in a sensible way. */
+ /* The whole handling of the initial matrix is a hack! */
+ if (xdev->initial_matrix.xy == 0) {
+ if (xdev->initial_matrix.xx < 0) { /* 180 degree rotation */
+ xdev->initial_matrix.tx += dw;
+ } else { /* no rotation */
+ xdev->initial_matrix.ty += dh;
+ }
+ } else {
+ if (xdev->initial_matrix.xy < 0) { /* 90 degree rotation */
+ xdev->initial_matrix.tx += dh;
+ xdev->initial_matrix.ty += dw;
+ } else { /* 270 degree rotation */
+ }
+ }
+ xdev->initial_matrix.xx *= qx;
+ xdev->initial_matrix.xy *= qx;
+ xdev->initial_matrix.yx *= qy;
+ xdev->initial_matrix.yy *= qy;
+ }
+ return 0;
+}
+
+/* ---------------- Closing/finalization ---------------- */
+
+/* Free fonts when closing the device. */
+private void
+free_x_fontmaps(x11fontmap **pmaps, gs_memory_t *mem)
+{
+ while (*pmaps) {
+ x11fontmap *font = *pmaps;
+
+ *pmaps = font->next;
+ if (font->std.names)
+ XFreeFontNames(font->std.names);
+ if (font->iso.names)
+ XFreeFontNames(font->iso.names);
+ gs_free_object(mem, font->x11_name, "free_x_fontmaps(x11_name)");
+ gs_free_object(mem, font->ps_name, "free_x_fontmaps(ps_name)");
+ gs_free_object(mem, font, "free_x_fontmaps(font)");
+ }
+}
+
+/* Close the device. */
+int
+gdev_x_close(gx_device_X *xdev)
+{
+ if (xdev->ghostview)
+ gdev_x_send_event(xdev, xdev->DONE);
+ if (xdev->vinfo) {
+ XFree((char *)xdev->vinfo);
+ xdev->vinfo = NULL;
+ }
+ gdev_x_free_colors(xdev);
+ free_x_fontmaps(&xdev->dingbat_fonts, xdev->memory);
+ free_x_fontmaps(&xdev->symbol_fonts, xdev->memory);
+ free_x_fontmaps(&xdev->regular_fonts, xdev->memory);
+ XCloseDisplay(xdev->dpy);
+ return 0;
}
diff --git a/gs/src/gdevxres.c b/gs/src/gdevxres.c
index 5e543da83..00dc4ede9 100644
--- a/gs/src/gdevxres.c
+++ b/gs/src/gdevxres.c
@@ -20,8 +20,8 @@
/* X Windows driver resource tables */
#include "std.h" /* must precede any file that includes <sys/types.h> */
#include "x_.h"
-#include "gx.h"
-#include "gserrors.h"
+#include "gstypes.h"
+#include "gsmemory.h"
#include "gxdevice.h"
#include "gdevx.h"
diff --git a/gs/src/gdevxxf.c b/gs/src/gdevxxf.c
index 675eca66c..5f127402a 100644
--- a/gs/src/gdevxxf.c
+++ b/gs/src/gdevxxf.c
@@ -56,7 +56,7 @@ private const gx_xfont_procs x_xfont_procs =
/* Return the xfont procedure record. */
const gx_xfont_procs *
-x_get_xfont_procs(gx_device * dev)
+gdev_x_get_xfont_procs(gx_device * dev)
{
return &x_xfont_procs;
}
@@ -345,7 +345,7 @@ x_render_char(gx_xfont * xf, gx_xglyph xg, gx_device * dev,
int x, y, w, h;
int code;
- if (dev->dname == gs_x11_device.dname) {
+ if (dev->dname == gs_x11_device.dname && !IS_BUFFERED((gx_device_X *)dev)){
code = (*xf->common.procs->char_metrics) (xf, xg, 0, &wxy, &bbox);
if (code < 0)
return code;
@@ -360,9 +360,9 @@ x_render_char(gx_xfont * xf, gx_xglyph xg, gx_device * dev,
xdev->text.item_count = xdev->text.char_count = 0;
}
if (xdev->text.item_count == 0) {
- set_fill_style(FillSolid);
- set_fore_color(color);
- set_function(GXcopy);
+ X_SET_FILL_STYLE(xdev, FillSolid);
+ X_SET_FORE_COLOR(xdev, color);
+ X_SET_FUNCTION(xdev, GXcopy);
xdev->text.origin.x = xdev->text.x = xo;
xdev->text.origin.y = yo;
xdev->text.items[0].font = xdev->fid = xxf->font->fid;
@@ -398,7 +398,7 @@ x_render_char(gx_xfont * xf, gx_xglyph xg, gx_device * dev,
w = bbox.q.x - bbox.p.x;
h = bbox.q.y - bbox.p.y;
fit_fill(dev, x, y, w, h);
- x_update_add(dev, x, y, w, h);
+ x_update_add(xdev, x, y, w, h);
}
return 0;
} else if (!required)
diff --git a/gs/src/genarch.c b/gs/src/genarch.c
index b6aadb52a..d0b84d7dd 100644
--- a/gs/src/genarch.c
+++ b/gs/src/genarch.c
@@ -23,6 +23,12 @@
#include "stdpre.h"
#include <ctype.h>
#include <stdio.h>
+/*
+ * In theory, not all systems provide <string.h>, or declare memset in
+ * that header file, but at this point I don't think we care about any
+ * that don't.
+ */
+#include <string.h>
#include <time.h>
/* We should write the result on stdout, but the original Turbo C 'make' */
diff --git a/gs/src/genconf.c b/gs/src/genconf.c
index f6f1125e7..fe862e801 100644
--- a/gs/src/genconf.c
+++ b/gs/src/genconf.c
@@ -30,7 +30,7 @@
* (e.g., some Linux versions). Also, this procedure does the right thing
* if old_ptr = NULL.
*/
-void *
+private void *
mrealloc(void *old_ptr, size_t old_size, size_t new_size)
{
void *new_ptr = malloc(new_size);
@@ -163,6 +163,7 @@ bool var_expand(P3(char *, char [MAX_STR], const config *));
void add_definition(P4(const char *, const char *, string_list *, bool));
string_item *lookup(P2(const char *, const string_list *));
+int
main(int argc, char *argv[])
{
config conf;
@@ -396,13 +397,17 @@ process_replaces(config * pconf)
for (tn = 0; tn < count; ++tn) {
if (items[tn].file_index == j) {
- /* Delete the item. Since we haven't sorted the items */
- /* yet, just replace this item with the last one. */
+ /*
+ * Delete the item. Since we haven't sorted
+ * the items yet, just replace this item
+ * with the last one, but make sure we don't
+ * miss scanning it.
+ */
if (pconf->debug)
printf("Replacing %s %s.\n",
pconf->lists.indexed[rn].list_name,
items[tn].str);
- items[tn] = items[--count];
+ items[tn--] = items[--count];
}
}
pconf->lists.indexed[rn].count = count;
@@ -422,7 +427,7 @@ process_replaces(config * pconf)
/* We use the 'index' of the file_contents string_item to record the union */
/* of the uniq_modes of all (direct and indirect) items in the file. */
/* Return the file_contents item for the file. */
-string_item *
+private string_item *
read_file(config * pconf, const char *fname)
{
char *cname = malloc(strlen(fname) + strlen(pconf->file_prefix) + 1);
@@ -570,8 +575,8 @@ pre: sprintf(template, pat, pconf->name_prefix);
break;
case 'e':
if (IS_CAT("emulator")) {
- sprintf(str, "emulator_(\"%s\",%d)",
- item, strlen(item));
+ sprintf(str, "emulator_(\"%s\",%u)",
+ item, (uint)strlen(item));
item = str;
break;
}
@@ -633,8 +638,8 @@ pre: sprintf(template, pat, pconf->name_prefix);
goto err;
case 'p':
if (IS_CAT("ps")) {
- sprintf(str, "psfile_(\"%s.ps\",%d)",
- item, strlen(item) + 3);
+ sprintf(str, "psfile_(\"%s.ps\",%u)",
+ item, (uint)(strlen(item) + 3));
item = str;
break;
}
@@ -695,14 +700,14 @@ add_item(string_list * list, const char *str, int file_index)
/* or the latest (if last = true). */
#define psi1 ((const string_item *)p1)
#define psi2 ((const string_item *)p2)
-int
+private int
cmp_index(const void *p1, const void *p2)
{
int cmp = psi1->index - psi2->index;
return (cmp < 0 ? -1 : cmp > 0 ? 1 : 0);
}
-int
+private int
cmp_str(const void *p1, const void *p2)
{
return strcmp(psi1->str, psi2->str);
diff --git a/gs/src/genht.c b/gs/src/genht.c
index 32ca07a5e..68564a5c1 100644
--- a/gs/src/genht.c
+++ b/gs/src/genht.c
@@ -31,8 +31,6 @@
#include "strimpl.h"
#include "sstring.h"
-extern_gx_device_halftone_list();
-
/*
* This program translates PostScript halftone resources into C data
* structures that can then be compiled into executables and put in shared,
@@ -322,7 +320,6 @@ void
gx_ht_complete_threshold_order(gx_ht_order *porder)
{
}
-const gx_dht_proc gx_device_halftone_list[] = { 0 };
/*
* In order to avoid a linking step, we #include the required files here
@@ -331,3 +328,5 @@ const gx_dht_proc gx_device_halftone_list[] = { 0 };
#include "gxhtbit.c"
#include "scantab.c"
#include "sstring.c"
+
+const gx_dht_proc gx_device_halftone_list[] = { 0 };
diff --git a/gs/src/gp.h b/gs/src/gp.h
index f0f3fab1d..b6d0b62f7 100644
--- a/gs/src/gp.h
+++ b/gs/src/gp.h
@@ -26,12 +26,12 @@
#include "gstypes.h"
/*
* This file defines the interface to ***ALL*** platform-specific routines,
- * with the exception of the thread/synchronization interface (gpsync.h).
- * The routines are implemented in a gp_*.c file specific to each platform.
- * We try very hard to keep this list short!
+ * with the exception of the thread/synchronization interface (gpsync.h)
+ * and getenv (gpgetenv.h). The implementations are in gp_*.c files
+ * specific to each platform. We try very hard to keep this list short!
*/
/*
- * gp_getenv is declared in a separate file, because a few places need it
+ * gp_getenv is declared in a separate file because a few places need it
* and don't want to include any of the other gs definitions.
*/
#include "gpgetenv.h"
@@ -204,24 +204,32 @@ const char *gp_file_name_concat_string(P4(const char *prefix, uint plen,
/* ------ Printer accessing ------ */
/*
- * Open a connection to a printer. A null file name means use the
- * standard printer connected to the machine, if any.
- * If possible, support "|command" for opening an output pipe.
- * Return NULL if the connection could not be opened.
+ * Open a connection to a printer. A null file name means use the standard
+ * printer connected to the machine, if any. Note that this procedure is
+ * called only if the original file name (normally the value of the
+ * OutputFile device parameter) was an ordinary file (not stdout, a pipe, or
+ * other %filedevice%file name): stdout is handled specially, and other
+ * values of filedevice are handled by calling the fopen procedure
+ * associated with that kind of "file".
*
* Note that if the file name is null (0-length), it may be replaced with
* the name of a scratch file.
*/
FILE *gp_open_printer(P2(char fname[gp_file_name_sizeof], int binary_mode));
-/* Close the connection to the printer. */
+/*
+ * Close the connection to the printer. Note that this is only called
+ * if the original file name was an ordinary file (not stdout, a pipe,
+ * or other %filedevice%file name): stdout is handled specially, and other
+ * values of filedevice are handled by calling the fclose procedure
+ * associated with that kind of "file".
+ */
void gp_close_printer(P2(FILE * pfile, const char *fname));
/* ------ File enumeration ------ */
#ifndef file_enum_DEFINED /* also defined in iodev.h */
# define file_enum_DEFINED
-struct file_enum_s; /* opaque to client, defined by implementor */
typedef struct file_enum_s file_enum;
#endif
diff --git a/gs/src/gp_gnrdl.c b/gs/src/gp_gnrdl.c
index e9bb66b59..fea4bf527 100644
--- a/gs/src/gp_gnrdl.c
+++ b/gs/src/gp_gnrdl.c
@@ -16,8 +16,30 @@
all copies.
*/
+/*
+ As of version 5.71, Ghostscript includes an interface to the GNU readline
+ library, as a build-time option. This library is licensed under the GNU
+ General Public License (GPL), not the GNU Library / Lesser General Public
+ License (LGPL). If you build Aladdin Ghostscript with the gnrdline
+ option, which links this library into the executable, the GPL DOES NOT
+ ALLOW YOU TO COPY OR DISTRIBUTE THE RESULT. For example, the GPL forbids
+ you to build a RPM of Aladdin Ghostscript with GNU readline support and
+ put it on a server.
+
+ The GPL does not forbid you to build or use the just-described software,
+ only to copy or distribute it.
+
+ You *are* allowed to distribute the result of linking the GNU readline
+ library into GNU Ghostscript, which is licensed with the GPL.
+
+ If you have questions or opinions about any of the above, please feel free
+ to contact the Free Software Foundation, authors of the GNU licenses, at
+ gnu@gnu.org, and/or Aladdin Enterprises, author of Ghostscript, at
+ ghost@aladdin.com.
+ */
+
-/* GNU readline implementation */
+/* GNU readline interface */
#include "ctype_.h"
#include "string_.h"
#include "malloc_.h"
@@ -27,11 +49,13 @@
#include "ghost.h"
#include "errors.h"
#include "gp.h"
+#include "gscdefs.h" /* for gs_product for GNU test */
#include "gsmalloc.h"
#include "gsmemory.h"
#include "gsstruct.h"
#include "stream.h"
#include "gxiodev.h"
+#include "ialloc.h"
#include "idict.h"
#include "iname.h"
#include "iutil.h"
@@ -129,14 +153,22 @@ gs_readline_complete(char *text, int state)
return NULL;
}
while ((p->c_idx = dict_next(cdict, p->c_idx, eltp)) >= 0) {
- const byte *rname = eltp->value.refs->value.const_bytes;
- uint rlen = eltp->value.refs->tas.rsize >> 2;
-
- if (rname && !strncmp((const char *)rname, text, p->c_len)) {
- char *name = (char *)malloc(rlen + 1);
-
- memcpy(name, rname, rlen);
- name[rlen] = 0;
+ ref rnstr;
+ const byte *nchars;
+ uint nlen;
+
+ if (!r_has_type(eltp, t_name))
+ continue;
+ name_string_ref(eltp, &rnstr);
+ nchars = rnstr.value.const_bytes;
+ nlen = r_size(&rnstr);
+ if (nlen < p->c_len)
+ continue;
+ if (!strncmp((const char *)nchars, text, p->c_len)) {
+ char *name = (char *)malloc(nlen + 1);
+
+ memcpy(name, nchars, nlen);
+ name[nlen] = 0;
return name;
}
}
@@ -213,7 +245,7 @@ rl_show_name_value(int count, int key)
char str[MAX_CVS];
const byte *pchars = (const byte *)str;
uint len;
- int code = obj_cvp(pvref, (byte *)str, MAX_CVS, &len, 1, 0);
+ int code = obj_cvp(pvref, (byte *)str, MAX_CVS, &len, 1, 0, imemory);
putchar('\n');
if (code < 0) {
@@ -250,6 +282,22 @@ int
gp_readline_init(void **preadline_data, gs_memory_t * mem)
{
readline_data_t *p;
+ int i;
+
+ /*
+ * If this package is included in a non-GNU build, warn the user
+ * about the consequences of the GPL.
+ */
+ for (i = strlen(gs_product) - 3; i >= 0; --i)
+ if (!strncmp(gs_product + i, "GNU", 3))
+ break;
+ if (i < 0) {
+ fputs("\n **** WARNING: This program appears to include both the GNU readline\n", stderr);
+ fputs(" **** library and non-GNU-licensed code. This being so, the GNU license\n", stderr);
+ fputs(" **** (COPYLEFT) forbids you to copy or distribute this program.\n", stderr);
+ fputs(" **** See src/gp_gnrdl.c for details.\n\n", stderr);
+ fflush(stderr);
+ }
using_history();
read_history(GS_histfile);
diff --git a/gs/src/gp_iwatc.c b/gs/src/gp_iwatc.c
index 6f6f54539..ab825df34 100644
--- a/gs/src/gp_iwatc.c
+++ b/gs/src/gp_iwatc.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1995, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1991, 1995, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -126,9 +126,9 @@ gp_close_printer(FILE * pfile, const char *fname)
FILE *
gp_open_scratch_file(const char *prefix, char fname[gp_file_name_sizeof],
const char *mode)
-{ /* Unfortunately, Watcom C doesn't provide mktemp, */
+{
+ /* Unfortunately, Watcom C doesn't provide mktemp, */
/* so we have to simulate it ourselves. */
- char *temp;
struct stat fst;
char *end;
@@ -137,19 +137,13 @@ gp_open_scratch_file(const char *prefix, char fname[gp_file_name_sizeof],
if (gp_getenv("TEMP", fname, &len) != 0)
*fname = 0;
- else {
- char last = '\\';
- char *temp;
-
- /* Prevent X's in path from being converted by mktemp. */
- for (temp = fname; *temp; temp++)
- *temp = last = tolower(*temp);
- switch (last) {
- default:
- strcat(fname, "\\");
- case ':':
- case '\\':
- ;
+ else if (*fname) {
+ switch (fname[strlen(fname) - 1]) {
+ default:
+ strcat(fname, "\\");
+ case ':':
+ case '\\':
+ ;
}
}
strcat(fname, prefix);
diff --git a/gs/src/gp_mshdl.c b/gs/src/gp_mshdl.c
new file mode 100644
index 000000000..f0979a1e0
--- /dev/null
+++ b/gs/src/gp_mshdl.c
@@ -0,0 +1,122 @@
+/* Copyright (C) 1999 Aladdin Enterprises. All rights reserved.
+
+ This file is part of Aladdin Ghostscript.
+
+ Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
+ or distributor accepts any responsibility for the consequences of using it,
+ or for whether it serves any particular purpose or works at all, unless he
+ or she says so in writing. Refer to the Aladdin Ghostscript Free Public
+ License (the "License") for full details.
+
+ Every copy of Aladdin Ghostscript must include a copy of the License,
+ normally in a plain ASCII text file named PUBLIC. The License grants you
+ the right to copy, modify and redistribute Aladdin Ghostscript, but only
+ under certain conditions described in the License. Among other things, the
+ License requires that the copyright notice and this notice be preserved on
+ all copies.
+ */
+
+
+/* %handle% IODevice */
+#include "errno_.h"
+#include "stdio_.h"
+#include "string_.h"
+#include "ctype_.h"
+#include <io.h>
+#include "gserror.h"
+#include "gstypes.h"
+#include "gsmemory.h" /* for gxiodev.h */
+#include "gxiodev.h"
+
+/* The MS-Windows handle IODevice */
+
+/* This allows an MS-Windows file handle to be passed in to
+ * Ghostscript as %handle%NNNNNNNN where NNNNNNNN is the hexadecimal
+ * value of the handle.
+ * The typical use is for another program to create a pipe,
+ * pass the write end into Ghostscript using
+ * -sOutputFile="%handle%NNNNNNNN"
+ * so that Ghostscript printer output can be captured by the
+ * other program. The handle would be created with CreatePipe().
+ * If Ghostscript is not a DLL, the pipe will have to be inheritable
+ * by the Ghostscript process.
+ */
+
+private iodev_proc_fopen(mswin_handle_fopen);
+private iodev_proc_fclose(mswin_handle_fclose);
+const gx_io_device gs_iodev_handle = {
+ "%handle%", "FileSystem",
+ {iodev_no_init, iodev_no_open_device,
+ NULL /*iodev_os_open_file */ , mswin_handle_fopen, mswin_handle_fclose,
+ iodev_no_delete_file, iodev_no_rename_file, iodev_no_file_status,
+ iodev_no_enumerate_files, NULL, NULL,
+ iodev_no_get_params, iodev_no_put_params
+ }
+};
+
+/* The file device procedures */
+#ifndef INVALID_HANDLE_VALUE
+#define INVALID_HANDLE_VALUE (-1)
+#endif
+
+/* Allow printer filename specified by -sOutputFile="..."
+ * to contain a hexadecimal encoded OS file handle in the
+ * form -sOutputFile="\\handle\\000001c5"
+ *
+ * Returns:
+ * The OS file handle on success.
+ * INVALID_HANDLE_VALUE on failure.
+ *
+ * This allows the caller to create an OS pipe and give us a
+ * handle to the write end of the pipe.
+ * If we are called as an EXE, the OS file handle must be
+ * inherited by Ghostscript.
+ * Pipes aren't supported under Win32s.
+ */
+private long
+get_os_handle(const char *name)
+{
+ ulong hfile; /* This must be as long as the longest handle. */
+ /* This is correct for Win32, maybe wrong for Win64. */
+ int i, ch;
+
+ for (i = 0; (ch = name[i]) != 0; ++i)
+ if (!isxdigit(ch))
+ return (long)INVALID_HANDLE_VALUE;
+ if (sscanf(name, "%lx", &hfile) != 1)
+ return (long)INVALID_HANDLE_VALUE;
+ return (long)hfile;
+}
+
+private int
+mswin_handle_fopen(gx_io_device * iodev, const char *fname, const char *access,
+ FILE ** pfile, char *rfname, uint rnamelen)
+{
+ int fd;
+ long hfile; /* Correct for Win32, may be wrong for Win64 */
+ errno = 0;
+
+ if ((hfile = get_os_handle(fname)) == (long)INVALID_HANDLE_VALUE)
+ return_error(gs_fopen_errno_to_code(EBADF));
+
+ /* associate a C file handle with an OS file handle */
+ fd = _open_osfhandle((long)hfile, 0);
+ if (fd == -1)
+ return_error(gs_fopen_errno_to_code(EBADF));
+
+ /* associate a C file stream with C file handle */
+ *pfile = fdopen(fd, (char *)access);
+ if (*pfile == NULL)
+ return_error(gs_fopen_errno_to_code(errno));
+
+ if (rfname != NULL)
+ strcpy(rfname, fname);
+ return 0;
+}
+
+private int
+mswin_handle_fclose(gx_io_device * iodev, FILE * file)
+{
+ fclose(file);
+ return 0;
+}
diff --git a/gs/src/gp_msio.c b/gs/src/gp_msio.c
index 1049939ed..1b1f4ed99 100644
--- a/gs/src/gp_msio.c
+++ b/gs/src/gp_msio.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1992, 1995, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1992, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -29,7 +29,17 @@
/* Factored out from gp_mswin.c by JD 6/25/97 */
+/*
+ * The MSVC compiler, when invoked with the /MD switch, considers that the
+ * dllimport qualifier on fprintf in stdio.h and the dllexport qualifier
+ * on the definition of fprintf in this file are incompatible.
+ * We use a hack (similar to the one in stdpre.h to deal with sys/types.h)
+ * to work around this.
+ */
+#define fprintf UNDEFINE_fprintf
#include "stdio_.h"
+#undef fprintf
+
#include <stdlib.h>
#include "gx.h"
#include "gp.h"
@@ -79,13 +89,12 @@ win_stdio_init(gx_io_device * iodev, gs_memory_t * mem)
/* Define alternate 'open' routines for our stdin/out/err streams. */
-extern int iodev_stdin_open(P4(gx_io_device *, const char *, stream **,
- gs_memory_t *));
+extern const gx_io_device gs_iodev_stdin;
private int
win_stdin_open(gx_io_device * iodev, const char *access, stream ** ps,
gs_memory_t * mem)
{
- int code = iodev_stdin_open(iodev, access, ps, mem);
+ int code = gs_iodev_stdin.procs.open_device(iodev, access, ps, mem);
stream *s = *ps;
if (code != 1)
@@ -96,13 +105,12 @@ win_stdin_open(gx_io_device * iodev, const char *access, stream ** ps,
return 0;
}
-extern int iodev_stdout_open(P4(gx_io_device *, const char *, stream **,
- gs_memory_t *));
+extern const gx_io_device gs_iodev_stdout;
private int
win_stdout_open(gx_io_device * iodev, const char *access, stream ** ps,
gs_memory_t * mem)
{
- int code = iodev_stdout_open(iodev, access, ps, mem);
+ int code = gs_iodev_stdout.procs.open_device(iodev, access, ps, mem);
stream *s = *ps;
if (code != 1)
@@ -113,13 +121,12 @@ win_stdout_open(gx_io_device * iodev, const char *access, stream ** ps,
return 0;
}
-extern int iodev_stderr_open(P4(gx_io_device *, const char *, stream **,
- gs_memory_t *));
+extern const gx_io_device gs_iodev_stderr;
private int
win_stderr_open(gx_io_device * iodev, const char *access, stream ** ps,
gs_memory_t * mem)
{
- int code = iodev_stderr_open(iodev, access, ps, mem);
+ int code = gs_iodev_stderr.procs.open_device(iodev, access, ps, mem);
stream *s = *ps;
if (code != 1)
diff --git a/gs/src/gp_mswin.c b/gs/src/gp_mswin.c
index 46ae109bb..44beced42 100644
--- a/gs/src/gp_mswin.c
+++ b/gs/src/gp_mswin.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1992, 1995, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1992, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -359,8 +359,8 @@ private int gp_printfile_win32(const char *filename, char *port);
/* Win32s: Pass to Win16 spooler via gs16spl.exe */
private int gp_printfile_gs16spl(const char *filename, const char *port);
-
-/* valid values for pmport are:
+/*
+ * Valid values for pmport are:
* ""
* action: WinNT and Win95 use default queue, Win32s prompts for port
* "LPT1:" (or other port that appears in win.ini [ports]
@@ -373,8 +373,8 @@ private int gp_printfile_gs16spl(const char *filename, const char *port);
* action: prompt for queue name then send to printer using
* WritePrinter (WinNT and Win95).
* action: prompt for port then use gs16spl.exe (Win32s).
- *
- /* Print File */
+ */
+/* Print File */
private int
gp_printfile(const char *filename, const char *pmport)
{
diff --git a/gs/src/gp_os2.c b/gs/src/gp_os2.c
index 3da014af7..34b1ea766 100644
--- a/gs/src/gp_os2.c
+++ b/gs/src/gp_os2.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1992, 1995, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1992, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -819,13 +819,12 @@ pm_std_read_reset(stream * s)
/* Define alternate 'open' routines for our stdin/out/err streams. */
-extern int iodev_stdin_open(P4(gx_io_device *, const char *, stream **,
- gs_memory_t *));
+extern const gx_io_device gs_iodev_stdin;
private int
pm_stdin_open(gx_io_device * iodev, const char *access, stream ** ps,
gs_memory_t * mem)
{
- int code = iodev_stdin_open(iodev, access, ps, mem);
+ int code = gs_iodev_stdin.procs.open_device(iodev, access, ps, mem);
stream *s = *ps;
if (code != 1)
@@ -837,13 +836,12 @@ pm_stdin_open(gx_io_device * iodev, const char *access, stream ** ps,
return 0;
}
-extern int iodev_stdout_open(P4(gx_io_device *, const char *, stream **,
- gs_memory_t *));
+extern const gx_io_device gs_iodev_stdout;
private int
pm_stdout_open(gx_io_device * iodev, const char *access, stream ** ps,
gs_memory_t * mem)
{
- int code = iodev_stdout_open(iodev, access, ps, mem);
+ int code = gs_iodev_stdout.procs.open_device(iodev, access, ps, mem);
stream *s = *ps;
if (code != 1)
@@ -854,13 +852,12 @@ pm_stdout_open(gx_io_device * iodev, const char *access, stream ** ps,
return 0;
}
-extern int iodev_stderr_open(P4(gx_io_device *, const char *, stream **,
- gs_memory_t *));
+extern const gx_io_device gs_iodev_stderr;
private int
pm_stderr_open(gx_io_device * iodev, const char *access, stream ** ps,
gs_memory_t * mem)
{
- int code = iodev_stderr_open(iodev, access, ps, mem);
+ int code = gs_iodev_stderr.procs.open_device(iodev, access, ps, mem);
stream *s = *ps;
if (code != 1)
diff --git a/gs/src/gp_unix.c b/gs/src/gp_unix.c
index ff2df3ecc..300ad610f 100644
--- a/gs/src/gp_unix.c
+++ b/gs/src/gp_unix.c
@@ -141,19 +141,16 @@ gp_getenv_display(void)
/* ------ Printer accessing ------ */
-/* Open a connection to a printer. A null file name means use the */
-/* standard printer connected to the machine, if any. */
-/* "|command" opens an output pipe. */
-/* Return NULL if the connection could not be opened. */
+/* Open a connection to a printer. See gp.h for details. */
FILE *
gp_open_printer(char fname[gp_file_name_sizeof], int binary_mode)
{
+ const char *fmode = (binary_mode ? "wb" : "w");
+
return
(strlen(fname) == 0 ?
- gp_open_scratch_file(gp_scratch_file_name_prefix, fname, "w") :
- fname[0] == '|' ?
- popen(fname + 1, "w") :
- fopen(fname, "w"));
+ gp_open_scratch_file(gp_scratch_file_name_prefix, fname, fmode) :
+ fopen(fname, fmode));
}
/* Close the connection to the printer. */
diff --git a/gs/src/gpcheck.h b/gs/src/gpcheck.h
index fb896754a..60744aef8 100644
--- a/gs/src/gpcheck.h
+++ b/gs/src/gpcheck.h
@@ -35,11 +35,10 @@
* a symbol CHECK_INTERRUPTS. Currently this is only the Microsoft
* Windows platform.
*/
+int gs_return_check_interrupt(P1(int code));
#ifdef CHECK_INTERRUPTS
int gp_check_interrupts(P0());
-int gs_return_check_interrupt(P1(int code));
-
# define process_interrupts() discard(gp_check_interrupts())
# define return_if_interrupt()\
{ int icode_ = gp_check_interrupts();\
diff --git a/gs/src/gs.mak b/gs/src/gs.mak
index 6e3ea09f9..e72401409 100644
--- a/gs/src/gs.mak
+++ b/gs/src/gs.mak
@@ -293,15 +293,15 @@ ADDMOD=$(EXP)$(ECHOGS_XE) -e .dev -a- $(NULL)
# because this must include $(GLSRCDIR), which isn't defined yet.
JI_=$(JSRCDIR)
JF_=
-JCF_=$(D_)SHARE_JPEG=$(SHARE_JPEG)
+JCF_=$(D_)SHARE_JPEG=$(SHARE_JPEG)$(_D)
PI_=$(PSRCDIR) $(II)$(ZSRCDIR)
# PF_ should include PNG_USE_CONST, but this doesn't work.
#PF_=-DPNG_USE_CONST
PF_=
-PCF_=$(D_)SHARE_LIBPNG=$(SHARE_LIBPNG)
+PCF_=$(D_)SHARE_LIBPNG=$(SHARE_LIBPNG)$(_D)
ZI_=$(ZSRCDIR)
ZF_=
-ZCF_=$(D_)SHARE_ZLIB=$(SHARE_ZLIB)
+ZCF_=$(D_)SHARE_ZLIB=$(SHARE_ZLIB)$(_D)
######################## How to define new 'features' #######################
#
diff --git a/gs/src/gsalloc.c b/gs/src/gsalloc.c
index 01d11b807..4c22cbd57 100644
--- a/gs/src/gsalloc.c
+++ b/gs/src/gsalloc.c
@@ -30,7 +30,7 @@
* This allocator produces tracing messages of the form
* [aNMOTS]...
* where
- * N is the VM space number,
+ * N is the VM space number, +1 if we are allocating from stable memory.
* M is : for movable objects, | for immovable,
* O is {alloc = +, free = -, grow = >, shrink = <},
* T is {bytes = b, object = <, ref = $, string = >}, and
@@ -38,12 +38,17 @@
* own chunk = L, lost = #, lost own chunk = ~, other = .}.
*/
#ifdef DEBUG
+private int
+alloc_trace_space(const gs_ref_memory_t *imem)
+{
+ return imem->space + (imem->stable_memory == (gs_memory_t *)imem);
+}
private void
alloc_trace(const char *chars, gs_ref_memory_t * imem, client_name_t cname,
gs_memory_type_ptr_t stype, uint size, const void *ptr)
{
if_debug7('A', "[a%d%s]%s %s(%u) %s0x%lx\n",
- imem->space, chars, client_name_string(cname),
+ alloc_trace_space(imem), chars, client_name_string(cname),
(ptr == 0 || stype == 0 ? "" :
struct_type_name_string(stype)),
size, (chars[1] == '+' ? "= " : ""), (ulong) ptr);
@@ -71,13 +76,11 @@ alloc_size_is_ok(gs_memory_type_ptr_t stype)
* are allocated outside GC space, they reference objects within it.
*/
public_st_ref_memory();
-#define mptr ((gs_ref_memory_t *)vptr)
private
ENUM_PTRS_BEGIN(ref_memory_enum_ptrs) return 0;
-
ENUM_PTR3(0, gs_ref_memory_t, streams, changes, saved);
ENUM_PTRS_END
-private RELOC_PTRS_BEGIN(ref_memory_reloc_ptrs)
+private RELOC_PTRS_WITH(ref_memory_reloc_ptrs, gs_ref_memory_t *mptr)
{
RELOC_PTR(gs_ref_memory_t, streams);
RELOC_PTR(gs_ref_memory_t, changes);
@@ -102,7 +105,7 @@ private obj_header_t *scavenge_low_free(P2(gs_ref_memory_t *mem, unsigned reques
private ulong compute_free_objects(P1(gs_ref_memory_t *));
private obj_header_t *alloc_obj(P5(gs_ref_memory_t *, ulong, gs_memory_type_ptr_t, alloc_flags_t, client_name_t));
private void consolidate_chunk_free(P2(chunk_t *cp, gs_ref_memory_t *mem));
-private void trim_obj(P3(gs_ref_memory_t *mem, obj_header_t *obj, uint size));
+private void trim_obj(P4(gs_ref_memory_t *mem, obj_header_t *obj, uint size, chunk_t *cp));
private chunk_t *alloc_acquire_chunk(P4(gs_ref_memory_t *, ulong, bool, client_name_t));
private chunk_t *alloc_add_chunk(P3(gs_ref_memory_t *, ulong, client_name_t));
void alloc_close_chunk(P1(gs_ref_memory_t *));
@@ -115,6 +118,7 @@ void alloc_close_chunk(P1(gs_ref_memory_t *));
private gs_memory_proc_alloc_bytes(i_alloc_bytes_immovable);
private gs_memory_proc_resize_object(i_resize_object);
private gs_memory_proc_free_object(i_free_object);
+private gs_memory_proc_stable(i_stable);
private gs_memory_proc_status(i_status);
private gs_memory_proc_free_all(i_free_all);
private gs_memory_proc_consolidate_free(i_consolidate_free);
@@ -144,6 +148,7 @@ const gs_memory_procs_t gs_ref_memory_procs =
i_alloc_bytes_immovable,
i_resize_object,
i_free_object,
+ i_stable,
i_status,
i_free_all,
i_consolidate_free,
@@ -180,6 +185,7 @@ ialloc_alloc_state(gs_raw_memory_t * parent, uint chunk_size)
if (iimem == 0)
return 0;
+ iimem->stable_memory = (gs_memory_t *)iimem;
iimem->procs = gs_ref_memory_procs;
iimem->parent = parent;
iimem->chunk_size = chunk_size;
@@ -197,6 +203,9 @@ ialloc_alloc_state(gs_raw_memory_t * parent, uint chunk_size)
iimem->cc.cbot = iimem->cc.ctop = 0;
iimem->cc.int_freed_top = iimem->cc.cbase;
iimem->pcc = 0;
+ iimem->save_level = 0;
+ iimem->new_mask = 0;
+ iimem->test_mask = ~0;
iimem->streams = 0;
iimem->roots = 0;
iimem->num_contexts = 0;
@@ -229,7 +238,7 @@ ialloc_solo(gs_raw_memory_t * parent, gs_memory_type_ptr_t pstype,
cp->cbot = cp->ctop;
cp->cprev = cp->cnext = 0;
/* Construct the object header "by hand". */
- obj->o_large = 0;
+ obj->o_alone = 1;
obj->o_size = pstype->ssize;
obj->o_type = pstype;
*pcp = cp;
@@ -451,7 +460,7 @@ gs_memory_set_gc_status(gs_ref_memory_t * mem, const gs_memory_gc_status_t * pst
size < imem->large_size\
)\
{ imem->cc.cbot = (byte *)ptr + obj_size_round(size);\
- ptr->o_large = 0;\
+ ptr->o_alone = 0;\
ptr->o_size = size;\
ptr->o_type = pstype;\
ptr++;\
@@ -543,7 +552,7 @@ i_alloc_byte_array(gs_memory_t * mem, uint num_elements, uint elt_size,
&st_bytes, ALLOC_DIRECT, cname);
if_debug6('A', "[a%d:+b.]%s -bytes-*(%lu=%u*%u) = 0x%lx\n",
- imem->space, client_name_string(cname),
+ alloc_trace_space(imem), client_name_string(cname),
(ulong) num_elements * elt_size,
num_elements, elt_size, (ulong) obj);
return (byte *) obj;
@@ -558,7 +567,7 @@ i_alloc_byte_array_immovable(gs_memory_t * mem, uint num_elements,
cname);
if_debug6('A', "[a%d|+b.]%s -bytes-*(%lu=%u*%u) = 0x%lx\n",
- imem->space, client_name_string(cname),
+ alloc_trace_space(imem), client_name_string(cname),
(ulong) num_elements * elt_size,
num_elements, elt_size, (ulong) obj);
return (byte *) obj;
@@ -575,8 +584,8 @@ i_alloc_struct_array(gs_memory_t * mem, uint num_elements,
(ulong) num_elements * pstype->ssize,
pstype, ALLOC_DIRECT, cname);
if_debug7('A', "[a%d:+<.]%s %s*(%lu=%u*%u) = 0x%lx\n",
- imem->space,
- client_name_string(cname), struct_type_name_string(pstype),
+ alloc_trace_space(imem), client_name_string(cname),
+ struct_type_name_string(pstype),
(ulong) num_elements * pstype->ssize,
num_elements, pstype->ssize, (ulong) obj);
return (char *)obj;
@@ -593,8 +602,8 @@ i_alloc_struct_array_immovable(gs_memory_t * mem, uint num_elements,
(ulong) num_elements * pstype->ssize,
pstype, ALLOC_IMMOVABLE | ALLOC_DIRECT, cname);
if_debug7('A', "[a%d|+<.]%s %s*(%lu=%u*%u) = 0x%lx\n",
- imem->space,
- client_name_string(cname), struct_type_name_string(pstype),
+ alloc_trace_space(imem), client_name_string(cname),
+ struct_type_name_string(pstype),
(ulong) num_elements * pstype->ssize,
num_elements, pstype->ssize, (ulong) obj);
return (char *)obj;
@@ -621,12 +630,12 @@ i_resize_object(gs_memory_t * mem, void *obj, uint new_num_elements,
new_obj = obj;
} else /* try and trim the object -- but only if room for a dummy header */
if (new_size_rounded + sizeof(obj_header_t) <= old_size_rounded) {
- trim_obj(imem, obj, new_size_rounded);
+ trim_obj(imem, obj, new_size_rounded, (chunk_t *)0);
new_obj = obj;
}
if (new_obj) {
if_debug8('A', "[a%d:%c%c ]%s %s(%lu=>%lu) 0x%lx\n",
- imem->space,
+ alloc_trace_space(imem),
(new_size > old_size ? '>' : '<'),
(pstype == &st_bytes ? 'b' : '<'),
client_name_string(cname),
@@ -715,7 +724,7 @@ i_free_object(gs_memory_t * mem, void *ptr, client_name_t cname)
}
return;
}
- if (pp->o_large) {
+ if (pp->o_alone) {
/*
* We gave this object its own chunk. Free the entire chunk,
* unless it belongs to an older save level, in which case
@@ -783,8 +792,8 @@ i_alloc_string(gs_memory_t * mem, uint nbytes, client_name_t cname)
byte *str;
top:if (imem->cc.ctop - imem->cc.cbot > nbytes) {
- if_debug4('A', "[a%d:+> ]%s(%u) = 0x%lx\n", imem->space,
- client_name_string(cname), nbytes,
+ if_debug4('A', "[a%d:+> ]%s(%u) = 0x%lx\n",
+ alloc_trace_space(imem), client_name_string(cname), nbytes,
(ulong) (imem->cc.ctop - nbytes));
str = imem->cc.ctop -= nbytes;
gs_alloc_fill(str, gs_alloc_fill_alloc, nbytes);
@@ -824,8 +833,9 @@ i_alloc_string_immovable(gs_memory_t * mem, uint nbytes, client_name_t cname)
if (cp == 0)
return 0;
str = cp->ctop = cp->climit - nbytes;
- if_debug4('a', "[a%d|+>L]%s(%u) = 0x%lx\n", imem->space,
- client_name_string(cname), nbytes, (ulong) str);
+ if_debug4('a', "[a%d|+>L]%s(%u) = 0x%lx\n",
+ alloc_trace_space(imem), client_name_string(cname), nbytes,
+ (ulong) str);
gs_alloc_fill(str, gs_alloc_fill_alloc, nbytes);
return str;
}
@@ -844,7 +854,8 @@ i_resize_string(gs_memory_t * mem, byte * data, uint old_num, uint new_num,
) { /* Resize in place. */
ptr = data + old_num - new_num;
if_debug6('A', "[a%d:%c> ]%s(%u->%u) 0x%lx\n",
- imem->space, (new_num > old_num ? '>' : '<'),
+ alloc_trace_space(imem),
+ (new_num > old_num ? '>' : '<'),
client_name_string(cname), old_num, new_num,
(ulong) ptr);
imem->cc.ctop = ptr;
@@ -864,7 +875,7 @@ i_resize_string(gs_memory_t * mem, byte * data, uint old_num, uint new_num,
gs_alloc_fill(data + new_num, gs_alloc_fill_free,
old_num - new_num);
if_debug5('A', "[a%d:<> ]%s(%u->%u) 0x%lx\n",
- imem->space, client_name_string(cname),
+ alloc_trace_space(imem), client_name_string(cname),
old_num, new_num, (ulong)ptr);
} else { /* Punt. */
ptr = gs_alloc_string(mem, new_num, cname);
@@ -882,17 +893,25 @@ i_free_string(gs_memory_t * mem, byte * data, uint nbytes,
{
gs_ref_memory_t * const imem = (gs_ref_memory_t *)mem;
if (data == imem->cc.ctop) {
- if_debug4('A', "[a%d:-> ]%s(%u) 0x%lx\n", imem->space,
- client_name_string(cname), nbytes, (ulong) data);
+ if_debug4('A', "[a%d:-> ]%s(%u) 0x%lx\n",
+ alloc_trace_space(imem), client_name_string(cname), nbytes,
+ (ulong) data);
imem->cc.ctop += nbytes;
} else {
- if_debug4('A', "[a%d:->#]%s(%u) 0x%lx\n", imem->space,
- client_name_string(cname), nbytes, (ulong) data);
+ if_debug4('A', "[a%d:->#]%s(%u) 0x%lx\n",
+ alloc_trace_space(imem), client_name_string(cname), nbytes,
+ (ulong) data);
imem->lost.strings += nbytes;
}
gs_alloc_fill(data, gs_alloc_fill_free, nbytes);
}
+private gs_memory_t *
+i_stable(gs_memory_t *mem)
+{
+ return mem->stable_memory;
+}
+
private void
i_status(gs_memory_t * mem, gs_memory_status_t * pstat)
{
@@ -988,9 +1007,9 @@ large_freelist_alloc(gs_ref_memory_t *mem, uint size)
/* Remove from freelist & return excess memory to free */
*best_fit_prev = *(obj_header_t **)best_fit;
- trim_obj(mem, best_fit, aligned_size);
+ trim_obj(mem, best_fit, aligned_size, (chunk_t *)0);
- /* Pre-init block header; o_large & o_type are already init'd */
+ /* Pre-init block header; o_alone & o_type are already init'd */
best_fit[-1].o_size = size;
return best_fit;
@@ -1015,12 +1034,20 @@ alloc_obj(gs_ref_memory_t *mem, ulong lsize, gs_memory_type_ptr_t pstype,
alloc_acquire_chunk(mem, asize + sizeof(chunk_head_t), false,
"large object chunk");
+ if (
+#if arch_sizeof_long > arch_sizeof_int
+ asize > max_uint
+#else
+ asize < lsize
+#endif
+ )
+ return 0;
if (cp == 0)
return 0;
ptr = (obj_header_t *) cp->cbot;
cp->cbot += asize;
- ptr->o_large = 1;
- pre_obj_set_large_size(ptr, lsize);
+ ptr->o_alone = 1;
+ ptr->o_size = lsize;
} else if (lsize > max_freelist_size && (flags & ALLOC_DIRECT) &&
(ptr = large_freelist_alloc(mem, lsize)) != 0) {
/* We hadn't checked the large block freelist yet. */
@@ -1061,7 +1088,7 @@ alloc_obj(gs_ref_memory_t *mem, ulong lsize, gs_memory_type_ptr_t pstype,
else if (!mem->is_controlled ||
(ptr = scavenge_low_free(mem, (uint)lsize)) == 0)
return 0; /* allocation failed */
- ptr->o_large = 0;
+ ptr->o_alone = 0;
ptr->o_size = (uint) lsize;
}
done:
@@ -1184,7 +1211,7 @@ scavenge_low_free(gs_ref_memory_t *mem, unsigned request_size)
found_pre->o_size = found_free - sizeof(obj_header_t);
/* Chop off excess tail piece & toss it back into free pool */
- trim_obj(mem, found_pre + 1, request_size);
+ trim_obj(mem, found_pre + 1, request_size, cp);
}
}
return found_pre;
@@ -1219,42 +1246,71 @@ remove_range_from_freelist(gs_ref_memory_t *mem, void* bottom, void* top)
/* Trim a memory object down to a given size */
private void
-trim_obj(gs_ref_memory_t *mem, obj_header_t *obj, uint size)
+trim_obj(gs_ref_memory_t *mem, obj_header_t *obj, uint size, chunk_t *cp)
/* Obj must have rounded size == req'd size, or have enough room for */
/* trailing dummy obj_header */
{
uint rounded_size = obj_align_round(size);
obj_header_t *pre_obj = obj - 1;
obj_header_t *excess_pre = (obj_header_t*)((char*)obj + rounded_size);
- uint excess_size =
- obj_align_round(pre_obj->o_size) - rounded_size - sizeof(obj_header_t);
+ uint old_rounded_size = obj_align_round(pre_obj->o_size);
+ uint excess_size = old_rounded_size - rounded_size - sizeof(obj_header_t);
/* trim object's size to desired */
- if (obj_align_round(pre_obj->o_size) == rounded_size)
+ if (old_rounded_size == rounded_size)
return; /* nothing to do here */
pre_obj->o_size = size;
-
+ /*
+ * If the object is alone in its chunk, move ctop to point to the end
+ * of the object.
+ */
+ if (pre_obj->o_alone) {
+ if (!cp) {
+ mem->cfreed.memory = mem;
+ if (chunk_locate(obj, &mem->cfreed)) {
+ cp = mem->cfreed.cp;
+ }
+ }
+ if (cp) {
+#ifdef DEBUG
+ if (cp->ctop != (byte *)obj + old_rounded_size) {
+ lprintf3("resizing 0x%lx, old size %u, new size %u, ctop wrong!\n",
+ (ulong)obj, old_rounded_size, size);
+ /* gs_abort */
+ } else
+#endif
+ {
+ cp->ctop = (byte *)excess_pre;
+ return;
+ }
+ }
+ /*
+ * Something very weird is going on. This probably shouldn't
+ * ever happen, but if it does....
+ */
+ pre_obj->o_alone = 0;
+ }
/* make excess into free obj */
excess_pre->o_type = &st_free; /* don't confuse GC */
excess_pre->o_size = excess_size;
- excess_pre->o_large = 0;
+ excess_pre->o_alone = 0;
if (excess_size >= obj_align_mod) {
- /* Put excess object on a freelist */
- obj_header_t **pfl;
+ /* Put excess object on a freelist */
+ obj_header_t **pfl;
if ((byte *)excess_pre >= mem->cc.int_freed_top)
mem->cc.int_freed_top = (byte *)excess_pre + excess_size;
if (excess_size <= max_freelist_size)
- pfl = &mem->freelists[(excess_size + obj_align_mask) >>
- log2_obj_align_mod];
+ pfl = &mem->freelists[(excess_size + obj_align_mask) >>
+ log2_obj_align_mod];
else
pfl = &mem->freelists[LARGE_FREELIST_INDEX];
- *(obj_header_t **) (excess_pre + 1) = *pfl;
- *pfl = excess_pre + 1;
- mem->cfreed.memory = mem;
+ *(obj_header_t **) (excess_pre + 1) = *pfl;
+ *pfl = excess_pre + 1;
+ mem->cfreed.memory = mem;
} else {
- /* excess piece will be "lost" memory */
- mem->lost.objects += excess_size + sizeof(obj_header_t);
+ /* excess piece will be "lost" memory */
+ mem->lost.objects += excess_size + sizeof(obj_header_t);
}
}
@@ -1457,7 +1513,7 @@ alloc_close_chunk(gs_ref_memory_t * mem)
*mem->pcc = mem->cc;
#ifdef DEBUG
if (gs_debug_c('a')) {
- dlprintf1("[a%d]", mem->space);
+ dlprintf1("[a%d]", alloc_trace_space(mem));
dprintf_chunk("closing chunk", mem->pcc);
}
#endif
@@ -1472,7 +1528,7 @@ alloc_open_chunk(gs_ref_memory_t * mem)
mem->cc = *mem->pcc;
#ifdef DEBUG
if (gs_debug_c('a')) {
- dlprintf1("[a%d]", mem->space);
+ dlprintf1("[a%d]", alloc_trace_space(mem));
dprintf_chunk("opening chunk", mem->pcc);
}
#endif
@@ -1576,7 +1632,7 @@ chunk_locate_ptr(const void *ptr, chunk_locator_t * clp)
return !ptr_is_in_inner_chunk(ptr, cp);
}
-/* ------ Debugging printout ------ */
+/* ------ Debugging ------ */
#ifdef DEBUG
@@ -1703,10 +1759,7 @@ debug_print_object(const void *obj, const dump_control_t * control)
;
}
if (options & dump_do_marks) {
- if (pre->o_large)
- dprintf1(" lmark=%d", pre->o_lmark);
- else
- dprintf2(" smark/back=%u (0x%x)", pre->o_smark, pre->o_smark);
+ dprintf2(" smark/back=%u (0x%x)", pre->o_smark, pre->o_smark);
}
dputc('\n');
if (type == &st_free)
@@ -1714,18 +1767,15 @@ debug_print_object(const void *obj, const dump_control_t * control)
if (options & dump_do_pointers) {
struct_proc_enum_ptrs((*proc)) = type->enum_ptrs;
uint index = 0;
- const void *ptr;
+ enum_ptr_t eptr;
gs_ptr_type_t ptype;
- /*
- * NOTE: the following cast should be unnecessary, but that
- * will require adding 'const' to the first prototype argument
- * of struct_proc_enum_ptrs.
- */
if (proc != gs_no_struct_enum_ptrs)
- for (; (ptype = (*proc) ((obj_header_t *) pre + 1, size, index, &ptr, type, NULL)) != 0;
+ for (; (ptype = (*proc)(pre + 1, size, index, &eptr, type, NULL)) != 0;
++index
) {
+ const void *ptr = eptr.ptr;
+
dprintf1(" ptr %u: ", index);
if (ptype == ptr_string_type || ptype == ptr_const_string_type) {
const gs_const_string *str = (const gs_const_string *)ptr;
@@ -1815,4 +1865,35 @@ debug_dump_memory(const gs_ref_memory_t * mem, const dump_control_t * control)
}
}
+/* Find all the objects that contain a given pointer. */
+void
+debug_find_pointers(const gs_ref_memory_t *mem, const void *target)
+{
+ dump_control_t control;
+ const chunk_t *mcp;
+
+ control.options = 0;
+ for (mcp = mem->cfirst; mcp != 0; mcp = mcp->cnext) {
+ const chunk_t *cp = (mcp == mem->pcc ? &mem->cc : mcp);
+
+ SCAN_CHUNK_OBJECTS(cp);
+ DO_ALL
+ struct_proc_enum_ptrs((*proc)) = pre->o_type->enum_ptrs;
+ uint index = 0;
+ enum_ptr_t eptr;
+
+ if (proc) /* doesn't trace refs */
+ for (; (*proc)(pre + 1, size, index, &eptr, pre->o_type, NULL); ++index)
+ if (eptr.ptr == target) {
+ dprintf1("Index %d in", index);
+ debug_print_object(pre + 1, &control);
+ }
+/* Temporarily redefine gs_exit so a chunk parsing error */
+/* won't actually exit. */
+#define gs_exit(n) DO_NOTHING
+ END_OBJECTS_SCAN
+#undef gs_exit
+ }
+}
+
#endif /* DEBUG */
diff --git a/gs/src/gsalphac.c b/gs/src/gsalphac.c
index 24840da98..d86ed2bdb 100644
--- a/gs/src/gsalphac.c
+++ b/gs/src/gsalphac.c
@@ -277,13 +277,12 @@ c_alpha_create_default_compositor(const gs_composite_t * pcte,
gs_alloc_struct_immovable(mem, gx_device_composite_alpha,
&st_device_composite_alpha,
"create default alpha compositor");
- *pcdev = (gx_device *) cdev;
+ *pcdev = (gx_device *)cdev;
if (cdev == 0)
return_error(gs_error_VMerror);
- *(gx_device *) cdev = *dev;
- cdev->dname = gs_composite_alpha_device.dname;
- cdev->memory = mem;
- cdev->stype = &st_device_composite_alpha;
+ gx_device_init((gx_device *)cdev,
+ (const gx_device *)&gs_composite_alpha_device, mem, true);
+ gx_device_copy_params((gx_device *)cdev, dev);
/*
* Set the color_info and depth to be compatible with the target,
* but using standard chunky color storage, including alpha.
@@ -295,7 +294,6 @@ c_alpha_create_default_compositor(const gs_composite_t * pcte,
cdev->color_info.max_gray = cdev->color_info.max_color = 255;
/* No halftoning will occur, but we fill these in anyway.... */
cdev->color_info.dither_grays = cdev->color_info.dither_colors = 256;
- assign_dev_procs(cdev, &gs_composite_alpha_device);
/*
* We could speed things up a little by tailoring the procedures in
* the device to the specific num_components, but for simplicity,
diff --git a/gs/src/gsbitops.c b/gs/src/gsbitops.c
index 3698105a1..ce0b54964 100644
--- a/gs/src/gsbitops.c
+++ b/gs/src/gsbitops.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1994, 1995, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -42,18 +42,14 @@
/* Define masks for little-endian operation. */
/* masks[i] has the first i bits off and the rest on. */
#if !arch_is_big_endian
-const bits16 mono_copy_masks[17] =
-{
+const bits16 mono_copy_masks[17] = {
0xffff, 0xff7f, 0xff3f, 0xff1f,
0xff0f, 0xff07, 0xff03, 0xff01,
0xff00, 0x7f00, 0x3f00, 0x1f00,
0x0f00, 0x0700, 0x0300, 0x0100,
0x0000
};
-
-# if arch_sizeof_int > 2
-const bits32 mono_fill_masks[33] =
-{
+const bits32 mono_fill_masks[33] = {
#define mask(n)\
((~0xff | (0xff >> (n & 7))) << (n & -8))
mask( 0),mask( 1),mask( 2),mask( 3),mask( 4),mask( 5),mask( 6),mask( 7),
@@ -63,8 +59,6 @@ const bits32 mono_fill_masks[33] =
0
#undef mask
};
-
-# endif
#endif
/* Fill a rectangle of bits with an 8x1 pattern. */
@@ -277,10 +271,12 @@ bits_bounding_box(const byte * data, uint height, uint raster,
gs_int_rect * pbox)
{
register const ulong *lp;
- static const byte first_1[16] =
- {4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0};
- static const byte last_1[16] =
- {0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4};
+ static const byte first_1[16] = {
+ 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+ static const byte last_1[16] = {
+ 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4
+ };
/* Count trailing blank rows. */
/* Since the raster is a multiple of sizeof(long), */
@@ -402,16 +398,21 @@ bits_bounding_box(const byte * data, uint height, uint raster,
}
/* Count the number of 1-bits in a half-byte. */
-static const byte half_byte_1s[16] =
-{0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
+static const byte half_byte_1s[16] = {
+ 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4
+};
/* Count the number of trailing 1s in an up-to-5-bit value, -1. */
-static const byte bits5_trailing_1s[32] =
-{0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 4};
+static const byte bits5_trailing_1s[32] = {
+ 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 3,
+ 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 4
+};
/* Count the number of leading 1s in an up-to-5-bit value, -1. */
-static const byte bits5_leading_1s[32] =
-{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 4};
+static const byte bits5_leading_1s[32] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 4
+};
/*
* Compress a value between 0 and 2^M to a value between 0 and 2^N-1.
@@ -419,26 +420,33 @@ static const byte bits5_leading_1s[32] =
* The name of the table is compress_count_M_N.
* As noted below, we require that N <= M.
*/
-static const byte compress_1_1[3] =
-{0, 1, 1};
-static const byte compress_2_1[5] =
-{0, 0, 1, 1, 1};
-static const byte compress_2_2[5] =
-{0, 1, 2, 2, 3};
-static const byte compress_3_1[9] =
-{0, 0, 0, 0, 1, 1, 1, 1, 1};
-static const byte compress_3_2[9] =
-{0, 0, 1, 1, 2, 2, 2, 3, 3};
-static const byte compress_4_1[17] =
-{0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
-static const byte compress_4_2[17] =
-{0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3};
-static const byte compress_4_4[17] =
-{0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 10, 11, 12, 13, 14, 15};
+static const byte compress_1_1[3] = {
+ 0, 1, 1
+};
+static const byte compress_2_1[5] = {
+ 0, 0, 1, 1, 1
+};
+static const byte compress_2_2[5] = {
+ 0, 1, 2, 2, 3
+};
+static const byte compress_3_1[9] = {
+ 0, 0, 0, 0, 1, 1, 1, 1, 1
+};
+static const byte compress_3_2[9] = {
+ 0, 0, 1, 1, 2, 2, 2, 3, 3
+};
+static const byte compress_4_1[17] = {
+ 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+};
+static const byte compress_4_2[17] = {
+ 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3
+};
+static const byte compress_4_4[17] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 10, 11, 12, 13, 14, 15
+};
/* The table of tables is indexed by log2(N) and then by M-1. */
-static const byte *const compress_tables[4][4] =
-{
+static const byte *const compress_tables[4][4] = {
{compress_1_1, compress_2_1, compress_3_1, compress_4_1},
{0, compress_2_2, compress_3_2, compress_4_2},
{0, 0, 0, compress_4_4}
diff --git a/gs/src/gsbittab.c b/gs/src/gsbittab.c
index ab23374fb..0b4d6ad0f 100644
--- a/gs/src/gsbittab.c
+++ b/gs/src/gsbittab.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -26,24 +26,21 @@
/*
* byte_reverse_bits[B] = the byte B with the order of bits reversed.
*/
-const byte byte_reverse_bits[256] =
-{
+const byte byte_reverse_bits[256] = {
bit_table_8(0, 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80)
};
/*
* byte_right_mask[N] = a byte with N trailing 1s, 0 <= N <= 8.
*/
-const byte byte_right_mask[9] =
-{
+const byte byte_right_mask[9] = {
0, 1, 3, 7, 0xf, 0x1f, 0x3f, 0x7f, 0xff
};
/*
* byte_count_bits[B] = the number of 1-bits in a byte with value B.
*/
-const byte byte_count_bits[256] =
-{
+const byte byte_count_bits[256] = {
bit_table_8(0, 1, 1, 1, 1, 1, 1, 1, 1)
};
@@ -63,31 +60,26 @@ const byte byte_count_bits[256] =
#define r32(n) r16(n),r16(n)
#define r64(n) r32(n),r32(n)
#define r128(n) r64(n),r64(n)
-const byte byte_bit_run_length_0[256] =
-{
+const byte byte_bit_run_length_0[256] = {
r128(0), r64(1), r32(2), r16(3), r8(4), t8(5)
};
-const byte byte_bit_run_length_1[256] =
-{
+const byte byte_bit_run_length_1[256] = {
r64(0), r32(1), r16(2), r8(3), t8(4),
r64(0), r32(1), r16(2), r8(3), t8(4)
};
-const byte byte_bit_run_length_2[256] =
-{
+const byte byte_bit_run_length_2[256] = {
r32(0), r16(1), r8(2), t8(3),
r32(0), r16(1), r8(2), t8(3),
r32(0), r16(1), r8(2), t8(3),
r32(0), r16(1), r8(2), t8(3)
};
-const byte byte_bit_run_length_3[256] =
-{
+const byte byte_bit_run_length_3[256] = {
r16(0), r8(1), t8(2), r16(0), r8(1), t8(2),
r16(0), r8(1), t8(2), r16(0), r8(1), t8(2),
r16(0), r8(1), t8(2), r16(0), r8(1), t8(2),
r16(0), r8(1), t8(2), r16(0), r8(1), t8(2)
};
-const byte byte_bit_run_length_4[256] =
-{
+const byte byte_bit_run_length_4[256] = {
r8(0), t8(1), r8(0), t8(1), r8(0), t8(1), r8(0), t8(1),
r8(0), t8(1), r8(0), t8(1), r8(0), t8(1), r8(0), t8(1),
r8(0), t8(1), r8(0), t8(1), r8(0), t8(1), r8(0), t8(1),
@@ -103,44 +95,41 @@ const byte byte_bit_run_length_4[256] =
a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h,\
a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h,\
a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h
-const byte byte_bit_run_length_5[256] =
-{
+const byte byte_bit_run_length_5[256] = {
rr8(0, 0, 0, 0, 1, 1, 2, 11)
};
-const byte byte_bit_run_length_6[256] =
-{
+const byte byte_bit_run_length_6[256] = {
rr8(0, 0, 1, 10, 0, 0, 1, 10)
};
-const byte byte_bit_run_length_7[256] =
-{
+const byte byte_bit_run_length_7[256] = {
rr8(0, 9, 0, 9, 0, 9, 0, 9)
};
/* Pointer tables indexed by bit number. */
-const byte *const byte_bit_run_length[8] =
-{byte_bit_run_length_0, byte_bit_run_length_1,
- byte_bit_run_length_2, byte_bit_run_length_3,
- byte_bit_run_length_4, byte_bit_run_length_5,
- byte_bit_run_length_6, byte_bit_run_length_7
+const byte *const byte_bit_run_length[8] = {
+ byte_bit_run_length_0, byte_bit_run_length_1,
+ byte_bit_run_length_2, byte_bit_run_length_3,
+ byte_bit_run_length_4, byte_bit_run_length_5,
+ byte_bit_run_length_6, byte_bit_run_length_7
};
-const byte *const byte_bit_run_length_neg[8] =
-{byte_bit_run_length_0, byte_bit_run_length_7,
- byte_bit_run_length_6, byte_bit_run_length_5,
- byte_bit_run_length_4, byte_bit_run_length_3,
- byte_bit_run_length_2, byte_bit_run_length_1
+const byte *const byte_bit_run_length_neg[8] = {
+ byte_bit_run_length_0, byte_bit_run_length_7,
+ byte_bit_run_length_6, byte_bit_run_length_5,
+ byte_bit_run_length_4, byte_bit_run_length_3,
+ byte_bit_run_length_2, byte_bit_run_length_1
};
/*
* byte_acegbdfh_to_abcdefgh[acegbdfh] = abcdefgh, where the letters
* denote the individual bits of the byte.
*/
-const byte byte_acegbdfh_to_abcdefgh[256] =
-{
+const byte byte_acegbdfh_to_abcdefgh[256] = {
bit_table_8(0, 0x80, 0x20, 0x08, 0x02, 0x40, 0x10, 0x04, 0x01)
};
/* Some C compilers insist on having executable code in every file.... */
+void gsbittab_dummy(P0()); /* for picky compilers */
void
gsbittab_dummy(void)
{
diff --git a/gs/src/gsccode.h b/gs/src/gsccode.h
index 2e2813633..b4aea014e 100644
--- a/gs/src/gsccode.h
+++ b/gs/src/gsccode.h
@@ -40,7 +40,7 @@ typedef ulong gs_glyph;
#define gs_no_glyph ((gs_glyph)0x7fffffff)
#if arch_sizeof_long > 4
-# define gs_min_cid_glyph ((gs_glyph)0x80000000)
+# define gs_min_cid_glyph ((gs_glyph)0x80000000L)
#else
/* Avoid compiler warnings about signed/unsigned constants. */
# define gs_min_cid_glyph ((gs_glyph)~0x7fffffff)
@@ -57,7 +57,37 @@ typedef bool(*gs_glyph_mark_proc_t) (P2(gs_glyph glyph, void *proc_data));
/* gs_proc_glyph_name((*procname)) in a formal argument list. */
typedef gs_proc_glyph_name((*gs_proc_glyph_name_t));
-/* Define a procedure for accessing the known encodings. */
+/* Define the indices for known encodings. */
+typedef enum {
+ ENCODING_INDEX_UNKNOWN = -1,
+ ENCODING_INDEX_STANDARD = 0,
+ ENCODING_INDEX_ISOLATIN1,
+ ENCODING_INDEX_SYMBOL,
+ ENCODING_INDEX_DINGBATS,
+ ENCODING_INDEX_WINANSI,
+ ENCODING_INDEX_MACGLYPH, /* a pseudo-encoding */
+ ENCODING_INDEX_ALOGLYPH, /* ditto */
+ ENCODING_INDEX_ALXGLYPH /* ditto */
+} gs_encoding_index_t;
+#define NUM_KNOWN_ENCODINGS 8
+
+/*
+ * For fonts that use more than one method to identify glyphs, define the
+ * glyph space for the values returned by procedures that return glyphs.
+ * Note that if a font uses only one method (such as Type 1 fonts, which
+ * only use names, or TrueType fonts, which only use indexes), the
+ * glyph_space argument is ignored.
+ */
+typedef enum gs_glyph_space_s {
+ GLYPH_SPACE_NAME, /* names (if available) */
+ GLYPH_SPACE_INDEX /* indexes (if available) */
+} gs_glyph_space_t;
+
+/*
+ * Define a procedure for accessing the known encodings. Note that if
+ * there is a choice, this procedure always returns a glyph name, not a
+ * glyph index.
+ */
#define gs_proc_known_encode(proc)\
gs_glyph proc(P2(gs_char, int))
typedef gs_proc_known_encode((*gs_proc_known_encode_t));
diff --git a/gs/src/gscdef.c b/gs/src/gscdef.c
index e8b20e938..c2b4e2f1c 100644
--- a/gs/src/gscdef.c
+++ b/gs/src/gscdef.c
@@ -18,7 +18,7 @@
/* Configuration scalars */
-#include "stdpre.h"
+#include "std.h"
#include "gscdefs.h" /* interface */
#include "gconf.h" /* for #defines */
@@ -41,7 +41,7 @@ const char *CONFIG_CONST gs_copyright = GS_COPYRIGHT;
#ifndef GS_PRODUCT
# define GS_PRODUCT\
- "Aladdin Ghostscript TESTER RELEASE"
+ "Aladdin Ghostscript BETA RELEASE"
#endif
const char *CONFIG_CONST gs_product = GS_PRODUCT;
diff --git a/gs/src/gschar.c b/gs/src/gschar.c
index 87016c476..aafafcf8b 100644
--- a/gs/src/gschar.c
+++ b/gs/src/gschar.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1989, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -17,164 +17,35 @@
*/
-/* Character writing operators for Ghostscript library */
+/* Character writing "operators" for Ghostscript library */
#include "gx.h"
-#include "memory_.h"
-#include "string_.h"
#include "gserrors.h"
#include "gsstruct.h"
-#include "gxfixed.h" /* ditto */
-#include "gxarith.h"
-#include "gxmatrix.h"
+#include "gsmatrix.h" /* for gscoord.h */
+#include "gscoord.h" /* for gs_idtransform */
#include "gzstate.h"
-#include "gxcoord.h"
#include "gxdevice.h"
#include "gxdevmem.h"
#include "gxchar.h"
#include "gxfont.h"
-#include "gxfont0.h"
-#include "gxfcache.h"
-#include "gspath.h"
-#include "gzpath.h"
-
-/* Define whether or not to cache characters rotated by angles other than */
-/* multiples of 90 degrees. */
-private bool CACHE_ROTATED_CHARS = true;
-
-/* Define whether or not to oversample characters at small sizes. */
-private bool OVERSAMPLE = true;
-
-/* Define the maximum size of a full temporary bitmap when rasterizing, */
-/* in bits (not bytes). */
-private uint MAX_TEMP_BITMAP_BITS = 80000;
-
-/* Structure descriptors */
-private_st_gs_show_enum();
-extern_st(st_gs_text_params);
-#define eptr ((gs_show_enum *)vptr)
-private
-ENUM_PTRS_BEGIN(show_enum_enum_ptrs)
-{
- index -= 5;
- if (index <= eptr->fstack.depth)
- ENUM_RETURN(eptr->fstack.items[index].font);
- index -= eptr->fstack.depth + 1;
- return ENUM_USING(st_gs_text_params, vptr, size, index);
-}
-ENUM_PTR(0, gs_show_enum, pgs);
-ENUM_PTR(1, gs_show_enum, show_gstate);
-ENUM_PTR3(2, gs_show_enum, dev_cache, dev_cache2, dev_null);
-ENUM_PTRS_END
-private RELOC_PTRS_BEGIN(show_enum_reloc_ptrs)
-{
- int i;
-
- RELOC_USING(st_gs_text_params, vptr, size); /* superclass */
- RELOC_PTR(gs_show_enum, pgs);
- RELOC_PTR(gs_show_enum, show_gstate);
- RELOC_PTR3(gs_show_enum, dev_cache, dev_cache2, dev_null);
- for (i = 0; i <= eptr->fstack.depth; i++)
- RELOC_PTR(gs_show_enum, fstack.items[i].font);
-}
-RELOC_PTRS_END
-#undef eptr
/* Forward declarations */
-private int continue_kshow(P1(gs_show_enum *));
-private int continue_show(P1(gs_show_enum *));
-private int continue_show_update(P1(gs_show_enum *));
-private int show_setup(P6(gs_show_enum *, gs_state *, const char *, uint,
- uint, bool));
-private void show_set_scale(P1(gs_show_enum *));
-private int show_cache_setup(P1(gs_show_enum *));
-private int show_state_setup(P1(gs_show_enum *));
-private int show_origin_setup(P4(gs_state *, fixed, fixed, gs_char_path_mode));
-private int stringwidth_setup(P4(gs_show_enum *, gs_state *, const char *,
- uint));
-
-/* Print the ctm if debugging */
-#define print_ctm(s,pgs)\
- dlprintf7("[p]%sctm=[%g %g %g %g %g %g]\n", s,\
- pgs->ctm.xx, pgs->ctm.xy, pgs->ctm.yx, pgs->ctm.yy,\
- pgs->ctm.tx, pgs->ctm.ty)
-
-/* ------ Driver procedure ------ */
-
-/*
- * When actually implemented, this will be moved further down in the file
- * and will replace other code that is there now....
- */
+private int show_n_begin(P4(gs_show_enum *penum, gs_state *pgs, int code,
+ gs_text_enum_t *pte));
-int
-gx_default_text_begin(gx_device * dev, gs_imager_state * pis,
- const gs_text_params_t * text, const gs_font * font,
-gx_path * path, const gx_device_color * pdcolor, const gx_clip_path * pcpath,
- gs_memory_t * memory, gs_text_enum_t ** ppenum)
-{
- return_error(gs_error_undefined);
-}
-
-/* ------ Font procedures ------ */
-
-/* Dummy (ineffective) BuildChar/BuildGlyph procedure */
-int
-gs_no_build_char(gs_show_enum * penum, gs_state * pgs,
- gs_font * pfont, gs_char chr, gs_glyph glyph)
-{
- return 1; /* failure, but not error */
-}
-
-/* Dummy character encoding procedure */
-gs_glyph
-gs_no_encode_char(gs_show_enum * penum,
- gs_font * pfont, gs_char * pchr)
-{
- return gs_no_glyph;
-}
+/* Structure descriptors */
+extern_st(st_gs_show_enum);
/* ------ String writing operators ------ */
-/* Allocate a show enumerator. */
-gs_show_enum *
-gs_show_enum_alloc(gs_memory_t * mem, gs_state * pgs, client_name_t cname)
-{
- gs_show_enum *penum;
-
- rc_alloc_struct_1(penum, gs_show_enum, &st_gs_show_enum, mem,
- return 0, cname);
- /* Initialize pointers for GC */
- penum->text.operation = 0; /* no pointers relevant */
- penum->dev = 0;
- penum->pgs = pgs;
- penum->dev_cache = 0;
- penum->dev_cache2 = 0;
- penum->dev_null = 0;
- penum->fstack.depth = -1;
- return penum;
-}
-
/* Free the contents of a show enumerator. */
void
gs_show_enum_release(gs_show_enum * penum, gs_memory_t * emem)
{
- penum->cc = 0;
- if (penum->dev_cache2 != 0) {
- rc_decrement_only(penum->dev_cache2,
- "gs_show_enum_release(dev_cache2)");
- penum->dev_cache2 = 0;
- }
- if (penum->dev_cache != 0) {
- rc_decrement_only(penum->dev_cache,
- "gs_show_enum_release(dev_cache)");
- penum->dev_cache = 0;
- }
- if (penum->dev_null != 0) {
- rc_decrement_only(penum->dev_null,
- "gs_show_enum_release(dev_null)");
- penum->dev_null = 0;
- }
+ if (penum->text.operation) /* otherwise, never initialized */
+ penum->procs->release((gs_text_enum_t *)penum, "gs_show_enum_release");
if (emem != 0)
- gs_free_object(emem, penum, "gs_show_enum_release(enum)");
+ gs_free_object(emem, penum, "gs_show_enum_release");
}
/* show[_n] */
@@ -182,9 +53,10 @@ int
gs_show_n_init(gs_show_enum * penum, gs_state * pgs,
const char *str, uint size)
{
- return show_setup(penum, pgs, str, size,
- TEXT_FROM_STRING | TEXT_DO_DRAW | TEXT_RETURN_WIDTH,
- true);
+ gs_text_enum_t *pte;
+ int code = gs_show_begin(pgs, (const byte *)str, size, pgs->memory, &pte);
+
+ return show_n_begin(penum, pgs, code, pte);
}
/* ashow[_n] */
@@ -192,12 +64,11 @@ int
gs_ashow_n_init(gs_show_enum * penum, gs_state * pgs,
floatp ax, floatp ay, const char *str, uint size)
{
- penum->text.delta_all.x = ax;
- penum->text.delta_all.y = ay;
- return show_setup(penum, pgs, str, size,
- TEXT_FROM_STRING | TEXT_ADD_TO_ALL_WIDTHS |
- TEXT_DO_DRAW | TEXT_RETURN_WIDTH,
- true);
+ gs_text_enum_t *pte;
+ int code = gs_ashow_begin(pgs, ax, ay, (const byte *)str, size,
+ pgs->memory, &pte);
+
+ return show_n_begin(penum, pgs, code, pte);
}
/* widthshow[_n] */
@@ -206,13 +77,11 @@ gs_widthshow_n_init(gs_show_enum * penum, gs_state * pgs,
floatp cx, floatp cy, gs_char chr,
const char *str, uint size)
{
- penum->text.delta_space.x = cx;
- penum->text.delta_space.y = cy;
- penum->text.space.s_char = chr;
- return show_setup(penum, pgs, str, size,
- TEXT_FROM_STRING | TEXT_ADD_TO_SPACE_WIDTH |
- TEXT_DO_DRAW | TEXT_RETURN_WIDTH,
- true);
+ gs_text_enum_t *pte;
+ int code = gs_widthshow_begin(pgs, cx, cy, chr, (const byte *)str, size,
+ pgs->memory, &pte);
+
+ return show_n_begin(penum, pgs, code, pte);
}
/* awidthshow[_n] */
@@ -221,16 +90,11 @@ gs_awidthshow_n_init(gs_show_enum * penum, gs_state * pgs,
floatp cx, floatp cy, gs_char chr, floatp ax, floatp ay,
const char *str, uint size)
{
- penum->text.delta_space.x = cx;
- penum->text.delta_space.y = cy;
- penum->text.space.s_char = chr;
- penum->text.delta_all.x = ax;
- penum->text.delta_all.y = ay;
- return show_setup(penum, pgs, str, size,
- TEXT_FROM_STRING |
- TEXT_ADD_TO_ALL_WIDTHS | TEXT_ADD_TO_SPACE_WIDTH |
- TEXT_DO_DRAW | TEXT_RETURN_WIDTH,
- true);
+ gs_text_enum_t *pte;
+ int code = gs_awidthshow_begin(pgs, cx, cy, chr, ax, ay,
+ (const byte *)str, size, pgs->memory, &pte);
+
+ return show_n_begin(penum, pgs, code, pte);
}
/* kshow[_n] */
@@ -238,12 +102,21 @@ int
gs_kshow_n_init(gs_show_enum * penum,
gs_state * pgs, const char *str, uint size)
{
- if (pgs->font->FontType == ft_composite)
+ gs_text_enum_t *pte;
+ int code;
+
+ switch (pgs->font->FontType) {
+ case ft_composite:
+ case ft_CID_encrypted:
+ case ft_CID_user_defined:
+ case ft_CID_TrueType:
+ case ft_CID_bitmap:
return_error(gs_error_invalidfont);
- return show_setup(penum, pgs, str, size,
- TEXT_FROM_STRING | TEXT_DO_DRAW | TEXT_INTERVENE |
- TEXT_RETURN_WIDTH,
- true);
+ default:
+ break;
+ }
+ code = gs_kshow_begin(pgs, (const byte *)str, size, pgs->memory, &pte);
+ return show_n_begin(penum, pgs, code, pte);
}
/* xyshow[_n] */
@@ -251,61 +124,30 @@ int
gs_xyshow_n_init(gs_show_enum * penum,
gs_state * pgs, const char *str, uint size)
{
- int code = show_setup(penum, pgs, str, size,
- TEXT_FROM_STRING |
- TEXT_REPLACE_X_WIDTHS | TEXT_REPLACE_Y_WIDTHS |
- TEXT_DO_DRAW | TEXT_INTERVENE | TEXT_RETURN_WIDTH,
- true);
+ gs_text_enum_t *pte;
+ int code = gs_xyshow_begin(pgs, (const byte *)str, size, NULL, NULL, 0,
+ pgs->memory, &pte);
- if (code < 0)
- return code;
- /* Initialize the pointers for the GC. */
- penum->text.x_widths = penum->text.y_widths = 0;
- return code;
+ return show_n_begin(penum, pgs, code, pte);
}
/* glyphshow */
-private int setup_glyph(P4(gs_show_enum *, gs_state *, gs_glyph, uint));
-private font_proc_encode_char(gs_glyphshow_encode_char);
int
gs_glyphshow_init(gs_show_enum * penum, gs_state * pgs, gs_glyph glyph)
{
- return setup_glyph(penum, pgs, glyph, TEXT_DO_DRAW);
+ gs_text_enum_t *pte;
+ int code = gs_glyphshow_begin(pgs, glyph, pgs->memory, &pte);
+
+ return show_n_begin(penum, pgs, code, pte);
}
int
gs_glyphpath_init(gs_show_enum * penum, gs_state * pgs, gs_glyph glyph,
bool stroke_path)
{
- int code = setup_glyph(penum, pgs, glyph,
- (stroke_path ? TEXT_DO_TRUE_CHARPATH :
- TEXT_DO_FALSE_CHARPATH));
+ gs_text_enum_t *pte;
+ int code = gs_glyphpath_begin(pgs, glyph, stroke_path, pgs->memory, &pte);
- penum->can_cache = -1;
- if_debug1('k', "[k]glyphpath, can_cache=%d", penum->can_cache);
- return code;
-}
-private int
-setup_glyph(gs_show_enum * penum, gs_state * pgs, gs_glyph glyph,
- uint operation)
-{
- int code;
-
- if (pgs->font->FontType == ft_composite)
- return_error(gs_error_invalidfont);
- code = show_setup(penum, pgs, NULL, 1,
- TEXT_FROM_SINGLE_GLYPH | TEXT_RETURN_WIDTH | operation,
- true);
- penum->text.data.d_glyph = glyph;
- penum->current_glyph = glyph;
- penum->encode_char = gs_glyphshow_encode_char;
- return code;
-}
-private gs_glyph
-gs_glyphshow_encode_char(gs_show_enum * penum, gs_font * pfont, gs_char * pchr)
-{
- /* We just nil out the character, and return the pre-loaded glyph. */
- *pchr = gs_no_char;
- return penum->current_glyph;
+ return show_n_begin(penum, pgs, code, pte);
}
/* ------ Related operators ------ */
@@ -315,9 +157,10 @@ int
gs_cshow_n_init(gs_show_enum * penum,
gs_state * pgs, const char *str, uint size)
{
- return show_setup(penum, pgs, str, size,
- TEXT_FROM_STRING | TEXT_DO_NONE | TEXT_INTERVENE,
- false);
+ gs_text_enum_t *pte;
+ int code = gs_cshow_begin(pgs, (const byte *)str, size, pgs->memory, &pte);
+
+ return show_n_begin(penum, pgs, code, pte);
}
/* stringwidth[_n] */
@@ -325,41 +168,11 @@ int
gs_stringwidth_n_init(gs_show_enum * penum, gs_state * pgs,
const char *str, uint size)
{
- return stringwidth_setup(penum, pgs, str, size);
-}
+ gs_text_enum_t *pte;
+ int code = gs_stringwidth_begin(pgs, (const byte *)str, size,
+ pgs->memory, &pte);
-/* Common code for stringwidth[_n] */
-private int
-stringwidth_setup(gs_show_enum * penum, gs_state * pgs, const char *str,
- uint size)
-{
- int code = show_setup(penum, pgs, str, size,
- TEXT_FROM_STRING | TEXT_DO_NONE | TEXT_RETURN_WIDTH,
- false);
- gs_memory_t *mem = pgs->memory;
- gx_device_null *dev_null;
-
- if (code < 0)
- return code;
- dev_null = gs_alloc_struct(mem, gx_device_null, &st_device_null,
- "stringwidth_setup(dev_null)");
- if (dev_null == 0)
- return_error(gs_error_VMerror);
- /* Do an extra gsave and suppress output */
- if ((code = gs_gsave(pgs)) < 0)
- return code;
- penum->level = pgs->level; /* for level check in show_update */
- /* Set up a null device that forwards xfont requests properly. */
- gs_make_null_device(dev_null, gs_currentdevice_inline(pgs), mem);
- pgs->ctm_default_set = false;
- penum->dev_null = dev_null;
- /* Retain this device, since it is referenced from the enumerator. */
- gx_device_retain((gx_device *)dev_null, true);
- gs_setdevice_no_init(pgs, (gx_device *) dev_null);
- /* Establish an arbitrary translation and current point. */
- gs_newpath(pgs);
- gx_translate_to_fixed(pgs, fixed_0, fixed_0);
- return gx_path_add_point(pgs->path, fixed_0, fixed_0);
+ return show_n_begin(penum, pgs, code, pte);
}
/* charpath[_n] */
@@ -367,15 +180,11 @@ int
gs_charpath_n_init(gs_show_enum * penum, gs_state * pgs,
const char *str, uint size, bool stroke_path)
{
- int code = show_setup(penum, pgs, str, size,
- TEXT_FROM_STRING |
- (stroke_path ? TEXT_DO_TRUE_CHARPATH :
- TEXT_DO_FALSE_CHARPATH),
- false);
+ gs_text_enum_t *pte;
+ int code = gs_charpath_begin(pgs, (const byte *)str, size, stroke_path,
+ pgs->memory, &pte);
- penum->can_cache = -1;
- if_debug1('k', "[k]charpath, can_cache=%d", penum->can_cache);
- return code;
+ return show_n_begin(penum, pgs, code, pte);
}
/* charboxpath[_n] */
@@ -383,33 +192,24 @@ int
gs_charboxpath_n_init(gs_show_enum * penum, gs_state * pgs,
const char *str, uint size, bool use_boxes)
{
- int code = show_setup(penum, pgs, str, size,
- TEXT_FROM_STRING |
- (use_boxes ? TEXT_DO_TRUE_CHARBOXPATH :
- TEXT_DO_FALSE_CHARBOXPATH),
- false);
+ gs_text_enum_t *pte;
+ int code = gs_charboxpath_begin(pgs, (const byte *)str, size, use_boxes,
+ pgs->memory, &pte);
- penum->can_cache = 0; /* different from charpath! */
- if_debug1('k', "[k]charboxpath, can_cache=%d", penum->can_cache);
- return code;
+ return show_n_begin(penum, pgs, code, pte);
}
/* ------ Width/cache operators ------ */
-private int set_cache_device(P6(gs_show_enum * penum, gs_state * pgs,
- floatp llx, floatp lly, floatp urx, floatp ury));
-
/* setcachedevice */
/* The elements of pw are: wx, wy, llx, lly, urx, ury. */
/* Note that this returns 1 if we just set up the cache device. */
int
-gs_setcachedevice_double(gs_show_enum * penum, gs_state * pgs, const double *pw)
+gs_setcachedevice_double(gs_show_enum *penum, gs_state *pgs, const double *pw)
{
- int code = gs_setcharwidth(penum, pgs, pw[0], pw[1]); /* default is don't cache */
-
- if (code < 0)
- return code;
- return set_cache_device(penum, pgs, pw[2], pw[3], pw[4], pw[5]);
+ if (penum->pgs != pgs)
+ return_error(gs_error_rangecheck);
+ return gs_text_setcachedevice((gs_text_enum_t *)penum, pw);
}
/* The _float procedure is strictly for backward compatibility. */
int
@@ -430,35 +230,9 @@ int
gs_setcachedevice2_double(gs_show_enum * penum, gs_state * pgs,
const double *pw2)
{
- int code;
-
- if (gs_rootfont(pgs)->WMode) {
- float vx = pw2[8], vy = pw2[9];
- gs_fixed_point pvxy, dvxy;
- cached_char *cc;
-
- if ((code = gs_point_transform2fixed(&pgs->ctm, -vx, -vy, &pvxy)) < 0 ||
- (code = gs_distance_transform2fixed(&pgs->ctm, vx, vy, &dvxy)) < 0
- )
- return 0; /* don't cache */
- if ((code = gs_setcharwidth(penum, pgs, pw2[6], pw2[7])) < 0)
- return code;
- /* Adjust the origin by (vx, vy). */
- gx_translate_to_fixed(pgs, pvxy.x, pvxy.y);
- code = set_cache_device(penum, pgs, pw2[2], pw2[3], pw2[4], pw2[5]);
- if (code != 1)
- return code;
- /* Adjust the character origin too. */
- cc = penum->cc;
- cc->offset.x += dvxy.x;
- cc->offset.y += dvxy.y;
- } else {
- code = gs_setcharwidth(penum, pgs, pw2[0], pw2[1]);
- if (code < 0)
- return code;
- code = set_cache_device(penum, pgs, pw2[2], pw2[3], pw2[4], pw2[5]);
- }
- return code;
+ if (penum->pgs != pgs)
+ return_error(gs_error_rangecheck);
+ return gs_text_setcachedevice2((gs_text_enum_t *)penum, pw2);
}
/* The _float procedure is strictly for backward compatibility. */
int
@@ -472,191 +246,6 @@ gs_setcachedevice2_float(gs_show_enum * penum, gs_state * pgs, const float *pw2)
return gs_setcachedevice2_double(penum, pgs, w2);
}
-/* Set up the cache device if relevant. */
-/* Return 1 if we just set up a cache device. */
-/* Used by setcachedevice and setcachedevice2. */
-private int
-set_cache_device(gs_show_enum * penum, gs_state * pgs, floatp llx, floatp lly,
- floatp urx, floatp ury)
-{
- gs_glyph glyph;
-
- /* See if we want to cache this character. */
- if (pgs->in_cachedevice) /* no recursion! */
- return 0;
- pgs->in_cachedevice = CACHE_DEVICE_NOT_CACHING; /* disable color/gray/image operators */
- /* We can only use the cache if we know the glyph. */
- glyph = gs_show_current_glyph(penum);
- if (glyph == gs_no_glyph)
- return 0;
- /* We can only use the cache if ctm is unchanged */
- /* (aside from a possible translation). */
- if (penum->can_cache <= 0 || !pgs->char_tm_valid) {
- if_debug2('k', "[k]no cache: can_cache=%d, char_tm_valid=%d\n",
- penum->can_cache, (int)pgs->char_tm_valid);
- return 0;
- } {
- const gs_font *pfont = pgs->font;
- gs_font_dir *dir = pfont->dir;
- gx_device *dev = gs_currentdevice_inline(pgs);
- int alpha_bits =
- (*dev_proc(dev, get_alpha_bits)) (dev, go_text);
- gs_log2_scale_point log2_scale;
- static const fixed max_cdim[3] =
- {
-#define max_cd(n)\
- (fixed_1 << (arch_sizeof_short * 8 - n)) - (fixed_1 >> n) * 3
- max_cd(0), max_cd(1), max_cd(2)
-#undef max_cd
- };
- ushort iwidth, iheight;
- cached_char *cc;
- gs_fixed_rect clip_box;
- int code;
-
- /* Compute the bounding box of the transformed character. */
- /* Since we accept arbitrary transformations, the extrema */
- /* may occur in any order; however, we can save some work */
- /* by observing that opposite corners before transforming */
- /* are still opposite afterwards. */
- gs_fixed_point cll, clr, cul, cur, cdim;
-
- if ((code = gs_distance_transform2fixed(&pgs->ctm, llx, lly, &cll)) < 0 ||
- (code = gs_distance_transform2fixed(&pgs->ctm, llx, ury, &clr)) < 0 ||
- (code = gs_distance_transform2fixed(&pgs->ctm, urx, lly, &cul)) < 0 ||
- (code = gs_distance_transform2fixed(&pgs->ctm, urx, ury, &cur)) < 0
- )
- return 0; /* don't cache */
- {
- fixed ctemp;
-
-#define swap(a, b) ctemp = a, a = b, b = ctemp
-#define make_min(a, b) if ( (a) > (b) ) swap(a, b)
-
- make_min(cll.x, cur.x);
- make_min(cll.y, cur.y);
- make_min(clr.x, cul.x);
- make_min(clr.y, cul.y);
-#undef make_min
-#undef swap
- }
- /* Now take advantage of symmetry. */
- if (clr.x < cll.x)
- cll.x = clr.x, cur.x = cul.x;
- if (clr.y < cll.y)
- cll.y = clr.y, cur.y = cul.y;
- /* Now cll and cur are the extrema of the box. */
- cdim.x = cur.x - cll.x;
- cdim.y = cur.y - cll.y;
- show_set_scale(penum);
- log2_scale.x = penum->log2_suggested_scale.x;
- log2_scale.y = penum->log2_suggested_scale.y;
-#ifdef DEBUG
- if (gs_debug_c('k')) {
- dlprintf6("[k]cbox=[%g %g %g %g] scale=%dx%d\n",
- fixed2float(cll.x), fixed2float(cll.y),
- fixed2float(cur.x), fixed2float(cur.y),
- 1 << log2_scale.x, 1 << log2_scale.y);
- print_ctm(" ", pgs);
- }
-#endif
- /*
- * If the device wants anti-aliased text,
- * increase the sampling scale to ensure that
- * if we want N bits of alpha, we generate
- * at least 2^N sampled bits per pixel.
- */
- if (alpha_bits > 1) {
- int more_bits =
- alpha_bits - (log2_scale.x + log2_scale.y);
-
- if (more_bits > 0) {
- if (log2_scale.x <= log2_scale.y) {
- log2_scale.x += (more_bits + 1) >> 1;
- log2_scale.y += more_bits >> 1;
- } else {
- log2_scale.x += more_bits >> 1;
- log2_scale.y += (more_bits + 1) >> 1;
- }
- }
- } else if (!OVERSAMPLE || pfont->PaintType != 0) {
- /* Don't oversample artificially stroked fonts. */
- log2_scale.x = log2_scale.y = 0;
- }
- if (cdim.x > max_cdim[log2_scale.x] ||
- cdim.y > max_cdim[log2_scale.y]
- )
- return 0; /* much too big */
- iwidth = ((ushort) fixed2int_var(cdim.x) + 2) << log2_scale.x;
- iheight = ((ushort) fixed2int_var(cdim.y) + 2) << log2_scale.y;
- if_debug3('k', "[k]iwidth=%u iheight=%u dev_cache %s\n",
- (uint) iwidth, (uint) iheight,
- (penum->dev_cache == 0 ? "not set" : "set"));
- if (penum->dev_cache == 0) {
- code = show_cache_setup(penum);
- if (code < 0)
- return code;
- }
- /*
- * If we're oversampling (i.e., the temporary bitmap is
- * larger than the final monobit or alpha array) and the
- * temporary bitmap is large, use incremental conversion
- * from oversampled bitmap strips to alpha values instead of
- * full oversampling with compression at the end.
- */
- cc = gx_alloc_char_bits(dir, penum->dev_cache,
- (iwidth > MAX_TEMP_BITMAP_BITS / iheight &&
- log2_scale.x + log2_scale.y > alpha_bits ?
- penum->dev_cache2 : NULL),
- iwidth, iheight, &log2_scale, alpha_bits);
- if (cc == 0)
- return 0; /* too big for cache */
- /* The mins handle transposed coordinate systems.... */
- /* Truncate the offsets to avoid artifacts later. */
- cc->offset.x = fixed_ceiling(-cll.x);
- cc->offset.y = fixed_ceiling(-cll.y);
- if_debug4('k', "[k]width=%u, height=%u, offset=[%g %g]\n",
- (uint) iwidth, (uint) iheight,
- fixed2float(cc->offset.x),
- fixed2float(cc->offset.y));
- if ((code = gs_gsave(pgs)) < 0) {
- gx_free_cached_char(dir, cc);
- return code;
- }
- /* Nothing can go wrong now.... */
- penum->cc = cc;
- cc->code = glyph;
- cc->wmode = gs_rootfont(pgs)->WMode;
- cc->wxy = penum->wxy;
- /* Install the device */
- gx_set_device_only(pgs, (gx_device *) penum->dev_cache);
- pgs->ctm_default_set = false;
- /* Adjust the transformation in the graphics context */
- /* so that the character lines up with the cache. */
- gx_translate_to_fixed(pgs,
- cc->offset.x << log2_scale.x,
- cc->offset.y << log2_scale.y);
- if ((log2_scale.x | log2_scale.y) != 0)
- gx_scale_char_matrix(pgs, 1 << log2_scale.x,
- 1 << log2_scale.y);
- /* Set the initial matrix for the cache device. */
- penum->dev_cache->initial_matrix = ctm_only(pgs);
- /* Set the oversampling factor. */
- penum->log2_current_scale.x = log2_scale.x;
- penum->log2_current_scale.y = log2_scale.y;
- /* Reset the clipping path to match the metrics. */
- clip_box.p.x = clip_box.p.y = 0;
- clip_box.q.x = int2fixed(iwidth);
- clip_box.q.y = int2fixed(iheight);
- if ((code = gx_clip_to_rectangle(pgs, &clip_box)) < 0)
- return code;
- gx_set_device_color_1(pgs); /* write 1's */
- pgs->in_cachedevice = CACHE_DEVICE_CACHING;
- }
- penum->width_status = sws_cache;
- return 1;
-}
-
/* setcharwidth */
/* Note that this returns 1 if the current show operation is */
/* non-displaying (stringwidth or cshow). */
@@ -664,28 +253,12 @@ int
gs_setcharwidth(gs_show_enum * penum, gs_state * pgs,
floatp wx, floatp wy)
{
- int code;
-
- if (penum->width_status != sws_none)
- return_error(gs_error_undefined);
- if ((code = gs_distance_transform2fixed(&pgs->ctm, wx, wy, &penum->wxy)) < 0)
- return code;
- /* Check whether we're setting the scalable width */
- /* for a cached xfont character. */
- if (penum->cc != 0) {
- penum->cc->wxy = penum->wxy;
- penum->width_status = sws_cache_width_only;
- } else {
- penum->width_status = sws_no_cache;
- }
- return !SHOW_IS_DRAWING(penum);
-}
+ double w[2];
-/* Return the cache device status. */
-gs_in_cache_device_t
-gs_incachedevice(const gs_state *pgs)
-{
- return pgs->in_cachedevice;
+ if (penum->pgs != pgs)
+ return_error(gs_error_rangecheck);
+ w[0] = wx, w[1] = wy;
+ return gs_text_setcharwidth((gs_text_enum_t *)penum, w);
}
/* ------ Enumerator ------ */
@@ -694,493 +267,48 @@ gs_incachedevice(const gs_state *pgs)
int
gs_show_next(gs_show_enum * penum)
{
- return (*penum->continue_proc) (penum);
-}
-
-/* Continuation procedures */
-private int show_update(P1(gs_show_enum * penum));
-private int show_move(P1(gs_show_enum * penum));
-private int show_proceed(P1(gs_show_enum * penum));
-private int show_finish(P1(gs_show_enum * penum));
-private int
-continue_show_update(gs_show_enum * penum)
-{
- int code = show_update(penum);
-
- if (code < 0)
- return code;
- code = show_move(penum);
- if (code != 0)
- return code;
- return show_proceed(penum);
-}
-private int
-continue_show(gs_show_enum * penum)
-{
- return show_proceed(penum);
-}
-/* For kshow, the CTM or font may have changed, so we have to reestablish */
-/* the cached values in the enumerator. */
-private int
-continue_kshow(gs_show_enum * penum)
-{
- int code = show_state_setup(penum);
-
- if (code < 0)
- return code;
- return show_proceed(penum);
-}
-
-/* Update position */
-private int
-show_update(gs_show_enum * penum)
-{
- gs_state *pgs = penum->pgs;
- cached_char *cc = penum->cc;
- int code;
-
- /* Update position for last character */
- switch (penum->width_status) {
- case sws_none:
- /* Adobe interpreters assume a character width of 0, */
- /* even though the documentation says this is an error.... */
- penum->wxy.x = penum->wxy.y = 0;
- break;
- case sws_cache:
- /* Finish installing the cache entry. */
- /* If the BuildChar/BuildGlyph procedure did a save and a */
- /* restore, it already undid the gsave in setcachedevice. */
- /* We have to check for this by comparing levels. */
- switch (pgs->level - penum->level) {
- default:
- return_error(gs_error_invalidfont); /* WRONG */
- case 2:
- code = gs_grestore(pgs);
- if (code < 0)
- return code;
- case 1:
- ;
- }
- gx_add_cached_char(pgs->font->dir, penum->dev_cache,
- cc, gx_lookup_fm_pair(pgs->font, pgs),
- &penum->log2_current_scale);
- if (!SHOW_IS_DRAWING(penum) ||
- penum->charpath_flag != cpm_show
- )
- break;
- /* falls through */
- case sws_cache_width_only:
- /* Copy the bits to the real output device. */
- code = gs_grestore(pgs);
- if (code < 0)
- return code;
- code = gs_state_color_load(pgs);
- if (code < 0)
- return code;
- return gx_image_cached_char(penum, cc);
- case sws_no_cache:
- ;
- }
- if (penum->charpath_flag != cpm_show) {
- /* Move back to the character origin, so that */
- /* show_move will get us to the right place. */
- code = gx_path_add_point(pgs->show_gstate->path,
- penum->origin.x, penum->origin.y);
- if (code < 0)
- return code;
- }
- return gs_grestore(pgs);
-}
-
-/* Move to next character */
-private int
-show_fast_move(gs_state * pgs, gs_fixed_point * pwxy)
-{
- int code = gx_path_add_rel_point_inline(pgs->path, pwxy->x, pwxy->y);
-
- /* If the current position is out of range, don't try to move. */
- if (code == gs_error_limitcheck && pgs->clamp_coordinates)
- code = 0;
- return code;
+ return gs_text_process((gs_text_enum_t *)penum);
}
-private int
-show_move(gs_show_enum * penum)
-{
- gs_state *pgs = penum->pgs;
-
- if (SHOW_IS_XYCSHOW(penum)) {
- penum->continue_proc = continue_show;
- return gs_show_move;
- }
- if (SHOW_IS_ADD_TO_ALL(penum))
- gs_rmoveto(pgs, penum->text.delta_all.x, penum->text.delta_all.y);
- if (SHOW_IS_ADD_TO_SPACE(penum)) {
- gs_char chr = penum->current_char & 0xff;
- int fdepth = penum->fstack.depth;
-
- if (fdepth > 0) {
- /* Add in the shifted font number. */
- uint fidx = penum->fstack.items[fdepth].index;
- switch (((gs_font_type0 *) (penum->fstack.items[fdepth - 1].font))->data.FMapType) {
- case fmap_1_7:
- case fmap_9_7:
- chr += fidx << 7;
- break;
- case fmap_CMap:
- chr = penum->current_char; /* the full character */
- if (!penum->cmap_code)
- break;
- /* falls through */
- default:
- chr += fidx << 8;
- }
- }
- if (chr == penum->text.space.s_char)
- gs_rmoveto(pgs, penum->text.delta_space.x,
- penum->text.delta_space.y);
- }
- /* wxy is in device coordinates */
- {
- int code = show_fast_move(pgs, &penum->wxy);
-
- if (code < 0)
- return code;
- }
- /* Check for kerning, but not on the last character. */
- if (SHOW_IS_DO_KERN(penum) && penum->index < penum->text.size) {
- penum->continue_proc = continue_kshow;
- return gs_show_kern;
- }
- return 0;
-}
-/* Process next character */
-private int
-show_proceed(gs_show_enum * penum)
+/*
+ * Return true if we only need the width from the rasterizer
+ * and can short-circuit the full rendering of the character,
+ * false if we need the actual character bits.
+ */
+bool
+gs_show_width_only(const gs_show_enum * penum)
{
- gs_state *pgs = penum->pgs;
- gs_font *pfont;
- cached_fm_pair *pair = 0;
- gs_font *rfont =
- (penum->fstack.depth < 0 ? pgs->font : penum->fstack.items[0].font);
- int wmode = rfont->WMode;
-
- font_proc_next_char((*next_char)) = rfont->procs.next_char;
- font_proc_next_glyph((*next_glyph)) = rfont->procs.next_glyph;
-#define next_char_glyph(penum, pchr, pglyph)\
- (next_char == 0 ? (*next_glyph)(penum, pchr, pglyph) :\
- (*(pglyph) = gs_no_glyph, (*next_char)(penum, pchr)))
- gs_char chr;
- gs_glyph glyph;
- int code;
- cached_char *cc;
- gx_device *dev = gs_currentdevice_inline(pgs);
- int alpha_bits = (*dev_proc(dev, get_alpha_bits)) (dev, go_text);
-
- if (penum->charpath_flag == cpm_show && SHOW_IS_DRAWING(penum)) {
- code = gs_state_color_load(pgs);
- if (code < 0)
- return code;
- }
- more: /* Proceed to next character */
- pfont = (penum->fstack.depth < 0 ? pgs->font :
- penum->fstack.items[penum->fstack.depth].font);
- /* can_cache >= 0 allows us to use cached characters, */
- /* even if we can't make new cache entries. */
- if (penum->can_cache >= 0) {
- /* Loop with cache */
- for (;;) {
- switch ((code = next_char_glyph(penum, &chr, &glyph))) {
- default: /* error */
- return code;
- case 2: /* done */
- return show_finish(penum);
- case 1: /* font change */
- pfont = penum->fstack.items[penum->fstack.depth].font;
- pgs->char_tm_valid = false;
- show_state_setup(penum);
- pair = 0;
- /* falls through */
- case 0: /* plain char */
- /*
- * We don't need to set penum->current_char in the
- * normal cases, but it's needed for widthshow,
- * kshow, and one strange client, so we may as well
- * do it here.
- */
- penum->current_char = chr;
- if (glyph == gs_no_glyph) {
- glyph = (*penum->encode_char) (penum, pfont, &chr);
- penum->current_char = chr;
- if (glyph == gs_no_glyph) {
- cc = 0;
- goto no_cache;
- }
- }
- if (pair == 0)
- pair = gx_lookup_fm_pair(pfont, pgs);
- cc = gx_lookup_cached_char(pfont, pair, glyph, wmode,
- alpha_bits);
- if (cc == 0) {
- /* Character is not in cache. */
- /* If possible, try for an xfont before */
- /* rendering from the outline. */
- if (pfont->ExactSize == fbit_use_outlines ||
- pfont->PaintType == 2
- )
- goto no_cache;
- if (pfont->BitmapWidths) {
- cc = gx_lookup_xfont_char(pgs, pair, chr,
- glyph, &pfont->procs.callbacks, wmode);
- if (cc == 0)
- goto no_cache;
- } else {
- if (!SHOW_IS_DRAWING(penum) != 0 ||
- penum->charpath_flag != cpm_show
- )
- goto no_cache;
- /* We might have an xfont, but we still */
- /* want the scalable widths. */
- cc = gx_lookup_xfont_char(pgs, pair, chr,
- glyph, &pfont->procs.callbacks, wmode);
- /* Render up to the point of */
- /* setcharwidth or setcachedevice, */
- /* just as for stringwidth. */
- /* This is the only case in which we can */
- /* to go no_cache with cc != 0. */
- goto no_cache;
- }
- }
- /* Character is in cache. */
- /* We might be doing .charboxpath or stringwidth; */
- /* check for these now. */
- if (penum->charpath_flag != cpm_show) {
- /* This is .charboxpath. Get the bounding box */
- /* and append it to a path. */
- gx_path box_path;
- gs_fixed_point pt;
- fixed llx, lly, urx, ury;
-
- code = gx_path_current_point(pgs->path, &pt);
- if (code < 0)
- return code;
- llx = fixed_rounded(pt.x - cc->offset.x) +
- int2fixed(penum->ftx);
- lly = fixed_rounded(pt.y - cc->offset.y) +
- int2fixed(penum->fty);
- urx = llx + int2fixed(cc->width),
- ury = lly + int2fixed(cc->height);
- gx_path_init_local(&box_path, pgs->memory);
- code =
- gx_path_add_rectangle(&box_path, llx, lly,
- urx, ury);
- if (code >= 0)
- code =
- gx_path_add_char_path(pgs->show_gstate->path,
- &box_path,
- penum->charpath_flag);
- if (code >= 0)
- code = gx_path_add_point(pgs->path, pt.x, pt.y);
- gx_path_free(&box_path, "show_proceed(box path)");
- if (code < 0)
- return code;
- } else if (SHOW_IS_DRAWING(penum)) {
- code = gx_image_cached_char(penum, cc);
- if (code < 0)
- return code;
- else if (code > 0) {
- cc = 0;
- goto no_cache;
- }
- }
- if (SHOW_IS_SLOW(penum)) {
- /* Split up the assignment so that the */
- /* Watcom compiler won't reserve esi/edi. */
- penum->wxy.x = cc->wxy.x;
- penum->wxy.y = cc->wxy.y;
- code = show_move(penum);
- } else
- code = show_fast_move(pgs, &cc->wxy);
- if (code) {
- /* Might be kshow, so store the state. */
- penum->current_glyph = glyph;
- return code;
- }
- }
- }
- } else {
- /* Can't use cache */
- switch ((code = next_char_glyph(penum, &chr, &glyph))) {
- default:
- return code;
- case 2:
- return show_finish(penum);
- case 1:
- pfont = penum->fstack.items[penum->fstack.depth].font;
- show_state_setup(penum);
- case 0:
- ;
- }
- penum->current_char = chr;
- if (glyph == gs_no_glyph) {
- glyph = (*penum->encode_char) (penum, pfont, &chr);
- penum->current_char = chr;
- }
- cc = 0;
- }
- no_cache:
- /*
- * We must call the client's rendering code. Normally,
- * we only do this if the character is not cached (cc = 0);
- * however, we also must do this if we have an xfont but
- * are using scalable widths. In this case, and only this case,
- * we get here with cc != 0. penum->current_char has already
- * been set, but not penum->current_glyph.
- */
- penum->current_glyph = glyph;
- if ((code = gs_gsave(pgs)) < 0)
- return code;
- /* Set the font to the current descendant font. */
- pgs->font = pfont;
- /* Reset the in_cachedevice flag, so that a recursive show */
- /* will use the cache properly. */
- pgs->in_cachedevice = CACHE_DEVICE_NONE;
- /* Reset the sampling scale. */
- penum->log2_current_scale.x = penum->log2_current_scale.y = 0;
- /* Set the charpath data in the graphics context if necessary, */
- /* so that fill and stroke will add to the path */
- /* rather than having their usual effect. */
- pgs->in_charpath = penum->charpath_flag;
- pgs->show_gstate =
- (penum->show_gstate == pgs ? pgs->saved : penum->show_gstate);
- pgs->stroke_adjust = false; /* per specification */
- {
- gs_fixed_point cpt;
- gx_path *ppath = pgs->path;
-
- if ((code = gx_path_current_point_inline(ppath, &cpt)) < 0)
- goto rret;
- penum->origin.x = cpt.x;
- penum->origin.y = cpt.y;
- /* Normally, char_tm is valid because of show_state_setup, */
- /* but if we're in a cshow, it may not be. */
- gs_currentcharmatrix(pgs, NULL, true);
-#if 1 /*USE_FPU <= 0 */
- if (pgs->ctm.txy_fixed_valid && pgs->char_tm.txy_fixed_valid) {
- fixed tx = pgs->ctm.tx_fixed;
- fixed ty = pgs->ctm.ty_fixed;
-
- gs_settocharmatrix(pgs);
- cpt.x += pgs->ctm.tx_fixed - tx;
- cpt.y += pgs->ctm.ty_fixed - ty;
- } else
-#endif
- {
- double tx = pgs->ctm.tx;
- double ty = pgs->ctm.ty;
- double fpx, fpy;
-
- gs_settocharmatrix(pgs);
- fpx = fixed2float(cpt.x) + (pgs->ctm.tx - tx);
- fpy = fixed2float(cpt.y) + (pgs->ctm.ty - ty);
-#define f_fits_in_fixed(f) f_fits_in_bits(f, fixed_int_bits)
- if (!(f_fits_in_fixed(fpx) && f_fits_in_fixed(fpy))) {
- gs_note_error(code = gs_error_limitcheck);
- goto rret;
- }
- cpt.x = float2fixed(fpx);
- cpt.y = float2fixed(fpy);
- }
- gs_newpath(pgs);
- code = show_origin_setup(pgs, cpt.x, cpt.y,
- penum->charpath_flag);
- if (code < 0)
- goto rret;
- }
- penum->width_status = sws_none;
- penum->continue_proc = continue_show_update;
- /* Try using the build procedure in the font. */
- /* < 0 means error, 0 means success, 1 means failure. */
- penum->cc = cc; /* set this now for build procedure */
- code = (*pfont->procs.build_char) (penum, pgs, pfont, chr, glyph);
- if (code < 0) {
- discard(gs_note_error(code));
- goto rret;
- }
- if (code == 0) {
- code = show_update(penum);
- if (code < 0)
- goto rret;
- /* Note that show_update does a grestore.... */
- code = show_move(penum);
- if (code)
- return code; /* ... so don't go to rret here. */
- goto more;
- }
- /*
- * Some BuildChar procedures do a save before the setcachedevice,
- * and a restore at the end. If we waited to allocate the cache
- * device until the setcachedevice, we would attempt to free it
- * after the restore. Therefore, allocate it now.
- */
- if (penum->dev_cache == 0) {
- code = show_cache_setup(penum);
- if (code < 0)
- goto rret;
- }
- return gs_show_render;
- /* If we get an error while setting up for BuildChar, */
- /* we must undo the partial setup. */
- rret:gs_grestore(pgs);
- return code;
-#undef next_char_glyph
+ return gs_text_is_width_only((const gs_text_enum_t *)penum);
}
-/* Finish show or stringwidth */
-private int
-show_finish(gs_show_enum * penum)
-{
- gs_state *pgs = penum->pgs;
- int code, rcode;
-
- gs_show_enum_release(penum, NULL);
- if (!SHOW_IS_STRINGWIDTH(penum))
- return 0;
- /* Save the accumulated width before returning, */
- /* and undo the extra gsave. */
- code = gs_currentpoint(pgs, &penum->width);
- rcode = gs_grestore(pgs);
- return (code < 0 ? code : rcode);
-}
+/* ------ Accessors ------ */
/* Return the current character for rendering. */
gs_char
gs_show_current_char(const gs_show_enum * penum)
{
- return penum->current_char;
+ return gs_text_current_char((const gs_text_enum_t *)penum);
}
/* Return the current glyph for rendering. */
gs_glyph
gs_show_current_glyph(const gs_show_enum * penum)
{
- return penum->current_glyph;
+ return gs_text_current_glyph((const gs_text_enum_t *)penum);
}
/* Return the width of the just-enumerated character (for cshow). */
int
gs_show_current_width(const gs_show_enum * penum, gs_point * ppt)
{
- return gs_idtransform(penum->pgs,
- fixed2float(penum->wxy.x),
- fixed2float(penum->wxy.y), ppt);
+ return gs_text_current_width((const gs_text_enum_t *)penum, ppt);
}
/* Return the just-displayed character for kerning. */
gs_char
gs_kshow_previous_char(const gs_show_enum * penum)
{
- return penum->current_char;
+ return gs_text_current_char((const gs_text_enum_t *)penum);
}
/* Return the about-to-be-displayed character for kerning. */
@@ -1190,321 +318,42 @@ gs_kshow_next_char(const gs_show_enum * penum)
return penum->text.data.bytes[penum->index];
}
-/* ------ Miscellaneous accessors ------ */
-
-/* Return the current font for cshow. */
-gs_font *
-gs_show_current_font(const gs_show_enum * penum)
-{
- return (penum->fstack.depth < 0 ? penum->pgs->font :
- penum->fstack.items[penum->fstack.depth].font);
-}
-
-/* Restore the current font after cshow. */
-int
-gs_show_restore_font(const gs_show_enum * penum)
-{
- int fdepth = penum->fstack.depth;
-
- if (fdepth >= 0) {
- gs_state *pgs = penum->pgs;
-
- gs_setfont(pgs, penum->fstack.items[0].font);
- pgs->font = penum->fstack.items[fdepth].font;
- }
- return 0;
-}
-
-/* Return the charpath mode. */
-gs_char_path_mode
-gs_show_in_charpath(const gs_show_enum * penum)
-{
- return penum->charpath_flag;
-}
-
/* Return the accumulated width for stringwidth. */
void
gs_show_width(const gs_show_enum * penum, gs_point * ppt)
{
- *ppt = penum->width;
-}
-
-/* Return true if we only need the width from the rasterizer */
-/* and can short-circuit the full rendering of the character, */
-/* false if we need the actual character bits. */
-/* This is only meaningful just before calling gs_setcharwidth or */
-/* gs_setcachedevice[2]. */
-/* Note that we can't do this if the procedure has done any extra [g]saves. */
-bool
-gs_show_width_only(const gs_show_enum * penum)
-{
- /* penum->cc will be non-zero iff we are calculating */
- /* the scalable width for an xfont character. */
- return ((!SHOW_IS_DRAWING(penum) || penum->cc != 0) &&
- penum->pgs->level == penum->level + 1);
+ gs_text_total_width((const gs_text_enum_t *)penum, ppt);
}
/* ------ Internal routines ------ */
-/* Initialize a show enumerator. */
+/*
+ * Force the enumerator to be a gs_show_enum *, which the current
+ * implementation code requires.
+ */
private int
-show_setup(gs_show_enum * penum, gs_state * pgs, const char *str,
- uint size, uint operation, bool propagate_charpath)
+show_n_begin(gs_show_enum *penum, gs_state *pgs, int code, gs_text_enum_t *pte)
{
- int code;
- gs_font *pfont;
-
- /* Set rest of common members. */
- penum->text.operation = operation;
- penum->text.data.bytes = (const byte *)str; /* avoid signed chars */
- penum->text.size = size;
- penum->index = 0;
- /* Set other members. */
- gx_set_dev_color(pgs);
- pfont = pgs->font;
- penum->pgs = pgs;
- penum->level = pgs->level;
- if (operation & TEXT_DO_ANY_CHARPATH)
- penum->charpath_flag =
- (operation & TEXT_DO_FALSE_CHARPATH ? cpm_false_charpath :
- operation & TEXT_DO_TRUE_CHARPATH ? cpm_true_charpath :
- operation & TEXT_DO_FALSE_CHARBOXPATH ? cpm_false_charboxpath :
- operation & TEXT_DO_TRUE_CHARBOXPATH ? cpm_true_charboxpath :
- cpm_show /* can't happen */ );
- else
- penum->charpath_flag =
- (propagate_charpath ? pgs->in_charpath : cpm_show);
- penum->dev_cache = 0;
- penum->dev_cache2 = 0;
- penum->dev_null = 0;
- penum->cc = 0;
- penum->continue_proc = continue_show;
- code = (*pfont->procs.init_fstack) (penum, pfont);
- if (code < 0)
- return code;
- penum->can_cache = /* show_state_setup may reset */
- (penum->charpath_flag == cpm_show ? 1 : -1);
- code = show_state_setup(penum);
if (code < 0)
return code;
- penum->show_gstate =
- (propagate_charpath && (pgs->in_charpath != 0) ?
- pgs->show_gstate : pgs);
- return 0;
-}
-
-/* Initialize the gstate-derived parts of a show enumerator. */
-/* We do this both when starting the show operation, */
-/* and when returning from the kshow callout. */
-private int
-show_state_setup(gs_show_enum * penum)
-{
- gs_state *pgs = penum->pgs;
- gx_clip_path *pcpath;
- const gs_font *pfont;
-
- if (penum->fstack.depth <= 0) {
- pfont = pgs->font;
- gs_currentcharmatrix(pgs, NULL, 1); /* make char_tm valid */
- } else {
- /* We have to concatenate the parent's FontMatrix as well. */
- gs_matrix mat;
- const gx_font_stack_item *pfsi =
- &penum->fstack.items[penum->fstack.depth];
-
- pfont = pfsi->font;
- gs_matrix_multiply(&pfont->FontMatrix,
- &pfsi[-1].font->FontMatrix, &mat);
- gs_setcharmatrix(pgs, &mat);
- }
- /* Skewing or non-rectangular rotation are not supported. */
- if (!CACHE_ROTATED_CHARS &&
- (is_fzero2(pgs->char_tm.xy, pgs->char_tm.yx) ||
- is_fzero2(pgs->char_tm.xx, pgs->char_tm.yy))
- )
- penum->can_cache = 0;
- if (penum->can_cache >= 0 &&
- gx_effective_clip_path(pgs, &pcpath) >= 0
- ) {
- gs_fixed_rect cbox;
-
- gx_cpath_inner_box(pcpath, &cbox);
- /* Since characters occupy an integral number of pixels, */
- /* we can (and should) round the inner clipping box */
- /* outward rather than inward. */
- penum->ibox.p.x = fixed2int_var(cbox.p.x);
- penum->ibox.p.y = fixed2int_var(cbox.p.y);
- penum->ibox.q.x = fixed2int_var_ceiling(cbox.q.x);
- penum->ibox.q.y = fixed2int_var_ceiling(cbox.q.y);
- gx_cpath_outer_box(pcpath, &cbox);
- penum->obox.p.x = fixed2int_var(cbox.p.x);
- penum->obox.p.y = fixed2int_var(cbox.p.y);
- penum->obox.q.x = fixed2int_var_ceiling(cbox.q.x);
- penum->obox.q.y = fixed2int_var_ceiling(cbox.q.y);
-#if 1 /*USE_FPU <= 0 */
- if (pgs->ctm.txy_fixed_valid && pgs->char_tm.txy_fixed_valid) {
- penum->ftx = (int)fixed2long(pgs->char_tm.tx_fixed -
- pgs->ctm.tx_fixed);
- penum->fty = (int)fixed2long(pgs->char_tm.ty_fixed -
- pgs->ctm.ty_fixed);
- } else {
-#endif
- double fdx = pgs->char_tm.tx - pgs->ctm.tx;
- double fdy = pgs->char_tm.ty - pgs->ctm.ty;
-
-#define int_bits (arch_sizeof_int * 8 - 1)
- if (!(f_fits_in_bits(fdx, int_bits) &&
- f_fits_in_bits(fdy, int_bits))
- )
- return_error(gs_error_limitcheck);
-#undef int_bits
- penum->ftx = (int)fdx;
- penum->fty = (int)fdy;
- }
- }
- penum->encode_char = pfont->procs.encode_char;
- return 0;
-}
-
-/* Set the suggested oversampling scale for character rendering. */
-private void
-show_set_scale(gs_show_enum * penum)
-{
- /*
- * Decide whether to oversample.
- * We have to decide this each time setcachedevice is called.
- */
- const gs_state *pgs = penum->pgs;
-
- if (penum->charpath_flag == cpm_show &&
- SHOW_IS_DRAWING(penum) &&
- gx_path_is_void_inline(pgs->path) &&
- /* Oversampling rotated characters doesn't work well. */
- (is_fzero2(pgs->char_tm.xy, pgs->char_tm.yx) ||
- is_fzero2(pgs->char_tm.xx, pgs->char_tm.yy))
- ) {
- const gs_font_base *pfont = (gs_font_base *) pgs->font;
- gs_fixed_point extent;
- int code = gs_distance_transform2fixed(&pgs->char_tm,
- pfont->FontBBox.q.x - pfont->FontBBox.p.x,
- pfont->FontBBox.q.y - pfont->FontBBox.p.y,
- &extent);
-
- if (code >= 0) {
- int sx =
- (extent.x == 0 ? 0 :
- any_abs(extent.x) < int2fixed(25) ? 2 :
- any_abs(extent.x) < int2fixed(60) ? 1 :
- 0);
- int sy =
- (extent.y == 0 ? 0 :
- any_abs(extent.y) < int2fixed(25) ? 2 :
- any_abs(extent.y) < int2fixed(60) ? 1 :
- 0);
-
- /* If we oversample at all, make sure we do it */
- /* in both X and Y. */
- if (sx == 0 && sy != 0)
- sx = 1;
- else if (sy == 0 && sx != 0)
- sy = 1;
- penum->log2_suggested_scale.x = sx;
- penum->log2_suggested_scale.y = sy;
- return;
- }
- }
- /* By default, don't scale. */
- penum->log2_suggested_scale.x =
- penum->log2_suggested_scale.y = 0;
-}
-
-/* Set up the cache device and related information. */
-/* Note that we always allocate both cache devices, */
-/* even if we only use one of them. */
-private int
-show_cache_setup(gs_show_enum * penum)
-{
- gs_state *pgs = penum->pgs;
- gs_memory_t *mem = pgs->memory;
- gx_device_memory *dev =
- gs_alloc_struct(mem, gx_device_memory, &st_device_memory,
- "show_cache_setup(dev_cache)");
- gx_device_memory *dev2 =
- gs_alloc_struct(mem, gx_device_memory, &st_device_memory,
- "show_cache_setup(dev_cache2)");
-
- if (dev == 0 || dev2 == 0) {
- gs_free_object(mem, dev2, "show_cache_setup(dev_cache2)");
- gs_free_object(mem, dev, "show_cache_setup(dev_cache)");
- return_error(gs_error_VMerror);
- }
- /*
- * We only initialize the devices for the sake of the GC,
- * (since we have to re-initialize dev as either a mem_mono
- * or a mem_abuf device before actually using it) and also
- * to set its memory pointer.
- */
- gs_make_mem_mono_device(dev, mem, gs_currentdevice_inline(pgs));
- penum->dev_cache = dev;
- gs_make_mem_mono_device(dev2, mem, gs_currentdevice_inline(pgs));
- penum->dev_cache2 = dev2;
- /* Retain these devices, since they are referenced from the enumerator. */
- gx_device_retain((gx_device *)dev, true);
- gx_device_retain((gx_device *)dev2, true);
- return 0;
-}
-
-/* Set the character origin as the origin of the coordinate system. */
-/* Used before rendering characters, and for moving the origin */
-/* in setcachedevice2 when WMode=1. */
-private int
-show_origin_setup(gs_state * pgs, fixed cpt_x, fixed cpt_y,
- gs_char_path_mode charpath_flag)
-{
- if (charpath_flag == cpm_show) {
- /* Round the translation in the graphics state. */
- /* This helps prevent rounding artifacts later. */
- cpt_x = fixed_rounded(cpt_x);
- cpt_y = fixed_rounded(cpt_y);
- }
- /*
- * BuildChar procedures expect the current point to be undefined,
- * so we omit the gx_path_add_point with ctm.t*_fixed.
- */
- return gx_translate_to_fixed(pgs, cpt_x, cpt_y);
-}
-
-/* Default fstack initialization procedure. */
-int
-gs_default_init_fstack(gs_show_enum * penum, gs_font * pfont)
-{
- penum->fstack.depth = -1;
- return 0;
-}
-
-/* Default next-character procedure. */
-int
-gs_default_next_char(gs_show_enum * penum, gs_char * pchr)
-{
- gs_glyph ignore_glyph;
-
- return gs_default_next_glyph(penum, pchr, &ignore_glyph);
-}
-
-/* Default next-glyph procedure. */
-int
-gs_default_next_glyph(gs_show_enum * penum, gs_char * pchr, gs_glyph * pglyph)
-{
- if (penum->index == penum->text.size)
- return 2;
- if (penum->text.operation & TEXT_FROM_SINGLE_GLYPH) {
- /* glyphshow or glyphpath */
- *pchr = gs_no_char;
- *pglyph = penum->text.data.d_glyph;
- } else {
- *pchr = penum->text.data.bytes[penum->index];
- *pglyph = gs_no_glyph;
+ if (gs_object_type(pgs->memory, pte) != &st_gs_show_enum) {
+ /* Use the default implementation. */
+ gx_device *dev = pgs->device;
+ gs_text_params_t text;
+ gs_memory_t *mem = pte->memory;
+ dev_proc_text_begin((*text_begin)) = dev_proc(dev, text_begin);
+
+ text = pte->text;
+ gs_text_release(pte, "show_n_begin");
+ /* Temporarily reset the text_begin procedure to the default. */
+ set_dev_proc(dev, text_begin, gx_default_text_begin);
+ code = gs_text_begin(pgs, &text, mem, &pte);
+ set_dev_proc(dev, text_begin, text_begin);
+ if (code < 0)
+ return code;
}
- penum->index++;
- return 0;
+ /* Now we know pte points to a gs_show_enum. */
+ *penum = *(gs_show_enum *)pte;
+ gs_free_object(pgs->memory, pte, "show_n_begin");
+ return code;
}
diff --git a/gs/src/gschar.h b/gs/src/gschar.h
index 2744c55b8..f6516e18d 100644
--- a/gs/src/gschar.h
+++ b/gs/src/gschar.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1989, 1995, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1989, 1995, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -58,6 +58,7 @@ int gs_show_n_init(P4(gs_show_enum *, gs_state *, const char *, uint)),
gs_charpath_n_init(P5(gs_show_enum *, gs_state *, const char *, uint, bool)),
gs_glyphpath_init(P4(gs_show_enum *, gs_state *, gs_glyph, bool)),
gs_charboxpath_n_init(P5(gs_show_enum *, gs_state *, const char *, uint, bool));
+int gs_show_use_glyph(P2(gs_show_enum *, gs_glyph));
/* After setting up the enumeration, all the string-related routines */
/* work the same way. The client calls gs_show_next until it returns */
@@ -67,19 +68,19 @@ int gs_show_n_init(P4(gs_show_enum *, gs_state *, const char *, uint)),
/* The client must render a character: obtain the code from */
/* gs_show_current_char, do whatever is necessary, and then */
/* call gs_show_next again. */
-#define gs_show_render 1
+#define gs_show_render TEXT_PROCESS_RENDER
/* The client has asked to intervene between characters (kshow). */
/* Obtain the previous and next codes from gs_kshow_previous_char */
/* and gs_kshow_next_char, do whatever is necessary, and then */
/* call gs_show_next again. */
-#define gs_show_kern 2
+#define gs_show_kern TEXT_PROCESS_INTERVENE
/* The client has asked to handle characters individually */
/* (xshow, yshow, xyshow, cshow). Obtain the current code */
/* from gs_show_current_char, do whatever is necessary, and then */
/* call gs_show_next again. */
-#define gs_show_move 3
+#define gs_show_move TEXT_PROCESS_INTERVENE
int gs_show_next(P1(gs_show_enum *));
@@ -89,7 +90,6 @@ gs_char
gs_kshow_next_char(P1(const gs_show_enum *));
gs_font *
gs_show_current_font(P1(const gs_show_enum *));
-int gs_show_restore_font(P1(const gs_show_enum *));
gs_glyph
gs_show_current_glyph(P1(const gs_show_enum *));
@@ -110,7 +110,6 @@ int gs_setcachedevice2_double(P3(gs_show_enum *, gs_state *, const double * /*[1
#define gs_setcachedevice2(penum, pgs, pw2)\
gs_setcachedevice2_float(penum, pgs, pw2)
int gs_setcharwidth(P4(gs_show_enum *, gs_state *, floatp, floatp));
-gs_in_cache_device_t gs_incachedevice(P1(const gs_state *));
/* Return true if we only need the width from the rasterizer */
/* and can short-circuit the full rendering of the character, */
diff --git a/gs/src/gschar0.c b/gs/src/gschar0.c
index b4c2941a5..9ab241517 100644
--- a/gs/src/gschar0.c
+++ b/gs/src/gschar0.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1992, 1993, 1997, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1991, 1992, 1993, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -25,67 +25,68 @@
#include "gsfcmap.h"
#include "gxfixed.h"
#include "gxdevice.h"
-#include "gxdevmem.h" /* for gxchar.h */
-#include "gxchar.h"
#include "gxfont.h"
#include "gxfont0.h"
+#include "gxtext.h"
/* Stack up modal composite fonts, down to a non-modal or base font. */
private int
-gs_stack_modal_fonts(gs_show_enum * penum)
+gs_stack_modal_fonts(gs_text_enum_t *pte)
{
- int fdepth = penum->fstack.depth;
- gs_font *cfont = penum->fstack.items[fdepth].font;
+ int fdepth = pte->fstack.depth;
+ gs_font *cfont = pte->fstack.items[fdepth].font;
while (cfont->FontType == ft_composite) {
gs_font_type0 *const cmfont = (gs_font_type0 *) cfont;
if (!fmap_type_is_modal(cmfont->data.FMapType))
break;
- if (fdepth == max_font_depth)
+ if (fdepth == MAX_FONT_STACK)
return_error(gs_error_invalidfont);
fdepth++;
cfont = cmfont->data.FDepVector[cmfont->data.Encoding[0]];
- penum->fstack.items[fdepth].font = cfont;
- penum->fstack.items[fdepth].index = 0;
+ pte->fstack.items[fdepth].font = cfont;
+ pte->fstack.items[fdepth].index = 0;
if_debug2('j', "[j]stacking depth=%d font=0x%lx\n",
fdepth, (ulong) cfont);
}
- penum->fstack.depth = fdepth;
+ pte->fstack.depth = fdepth;
return 0;
}
/* Initialize the composite font stack for a show enumerator. */
+/* Return an error if the data is not a byte string. */
int
-gs_type0_init_fstack(gs_show_enum * penum, gs_font * pfont)
+gs_type0_init_fstack(gs_text_enum_t *pte, gs_font * pfont)
{
+ if (!(pte->text.operation & (TEXT_FROM_STRING | TEXT_FROM_BYTES)))
+ return_error(gs_error_invalidfont);
if_debug1('j', "[j]stacking depth=0 font=0x%lx\n",
(ulong) pfont);
- penum->fstack.depth = 0;
- penum->fstack.items[0].font = pfont;
- penum->fstack.items[0].index = 0;
- return gs_stack_modal_fonts(penum);
+ pte->fstack.depth = 0;
+ pte->fstack.items[0].font = pfont;
+ pte->fstack.items[0].index = 0;
+ return gs_stack_modal_fonts(pte);
}
/* Select the appropriate descendant of a font. */
-/* Uses free variables: penum. */
+/* Uses free variables: pte. */
/* Uses pdata, uses & updates fdepth, sets pfont. */
#define select_descendant(pfont, pdata, fidx, fdepth)\
- if ( fidx >= pdata->encoding_size )\
+ if (fidx >= pdata->encoding_size)\
return_error(gs_error_rangecheck);\
- if ( fdepth == max_font_depth )\
+ if (fdepth == MAX_FONT_STACK)\
return_error(gs_error_invalidfont);\
pfont = pdata->FDepVector[pdata->Encoding[fidx]];\
- if ( ++fdepth > orig_depth || pfont != penum->fstack.items[fdepth].font )\
- penum->fstack.items[fdepth].font = pfont,\
- changed = 1;\
- penum->fstack.items[fdepth].index = fidx
+ if (++fdepth > orig_depth || pfont != pte->fstack.items[fdepth].font)\
+ pte->fstack.items[fdepth].font = pfont, changed = 1;\
+ pte->fstack.items[fdepth].index = fidx
/* Get the root EscChar of a composite font, which overrides the EscChar */
/* of descendant fonts. */
private uint
-root_esc_char(const gs_show_enum * penum)
+root_esc_char(const gs_text_enum_t *pte)
{
- return ((gs_font_type0 *) (penum->fstack.items[0].font))->data.EscChar;
+ return ((gs_font_type0 *) (pte->fstack.items[0].font))->data.EscChar;
}
/* Get the next character or glyph from a composite string. */
@@ -94,13 +95,12 @@ root_esc_char(const gs_show_enum * penum)
/* If the string is empty, return 2. */
/* If the current (base) font changed, return 1. Otherwise, return 0. */
int
-gs_type0_next_glyph(register gs_show_enum * penum, gs_char * pchr,
- gs_glyph * pglyph)
+gs_type0_next_char_glyph(gs_text_enum_t *pte, gs_char *pchr, gs_glyph *pglyph)
{
- const byte *str = penum->text.data.bytes;
- const byte *p = str + penum->index;
- const byte *end = str + penum->text.size;
- int fdepth = penum->fstack.depth;
+ const byte *str = pte->text.data.bytes;
+ const byte *p = str + pte->index;
+ const byte *end = str + pte->text.size;
+ int fdepth = pte->fstack.depth;
int orig_depth = fdepth;
gs_font *pfont;
@@ -123,10 +123,10 @@ gs_type0_next_glyph(register gs_show_enum * penum, gs_char * pchr,
* reported by Norio Katayama, and confirmed by someone at Adobe.)
*/
- if (penum->index == 0) {
+ if (pte->index == 0) {
int idepth = 0;
- pfont = penum->fstack.items[0].font;
+ pfont = pte->fstack.items[0].font;
for (; pfont->FontType == ft_composite;) {
fmap_type fmt = (pdata = &pfont0->data)->FMapType;
@@ -135,7 +135,7 @@ gs_type0_next_glyph(register gs_show_enum * penum, gs_char * pchr,
chr = *p;
switch (fmt) {
case fmap_escape:
- if (chr != root_esc_char(penum))
+ if (chr != root_esc_char(pte))
break;
need_left(2);
fidx = p[1];
@@ -146,7 +146,7 @@ gs_type0_next_glyph(register gs_show_enum * penum, gs_char * pchr,
idepth, (ulong) pfont);
continue;
case fmap_double_escape:
- if (chr != root_esc_char(penum))
+ if (chr != root_esc_char(pte))
break;
need_left(2);
fidx = p[1];
@@ -177,13 +177,13 @@ gs_type0_next_glyph(register gs_show_enum * penum, gs_char * pchr,
if (idepth != 0) {
int code;
- penum->fstack.depth = idepth;
- code = gs_stack_modal_fonts(penum);
+ pte->fstack.depth = idepth;
+ code = gs_stack_modal_fonts(pte);
if (code < 0)
return code;
- if (penum->fstack.depth > idepth)
+ if (pte->fstack.depth > idepth)
changed = 1;
- orig_depth = fdepth = penum->fstack.depth;
+ orig_depth = fdepth = pte->fstack.depth;
}
}
/* Handle initial escapes or shifts. */
@@ -192,7 +192,7 @@ gs_type0_next_glyph(register gs_show_enum * penum, gs_char * pchr,
return 2;
chr = *p;
while (fdepth > 0) {
- pfont = penum->fstack.items[fdepth - 1].font;
+ pfont = pte->fstack.items[fdepth - 1].font;
pdata = &pfont0->data;
switch (pdata->FMapType) {
default: /* non-modal */
@@ -200,7 +200,7 @@ gs_type0_next_glyph(register gs_show_enum * penum, gs_char * pchr,
continue;
case fmap_escape:
- if (chr != root_esc_char(penum))
+ if (chr != root_esc_char(pte))
break;
need_left(2);
fidx = *++p;
@@ -228,7 +228,7 @@ gs_type0_next_glyph(register gs_show_enum * penum, gs_char * pchr,
continue;
case fmap_double_escape:
- if (chr != root_esc_char(penum))
+ if (chr != root_esc_char(pte))
break;
need_left(2);
fidx = *++p;
@@ -264,7 +264,7 @@ gs_type0_next_glyph(register gs_show_enum * penum, gs_char * pchr,
* simply the first byte of the data.
*/
- while ((pfont = penum->fstack.items[fdepth].font)->FontType == ft_composite) {
+ while ((pfont = pte->fstack.items[fdepth].font)->FontType == ft_composite) {
pdata = &pfont0->data;
switch (pdata->FMapType) {
default: /* can't happen */
@@ -364,7 +364,7 @@ gs_type0_next_glyph(register gs_show_enum * penum, gs_char * pchr,
&fidx, &chr, &glyph);
if (code < 0)
return code;
- penum->cmap_code = code; /* hack for widthshow */
+ pte->cmap_code = code; /* hack for widthshow */
p = str + mindex;
if_debug3('J', "[J]CMap returns %d, chr=0x%lx, glyph=0x%lx\n",
code, (ulong) chr, (ulong) glyph);
@@ -391,12 +391,12 @@ done:
*pglyph = glyph;
/* Update the pointer into the original string, but only if */
/* we didn't switch over to parsing a code from a CMap. */
- if (str == penum->text.data.bytes)
- penum->index = p - str;
- penum->fstack.depth = fdepth;
+ if (str == pte->text.data.bytes)
+ pte->index = p - str;
+ pte->fstack.depth = fdepth;
if_debug4('J', "[J]depth=%d font=0x%lx index=%d changed=%d\n",
- fdepth, (ulong) penum->fstack.items[fdepth].font,
- penum->fstack.items[fdepth].index, changed);
+ fdepth, (ulong) pte->fstack.items[fdepth].font,
+ pte->fstack.items[fdepth].index, changed);
return changed;
#undef pfont0
}
diff --git a/gs/src/gscie.c b/gs/src/gscie.c
index 577f31988..328090786 100644
--- a/gs/src/gscie.c
+++ b/gs/src/gscie.c
@@ -24,10 +24,10 @@
#include "gserrors.h"
#include "gsstruct.h"
#include "gsmatrix.h" /* for gscolor2.h */
-#include "gxcspace.h"
+#include "gxcspace.h" /* for gxcie.c */
#include "gscolor2.h" /* for gs_set/currentcolorrendering */
-#include "gscie.h"
#include "gxarith.h"
+#include "gxcie.h"
#include "gxdevice.h" /* for gxcmap.h */
#include "gxcmap.h"
#include "gzstate.h"
@@ -63,19 +63,18 @@ private_st_joint_caches();
int j;\
\
for (j = 0; j < countof(pcache); j++) {\
+ cie_cache_floats *pcf = &(pcache)[j].floats;\
int i;\
gs_for_loop_params lp;\
\
- gs_cie_cache_init(&(pcache)[j].floats.params, &lp,\
- &(domains)[j], cname);\
+ gs_cie_cache_init(&pcf->params, &lp, &(domains)[j], cname);\
for (i = 0; i < gx_cie_cache_size; lp.init += lp.step, i++) {\
- pcache[j].floats.values[i] =\
- (*(rprocs)->procs[j])(lp.init, pcie);\
+ pcf->values[i] = (*(rprocs)->procs[j])(lp.init, pcie);\
if_debug5('C', "[C]%s[%d,%d] = %g => %g\n",\
- cname, j, i, lp.init, pcache[j].floats.values[i]);\
+ cname, j, i, lp.init, pcf->values[i]);\
}\
- (pcache)[j].floats.params.is_identity =\
- (rprocs)->procs[j] == (dprocs).procs[j];\
+ pcf->params.is_identity =\
+ (rprocs)->procs[j] == (dprocs).procs[j];\
}\
END
@@ -396,7 +395,7 @@ gx_install_cie_abc(gs_cie_abc *pcie, gs_state * pgs)
}
int
-gx_install_CIEDEFG(gs_color_space * pcs, gs_state * pgs)
+gx_install_CIEDEFG(const gs_color_space * pcs, gs_state * pgs)
{
gs_cie_defg *pcie = pcs->params.defg;
@@ -407,7 +406,7 @@ gx_install_CIEDEFG(gs_color_space * pcs, gs_state * pgs)
}
int
-gx_install_CIEDEF(gs_color_space * pcs, gs_state * pgs)
+gx_install_CIEDEF(const gs_color_space * pcs, gs_state * pgs)
{
gs_cie_def *pcie = pcs->params.def;
@@ -418,13 +417,13 @@ gx_install_CIEDEF(gs_color_space * pcs, gs_state * pgs)
}
int
-gx_install_CIEABC(gs_color_space * pcs, gs_state * pgs)
+gx_install_CIEABC(const gs_color_space * pcs, gs_state * pgs)
{
return gx_install_cie_abc(pcs->params.abc, pgs);
}
int
-gx_install_CIEA(gs_color_space * pcs, gs_state * pgs)
+gx_install_CIEA(const gs_color_space * pcs, gs_state * pgs)
{
gs_cie_a *pcie = pcs->params.a;
int i;
diff --git a/gs/src/gsciemap.c b/gs/src/gsciemap.c
index 9f9a8127f..593d672ad 100644
--- a/gs/src/gsciemap.c
+++ b/gs/src/gsciemap.c
@@ -21,9 +21,9 @@
#include "math_.h"
#include "gx.h"
#include "gserrors.h"
-#include "gxcspace.h"
-#include "gscie.h"
+#include "gxcspace.h" /* for gxcie.c */
#include "gxarith.h"
+#include "gxcie.h"
#include "gxdevice.h" /* for gxcmap.h */
#include "gxcmap.h"
#include "gxistate.h"
diff --git a/gs/src/gscolor.c b/gs/src/gscolor.c
index 27b844ef5..d91844aba 100644
--- a/gs/src/gscolor.c
+++ b/gs/src/gscolor.c
@@ -38,20 +38,16 @@ public_st_client_color();
public_st_transfer_map();
/* GC procedures */
-#define mptr ((gx_transfer_map *)vptr)
private
-ENUM_PTRS_BEGIN(transfer_map_enum_ptrs) return 0;
-
-case 0:
-ENUM_RETURN((mptr->proc == 0 ? mptr->closure.data : 0));
+ENUM_PTRS_WITH(transfer_map_enum_ptrs, gx_transfer_map *mptr) return 0;
+case 0: ENUM_RETURN((mptr->proc == 0 ? mptr->closure.data : 0));
ENUM_PTRS_END
-private RELOC_PTRS_BEGIN(transfer_map_reloc_ptrs)
+private RELOC_PTRS_WITH(transfer_map_reloc_ptrs, gx_transfer_map *mptr)
{
if (mptr->proc == 0)
RELOC_PTR(gx_transfer_map, closure.data);
}
RELOC_PTRS_END
-#undef mptr
/* Initialize colors with 1, or 3, or 4 paint components. */
/* (These are only used by setcolorspace.) */
diff --git a/gs/src/gscolor2.c b/gs/src/gscolor2.c
index c73467a8a..38834d786 100644
--- a/gs/src/gscolor2.c
+++ b/gs/src/gscolor2.c
@@ -180,10 +180,16 @@ const gs_color_space_type gs_color_space_type_Indexed = {
/* GC procedures. */
-#define pcs ((gs_color_space *)vptr)
+private uint
+indexed_table_size(const gs_color_space *pcs)
+{
+ return (pcs->params.indexed.hival + 1) *
+ cs_num_components((const gs_color_space *)
+ &pcs->params.indexed.base_space);
+}
private
-ENUM_PTRS_BEGIN(cs_Indexed_enum_ptrs)
+ENUM_PTRS_WITH(cs_Indexed_enum_ptrs, gs_color_space *pcs)
{
return ENUM_USING(*pcs->params.indexed.base_space.type->stype,
&pcs->params.indexed.base_space,
@@ -192,29 +198,28 @@ ENUM_PTRS_BEGIN(cs_Indexed_enum_ptrs)
case 0:
if (pcs->params.indexed.use_proc)
ENUM_RETURN((void *)pcs->params.indexed.lookup.map);
-else {
- pcs->params.indexed.lookup.table.size =
- (pcs->params.indexed.hival + 1) *
- cs_num_components((const gs_color_space *)
- &pcs->params.indexed.base_space);
- ENUM_RETURN_CONST_STRING_PTR(gs_color_space,
- params.indexed.lookup.table);
-}
+else
+ return ENUM_CONST_STRING2(pcs->params.indexed.lookup.table.data,
+ indexed_table_size(pcs));
ENUM_PTRS_END
-private RELOC_PTRS_BEGIN(cs_Indexed_reloc_ptrs)
+private RELOC_PTRS_WITH(cs_Indexed_reloc_ptrs, gs_color_space *pcs)
{
RELOC_USING(*pcs->params.indexed.base_space.type->stype,
&pcs->params.indexed.base_space,
sizeof(gs_base_color_space));
if (pcs->params.indexed.use_proc)
RELOC_PTR(gs_color_space, params.indexed.lookup.map);
- else
- RELOC_CONST_STRING_PTR(gs_color_space, params.indexed.lookup.table);
+ else {
+ gs_const_string table;
+
+ table.data = pcs->params.indexed.lookup.table.data;
+ table.size = indexed_table_size(pcs);
+ RELOC_CONST_STRING_VAR(table);
+ pcs->params.indexed.lookup.table.data = table.data;
+ }
}
RELOC_PTRS_END
-#undef pcs
-
/* Return the base space of an Indexed color space. */
private const gs_color_space *
gx_base_space_Indexed(const gs_color_space * pcs)
diff --git a/gs/src/gscparam.c b/gs/src/gscparam.c
index 72c04cff4..d46fd95ec 100644
--- a/gs/src/gscparam.c
+++ b/gs/src/gscparam.c
@@ -101,7 +101,7 @@ gs_c_param_list_write(gs_c_param_list * plist, gs_memory_t * mem)
plist->target = 0; /* not used for writing */
plist->count = 0;
plist->any_requested = false;
- gs_c_param_list_rewrite(plist);
+ gs_c_param_list_write_more(plist);
}
/* Set the target of a list. Only relevant for reading. */
@@ -112,9 +112,9 @@ gs_c_param_list_set_target(gs_c_param_list *plist, gs_param_list *target)
}
/* Re-enable a list for writing, without clearing it. */
-/* gs_c_parram_list_write must have been called previously. */
+/* gs_c_param_list_write must have been called previously. */
void
-gs_c_param_list_rewrite(gs_c_param_list * plist)
+gs_c_param_list_write_more(gs_c_param_list * plist)
{
plist->procs = &c_write_procs;
plist->coll_type = gs_param_collection_dict_any;
diff --git a/gs/src/gscpm.h b/gs/src/gscpm.h
index a50b922d6..821289eb9 100644
--- a/gs/src/gscpm.h
+++ b/gs/src/gscpm.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1995, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -24,6 +24,7 @@
typedef enum {
cpm_show, /* *show (default, must be 0) */
+ cpm_charwidth, /* stringwidth rmoveto (not standard PS) */
cpm_false_charpath, /* false charpath */
cpm_true_charpath, /* true charpath */
cpm_false_charboxpath, /* false charboxpath (not standard PS) */
diff --git a/gs/src/gscrd.c b/gs/src/gscrd.c
index 83511db75..2ab078490 100644
--- a/gs/src/gscrd.c
+++ b/gs/src/gscrd.c
@@ -38,20 +38,15 @@ extern_gs_lib_device_list();
/* Allocator structure type */
public_st_cie_render1();
-#define pcrd ((gs_cie_render *)vptr)
private
-ENUM_PTRS_BEGIN(cie_render1_enum_ptrs) return 0;
-
-case 0:
-return ENUM_OBJ(pcrd->client_data);
-case 1:
-return ENUM_OBJ(pcrd->RenderTable.lookup.table);
-case 2:
-return (pcrd->RenderTable.lookup.table ?
- ENUM_CONST_STRING(&pcrd->TransformPQR.proc_data) :
- 0);
+ENUM_PTRS_WITH(cie_render1_enum_ptrs, gs_cie_render *pcrd) return 0;
+case 0: return ENUM_OBJ(pcrd->client_data);
+case 1: return ENUM_OBJ(pcrd->RenderTable.lookup.table);
+case 2: return (pcrd->RenderTable.lookup.table ?
+ ENUM_CONST_STRING(&pcrd->TransformPQR.proc_data) :
+ 0);
ENUM_PTRS_END
-private RELOC_PTRS_BEGIN(cie_render1_reloc_ptrs);
+private RELOC_PTRS_WITH(cie_render1_reloc_ptrs, gs_cie_render *pcrd);
RELOC_OBJ_VAR(pcrd->client_data);
if (pcrd->RenderTable.lookup.table)
{
@@ -59,7 +54,6 @@ RELOC_OBJ_VAR(pcrd->RenderTable.lookup.table);
RELOC_CONST_STRING_VAR(pcrd->TransformPQR.proc_data);
}
RELOC_PTRS_END
-#undef pcrd
/* Default CRD procedures. */
diff --git a/gs/src/gscscie.c b/gs/src/gscscie.c
index b5c83995f..cddf36fec 100644
--- a/gs/src/gscscie.c
+++ b/gs/src/gscscie.c
@@ -25,7 +25,7 @@
#include "gsmatrix.h" /* for gscolor2.h */
#include "gxcspace.h"
#include "gscolor2.h" /* for gs_set/currentcolorrendering */
-#include "gscie.h"
+#include "gxcie.h"
#include "gxarith.h"
#include "gxdevice.h" /* for gxcmap.h */
#include "gxcmap.h"
@@ -42,10 +42,6 @@ private_st_cie_def();
private_st_cie_defg();
/* Define the CIE color space types. */
-/* We use CIExxx rather than CIEBasedxxx in some places because */
-/* gcc under VMS only retains 23 characters of procedure names, */
-/* and DEC C truncates all identifiers at 31 characters. */
-extern cs_proc_init_color(gx_init_CIE);
private cs_proc_concrete_space(gx_concrete_space_CIE);
private cs_proc_install_cspace(gx_install_CIE);
@@ -53,9 +49,6 @@ private cs_proc_install_cspace(gx_install_CIE);
gs_private_st_ptrs1(st_color_space_CIEDEFG, gs_base_color_space,
"gs_color_space(CIEDEFG)", cs_CIEDEFG_enum_ptrs, cs_CIEDEFG_reloc_ptrs,
params.defg);
-extern cs_proc_restrict_color(gx_restrict_CIEDEFG);
-extern cs_proc_concretize_color(gx_concretize_CIEDEFG);
-extern cs_proc_install_cspace(gx_install_CIEDEFG);
private cs_proc_adjust_cspace_count(gx_adjust_cspace_CIEDEFG);
const gs_color_space_type gs_color_space_type_CIEDEFG = {
gs_color_space_index_CIEDEFG, true, true,
@@ -72,9 +65,6 @@ const gs_color_space_type gs_color_space_type_CIEDEFG = {
gs_private_st_ptrs1(st_color_space_CIEDEF, gs_base_color_space,
"gs_color_space(CIEDEF)", cs_CIEDEF_enum_ptrs, cs_CIEDEF_reloc_ptrs,
params.def);
-extern cs_proc_restrict_color(gx_restrict_CIEDEF);
-extern cs_proc_concretize_color(gx_concretize_CIEDEF);
-extern cs_proc_install_cspace(gx_install_CIEDEF);
private cs_proc_adjust_cspace_count(gx_adjust_cspace_CIEDEF);
const gs_color_space_type gs_color_space_type_CIEDEF = {
gs_color_space_index_CIEDEF, true, true,
@@ -91,11 +81,7 @@ const gs_color_space_type gs_color_space_type_CIEDEF = {
gs_private_st_ptrs1(st_color_space_CIEABC, gs_base_color_space,
"gs_color_space(CIEABC)", cs_CIEABC_enum_ptrs, cs_CIEABC_reloc_ptrs,
params.abc);
-cs_proc_restrict_color(gx_restrict_CIEABC);
-cs_proc_concretize_color(gx_concretize_CIEABC);
-cs_proc_install_cspace(gx_install_CIEABC);
private cs_proc_adjust_cspace_count(gx_adjust_cspace_CIEABC);
-extern cs_proc_remap_color(gx_remap_CIEABC);
const gs_color_space_type gs_color_space_type_CIEABC = {
gs_color_space_index_CIEABC, true, true,
&st_color_space_CIEABC, gx_num_components_3,
@@ -111,9 +97,6 @@ const gs_color_space_type gs_color_space_type_CIEABC = {
gs_private_st_ptrs1(st_color_space_CIEA, gs_base_color_space,
"gs_color_space(CIEA)", cs_CIEA_enum_ptrs, cs_CIEA_reloc_ptrs,
params.a);
-cs_proc_restrict_color(gx_restrict_CIEA);
-cs_proc_concretize_color(gx_concretize_CIEA);
-cs_proc_install_cspace(gx_install_CIEA);
private cs_proc_adjust_cspace_count(gx_adjust_cspace_CIEA);
const gs_color_space_type gs_color_space_type_CIEA = {
gs_color_space_index_CIEA, true, true,
diff --git a/gs/src/gscsepr.c b/gs/src/gscsepr.c
index 689a8cd93..5f7c88c82 100644
--- a/gs/src/gscsepr.c
+++ b/gs/src/gscsepr.c
@@ -55,10 +55,8 @@ const gs_color_space_type gs_color_space_type_Separation = {
/* GC procedures */
-#define pcs ((gs_color_space *)vptr)
-
private
-ENUM_PTRS_BEGIN(cs_Separation_enum_ptrs)
+ENUM_PTRS_WITH(cs_Separation_enum_ptrs, gs_color_space *pcs)
{
return ENUM_USING(*pcs->params.separation.alt_space.type->stype,
&pcs->params.separation.alt_space,
@@ -66,7 +64,7 @@ ENUM_PTRS_BEGIN(cs_Separation_enum_ptrs)
}
ENUM_PTR(0, gs_color_space, params.separation.map);
ENUM_PTRS_END
-private RELOC_PTRS_BEGIN(cs_Separation_reloc_ptrs)
+private RELOC_PTRS_WITH(cs_Separation_reloc_ptrs, gs_color_space *pcs)
{
RELOC_PTR(gs_color_space, params.separation.map);
RELOC_USING(*pcs->params.separation.alt_space.type->stype,
@@ -75,8 +73,6 @@ private RELOC_PTRS_BEGIN(cs_Separation_reloc_ptrs)
}
RELOC_PTRS_END
-#undef pcs
-
/* Get the alternate space for a Separation space. */
private const gs_color_space *
gx_alt_space_Separation(const gs_color_space * pcs)
diff --git a/gs/src/gscspace.c b/gs/src/gscspace.c
index 548b6015b..719b17470 100644
--- a/gs/src/gscspace.c
+++ b/gs/src/gscspace.c
@@ -24,6 +24,7 @@
#include "gsstruct.h"
#include "gsccolor.h"
#include "gsutil.h" /* for gs_next_ids */
+#include "gxcmap.h"
#include "gxcspace.h"
#include "gxistate.h"
@@ -33,15 +34,6 @@
* the PostScript operator procedures (setcmykcolor, etc.) for dealing with
* it.
*/
-extern cs_proc_remap_color(gx_remap_DeviceGray);
-extern cs_proc_concretize_color(gx_concretize_DeviceGray);
-extern cs_proc_remap_concrete_color(gx_remap_concrete_DGray);
-extern cs_proc_remap_color(gx_remap_DeviceRGB);
-extern cs_proc_concretize_color(gx_concretize_DeviceRGB);
-extern cs_proc_remap_concrete_color(gx_remap_concrete_DRGB);
-extern cs_proc_remap_color(gx_remap_DeviceCMYK);
-extern cs_proc_concretize_color(gx_concretize_DeviceCMYK);
-extern cs_proc_remap_concrete_color(gx_remap_concrete_DCMYK);
private const gs_color_space_type gs_color_space_type_DeviceGray = {
gs_color_space_index_DeviceGray, true, true,
&st_base_color_space, gx_num_components_1,
@@ -262,17 +254,17 @@ gx_no_adjust_cspace_count(const gs_color_space * pcs, int delta)
/* GC procedures */
-#define pcs ((gs_color_space *)vptr)
private
ENUM_PTRS_BEGIN_PROC(color_space_enum_ptrs)
{
+ EV_CONST gs_color_space *pcs = vptr;
+
return ENUM_USING(*pcs->type->stype, vptr, size, index);
ENUM_PTRS_END_PROC
}
private
-RELOC_PTRS_BEGIN(color_space_reloc_ptrs)
+RELOC_PTRS_WITH(color_space_reloc_ptrs, gs_color_space *pcs)
{
RELOC_USING(*pcs->type->stype, vptr, size);
}
RELOC_PTRS_END
-#undef pcs
diff --git a/gs/src/gsdevice.c b/gs/src/gsdevice.c
index ace76786b..8908ef2b9 100644
--- a/gs/src/gsdevice.c
+++ b/gs/src/gsdevice.c
@@ -22,9 +22,10 @@
#include "memory_.h" /* for memcpy */
#include "string_.h"
#include "gx.h"
+#include "gp.h"
#include "gscdefs.h" /* for gs_lib_device_list */
#include "gserrors.h"
-#include "gp.h"
+#include "gsfname.h"
#include "gsstruct.h"
#include "gspath.h" /* gs_initclip prototype */
#include "gspaint.h" /* gs_erasepage prototype */
@@ -34,6 +35,7 @@
#include "gxcmap.h"
#include "gxdevice.h"
#include "gxdevmem.h"
+#include "gxiodev.h"
/* Include the extern for the device list. */
extern_gs_lib_device_list();
@@ -64,19 +66,15 @@ gx_device_free_local(gx_device *dev)
}
/* GC procedures */
-#define fdev ((gx_device_forward *)vptr)
private
-ENUM_PTRS_BEGIN(device_forward_enum_ptrs) return 0;
-
-case 0:
-ENUM_RETURN(gx_device_enum_ptr(fdev->target));
+ENUM_PTRS_WITH(device_forward_enum_ptrs, gx_device_forward *fdev) return 0;
+case 0: ENUM_RETURN(gx_device_enum_ptr(fdev->target));
ENUM_PTRS_END
-private RELOC_PTRS_BEGIN(device_forward_reloc_ptrs)
+private RELOC_PTRS_WITH(device_forward_reloc_ptrs, gx_device_forward *fdev)
{
fdev->target = gx_device_reloc_ptr(fdev->target, gcst);
}
RELOC_PTRS_END
-#undef fdev
/*
* Structure descriptors. These must follow the procedures, because
@@ -629,60 +627,155 @@ gx_device_copy_params(gx_device *dev, const gx_device *target)
#undef COPY_PARAM
+/*
+ * Parse the output file name for a device, recognizing "-" and "|command",
+ * and also detecting and validating any %nnd format for inserting the
+ * page count. If a format is present, store a pointer to its last
+ * character in *pfmt, otherwise store 0 there. Note that an empty name
+ * is currently allowed.
+ */
+int
+gx_parse_output_file_name(gs_parsed_file_name_t *pfn, const char **pfmt,
+ const char *fname, uint fnlen)
+{
+ int code = gs_parse_file_name(pfn, fname, fnlen);
+ bool have_format = false, field = 0;
+ int width[2], int_width = sizeof(int) * 3, w = 0;
+ uint i;
+
+ *pfmt = 0;
+ if (fnlen == 0) { /* allow null name */
+ pfn->memory = 0;
+ pfn->iodev = NULL;
+ pfn->fname = 0; /* irrelevant since length = 0 */
+ pfn->len = 0;
+ return 0;
+ }
+ if (code < 0)
+ return code;
+ if (!pfn->iodev) {
+ if (!strcmp(pfn->fname, "-")) {
+ pfn->iodev = gs_findiodevice((const byte *)"%stdout", 7);
+ pfn->fname = NULL;
+ } else if (pfn->fname[0] == '|') {
+ pfn->iodev = gs_findiodevice((const byte *)"%pipe", 5);
+ pfn->fname++, pfn->len--;
+ } else
+ pfn->iodev = iodev_default;
+ if (!pfn->iodev)
+ return_error(gs_error_undefinedfilename);
+ }
+ if (!pfn->fname)
+ return 0;
+ /* Scan the file name for a format string, and validate it if present. */
+ width[0] = width[1] = 0;
+ for (i = 0; i < pfn->len; ++i)
+ if (pfn->fname[i] == '%') {
+ if (i + 1 < pfn->len && pfn->fname[i + 1] == '%')
+ continue;
+ if (have_format) /* more than one % */
+ return_error(gs_error_rangecheck);
+ have_format = true;
+ sw:
+ if (++i == pfn->len)
+ return_error(gs_error_rangecheck);
+ switch (pfn->fname[i]) {
+ case 'l':
+ int_width = sizeof(long) * 3;
+ case ' ': case '#': case '+': case '-':
+ goto sw;
+ case '.':
+ if (field)
+ return_error(gs_error_rangecheck);
+ field = 1;
+ continue;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ width[field] = width[field] * 10 + pfn->fname[i] - '0';
+ goto sw;
+ case 'd': case 'i': case 'u': case 'o': case 'x': case 'X':
+ *pfmt = &pfn->fname[i];
+ continue;
+ default:
+ return_error(gs_error_rangecheck);
+ }
+ }
+ if (have_format) {
+ /* Calculate a conservative maximum width. */
+ w = max(width[0], width[1]);
+ w = max(w, int_width) + 5;
+ }
+ if (strlen(pfn->iodev->dname) + pfn->len + w >= gp_file_name_sizeof)
+ return_error(gs_error_rangecheck);
+ return 0;
+}
+
/* Open the output file for a device. */
int
-gx_device_open_output_file(const gx_device * dev, const char *fname,
+gx_device_open_output_file(const gx_device * dev, char *fname,
bool binary, bool positionable, FILE ** pfile)
{
+ gs_parsed_file_name_t parsed;
+ const char *fmt;
char pfname[gp_file_name_sizeof];
- char pfmt[10];
- const char *fsrc = fname;
- char *fdest = pfname;
- long count1 = dev->PageCount + 1;
+ int code = gx_parse_output_file_name(&parsed, &fmt, fname, strlen(fname));
- if (!strcmp(fname, "-")) {
+ if (code < 0)
+ return code;
+ if (parsed.iodev && !strcmp(parsed.iodev->dname, "%stdout%")) {
+ if (parsed.fname)
+ return_error(gs_error_undefinedfilename);
*pfile = stdout;
/* Force stdout to binary. */
return gp_setmode_binary(*pfile, true);
}
-/****** SHOULD RETURN rangecheck IF FILE NAME TOO LONG ******/
- for (; *fsrc; ++fsrc) {
- if (*fsrc != '%') {
- *fdest++ = *fsrc;
- continue;
- }
- if (fsrc[1] == '%') {
- *fdest++ = '%';
- ++fsrc;
- continue;
- } {
- char *ffmt = pfmt;
- bool use_long;
-
-/****** SHOULD CHECK FOR FORMAT TOO LONG ******/
- while (!isalpha(*fsrc))
- *ffmt++ = *fsrc++;
- if ((use_long = (*fsrc == 'l')))
- *ffmt++ = *fsrc++;
- *ffmt = *fsrc;
- ffmt[1] = 0;
-/****** SHOULD CHECK FOR LEGAL FORMATS ******/
- sprintf(fdest, pfmt, (use_long ? count1 : (int)count1));
- fdest += strlen(fdest);
- }
+ if (!parsed.fname)
+ return_error(gs_error_undefinedfilename);
+ if (fmt) {
+ long count1 = dev->PageCount + 1;
+
+ while (*fmt != 'l' && *fmt != '%')
+ --fmt;
+ if (*fmt == 'l')
+ sprintf(pfname, parsed.fname, count1);
+ else
+ sprintf(pfname, parsed.fname, (int)count1);
+ parsed.fname = pfname;
+ parsed.len = strlen(parsed.fname);
}
- *fdest = 0;
- if (positionable && pfname[0] != '|') {
+ if (positionable || (parsed.iodev && parsed.iodev != iodev_default)) {
char fmode[4];
strcpy(fmode, gp_fmode_wb);
- strcat(fmode, "+");
- *pfile = gp_fopen(pfname, fmode);
+ if (positionable)
+ strcat(fmode, "+");
+ code = parsed.iodev->procs.fopen(parsed.iodev, parsed.fname, fmode,
+ pfile, NULL, 0);
if (*pfile)
return 0;
}
- *pfile = gp_open_printer(pfname, binary);
+ *pfile = gp_open_printer((fmt ? pfname : fname), binary);
if (*pfile)
return 0;
return_error(gs_error_invalidfileaccess);
}
+
+/* Close the output file for a device. */
+int
+gx_device_close_output_file(const gx_device * dev, const char *fname,
+ FILE *file)
+{
+ gs_parsed_file_name_t parsed;
+ const char *fmt;
+ int code = gx_parse_output_file_name(&parsed, &fmt, fname, strlen(fname));
+
+ if (code < 0)
+ return code;
+ if (!strcmp(parsed.iodev->dname, "%stdout%"))
+ return 0;
+ /* NOTE: fname is unsubstituted if the name has any %nnd formats. */
+ if (parsed.iodev != iodev_default)
+ return parsed.iodev->procs.fclose(parsed.iodev, file);
+ gp_close_printer(file, parsed.fname);
+ return 0;
+}
diff --git a/gs/src/gsdevice.h b/gs/src/gsdevice.h
index 64147a17f..fb84cc320 100644
--- a/gs/src/gsdevice.h
+++ b/gs/src/gsdevice.h
@@ -101,7 +101,6 @@ int gs_flushpage(P1(gs_state *));
int gs_copypage(P1(gs_state *));
int gs_output_page(P3(gs_state *, int, int));
int gs_nulldevice(P1(gs_state *));
-int gs_opendevice(P1(gx_device *dev));
int gs_setdevice(P2(gs_state *, gx_device *));
int gs_setdevice_no_erase(P2(gs_state *, gx_device *)); /* returns 1 */
/* if erasepage required */
diff --git a/gs/src/gsdevmem.c b/gs/src/gsdevmem.c
index a252b2a76..fb00204aa 100644
--- a/gs/src/gsdevmem.c
+++ b/gs/src/gsdevmem.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1995, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -22,6 +22,7 @@
#include "memory_.h"
#include "gx.h"
#include "gserrors.h"
+#include "gsdevice.h" /* for prototypes */
#include "gxarith.h"
#include "gxdevice.h"
#include "gxdevmem.h"
diff --git a/gs/src/gsdll32w.lnk b/gs/src/gsdll32w.lnk
new file mode 100644
index 000000000..12c60ffb6
--- /dev/null
+++ b/gs/src/gsdll32w.lnk
@@ -0,0 +1,11 @@
+EXPORT gsdll_revision.1
+EXPORT gsdll_init.2
+EXPORT gsdll_execute_begin.3
+EXPORT gsdll_execute_cont.4
+EXPORT gsdll_execute_end.5
+EXPORT gsdll_exit.6
+EXPORT gsdll_lock_device.7
+EXPORT gsdll_copy_dib.8
+EXPORT gsdll_copy_palette.9
+EXPORT gsdll_draw.10
+EXPORT gsdll_get_bitmap_row.11
diff --git a/gs/src/gsdparam.c b/gs/src/gsdparam.c
index d872f9d88..606b66f72 100644
--- a/gs/src/gsdparam.c
+++ b/gs/src/gsdparam.c
@@ -22,6 +22,7 @@
#include "string_.h" /* for strlen */
#include "gx.h"
#include "gserrors.h"
+#include "gsdevice.h" /* for prototypes */
#include "gsparam.h"
#include "gxdevice.h"
#include "gxfixed.h"
diff --git a/gs/src/gsdsrc.c b/gs/src/gsdsrc.c
index da522fe51..2c32ec4b9 100644
--- a/gs/src/gsdsrc.c
+++ b/gs/src/gsdsrc.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1997, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -27,9 +27,8 @@
/* GC descriptor */
public_st_data_source();
-#define psrc ((gs_data_source_t *)vptr)
private
-ENUM_PTRS_BEGIN(data_source_enum_ptrs)
+ENUM_PTRS_WITH(data_source_enum_ptrs, gs_data_source_t *psrc)
{
if (psrc->type == data_source_type_string)
ENUM_RETURN_CONST_STRING_PTR(gs_data_source_t, data.str);
@@ -39,7 +38,7 @@ ENUM_PTRS_BEGIN(data_source_enum_ptrs)
ENUM_RETURN_PTR(gs_data_source_t, data.str.data);
}
ENUM_PTRS_END
-private RELOC_PTRS_BEGIN(data_source_reloc_ptrs)
+private RELOC_PTRS_WITH(data_source_reloc_ptrs, gs_data_source_t *psrc)
{
if (psrc->type == data_source_type_string)
RELOC_CONST_STRING_PTR(gs_data_source_t, data.str);
@@ -49,7 +48,6 @@ private RELOC_PTRS_BEGIN(data_source_reloc_ptrs)
RELOC_PTR(gs_data_source_t, data.str.data);
}
RELOC_PTRS_END
-#undef psrc
/* Access data from a string or a byte object. */
/* Does *not* check bounds. */
diff --git a/gs/src/gserror.h b/gs/src/gserror.h
index 2784fc096..8c113d777 100644
--- a/gs/src/gserror.h
+++ b/gs/src/gserror.h
@@ -22,10 +22,8 @@
#ifndef gserror_INCLUDED
# define gserror_INCLUDED
-#ifdef DEBUG
int gs_log_error(P3(int, const char *, int));
-
-#else
+#ifndef DEBUG
# define gs_log_error(err, file, line) (err)
#endif
#define gs_note_error(err) gs_log_error(err, __FILE__, __LINE__)
diff --git a/gs/src/gsfcmap.c b/gs/src/gsfcmap.c
index a2f447a27..3fceff3ec 100644
--- a/gs/src/gsfcmap.c
+++ b/gs/src/gsfcmap.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1997, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -28,11 +28,10 @@ public_st_cmap();
public_st_code_map();
public_st_code_map_element();
-#define pcmap ((gx_code_map *)vptr)
/* Because code maps can be elements of arrays, */
/* their enum_ptrs procedure must never return 0 prematurely. */
private
-ENUM_PTRS_BEGIN(code_map_enum_ptrs) return 0;
+ENUM_PTRS_WITH(code_map_enum_ptrs, gx_code_map *pcmap) return 0;
ENUM_PTR(0, gx_code_map, cmap);
case 1:
switch (pcmap->type)
@@ -46,7 +45,7 @@ switch (pcmap->type)
ENUM_RETURN_PTR(gx_code_map, data.subtree);
}
ENUM_PTRS_END
-private RELOC_PTRS_BEGIN(code_map_reloc_ptrs);
+private RELOC_PTRS_WITH(code_map_reloc_ptrs, gx_code_map *pcmap);
switch (pcmap->type) {
case cmap_subtree:
RELOC_PTR(gx_code_map, data.subtree);
@@ -56,7 +55,6 @@ switch (pcmap->type) {
}
RELOC_PTR(gx_code_map, cmap);
RELOC_PTRS_END
-#undef pcmap
/* CIDSystemInfo structure descriptors */
private_st_cid_system_info();
diff --git a/gs/src/zfname.c b/gs/src/gsfname.c
index 1611b3825..4c3b82d17 100644
--- a/gs/src/zfname.c
+++ b/gs/src/gsfname.c
@@ -19,37 +19,34 @@
/* File name utilities */
#include "memory_.h"
-#include "ghost.h"
-#include "oper.h"
-#include "ialloc.h"
-#include "stream.h"
-#include "gxiodev.h" /* must come after stream.h */
-#include "fname.h"
+#include "gserror.h"
+#include "gserrors.h"
+#include "gsmemory.h"
+#include "gstypes.h"
+#include "gsfname.h"
+#include "gxiodev.h"
/* Parse a file name into device and individual name. */
/* The device may be NULL, or the name may be NULL, but not both. */
/* According to the Adobe documentation, %device and %device% */
/* are equivalent; both return name==NULL. */
int
-parse_file_name(const ref * op, parsed_file_name * pfn)
+gs_parse_file_name(gs_parsed_file_name_t * pfn, const char *pname, uint len)
{
- const byte *pname;
- uint len, dlen;
- const byte *pdelim;
+ uint dlen;
+ const char *pdelim;
gx_io_device *iodev;
- check_read_type(*op, t_string);
- len = r_size(op);
- pname = op->value.const_bytes;
if (len == 0)
- return_error(e_undefinedfilename);
+ return_error(gs_error_undefinedfilename); /* null name not allowed */
if (pname[0] != '%') { /* no device */
+ pfn->memory = 0;
pfn->iodev = NULL;
- pfn->fname = (const char *)pname;
+ pfn->fname = pname;
pfn->len = len;
return 0;
}
- pdelim = (const byte *)memchr(pname + 1, '%', len - 1);
+ pdelim = memchr(pname + 1, '%', len - 1);
if (pdelim == NULL) /* %device */
dlen = len;
else if (pdelim[1] == 0) { /* %device% */
@@ -59,43 +56,49 @@ parse_file_name(const ref * op, parsed_file_name * pfn)
dlen = pdelim - pname;
pdelim++, len--;
}
- iodev = gs_findiodevice(pname, dlen);
+ iodev = gs_findiodevice((const byte *)pname, dlen);
if (iodev == 0)
- return_error(e_undefinedfilename);
+ return_error(gs_error_undefinedfilename);
+ pfn->memory = 0;
pfn->iodev = iodev;
- pfn->fname = (const char *)pdelim;
+ pfn->fname = pdelim;
pfn->len = len - dlen;
return 0;
}
/* Parse a real (non-device) file name and convert to a C string. */
int
-parse_real_file_name(const ref * op, parsed_file_name * pfn, client_name_t cname)
+gs_parse_real_file_name(gs_parsed_file_name_t * pfn, const char *pname,
+ uint len, gs_memory_t *mem, client_name_t cname)
{
- int code = parse_file_name(op, pfn);
+ int code = gs_parse_file_name(pfn, pname, len);
if (code < 0)
return code;
if (pfn->len == 0)
- return_error(e_invalidfileaccess); /* device only */
- return terminate_file_name(pfn, cname);
+ return_error(gs_error_invalidfileaccess); /* device only */
+ return gs_terminate_file_name(pfn, mem, cname);
}
/* Convert a file name to a C string by adding a null terminator. */
int
-terminate_file_name(parsed_file_name * pfn, client_name_t cname)
+gs_terminate_file_name(gs_parsed_file_name_t * pfn, gs_memory_t *mem,
+ client_name_t cname)
{
uint len = pfn->len;
- ref fnref;
- const char *fname;
+ char *fname;
if (pfn->iodev == NULL) /* no device */
pfn->iodev = iodev_default;
- fnref.value.const_bytes = (const byte *)pfn->fname;
- r_set_size(&fnref, len);
- fname = ref_to_string(&fnref, imemory, cname);
+ if (pfn->memory)
+ return 0; /* already copied */
+ /* Copy the file name to a C string. */
+ fname = (char *)gs_alloc_string(mem, len + 1, cname);
if (fname == 0)
- return_error(e_VMerror);
+ return_error(gs_error_VMerror);
+ memcpy(fname, pfn->fname, len);
+ fname[len] = 0;
+ pfn->memory = mem;
pfn->fname = fname;
pfn->len = len + 1; /* null terminator */
return 0;
@@ -103,8 +106,9 @@ terminate_file_name(parsed_file_name * pfn, client_name_t cname)
/* Free a file name that was copied to a C string. */
void
-free_file_name(parsed_file_name * pfn, client_name_t cname)
+gs_free_file_name(gs_parsed_file_name_t * pfn, client_name_t cname)
{
if (pfn->fname != 0)
- ifree_const_string((const byte *)pfn->fname, pfn->len, cname);
+ gs_free_const_string(pfn->memory, (const byte *)pfn->fname, pfn->len,
+ cname);
}
diff --git a/gs/src/fname.h b/gs/src/gsfname.h
index 8e3a8e735..5d10fa0d7 100644
--- a/gs/src/fname.h
+++ b/gs/src/gsfname.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1993, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -17,32 +17,42 @@
*/
-/* Requires gxiodev.h */
-#ifndef fname_INCLUDED
-# define fname_INCLUDED
+#ifndef gsfname_INCLUDED
+# define gsfname_INCLUDED
/*
* Define a structure for representing a parsed file name, consisting of
* an IODevice name in %'s, a file name, or both. Note that the file name
* may be either a gs_string (no terminator) or a C string (null terminator).
+ *
+ * NOTE: You must use parse_[real_]file_name to construct parsed_file_names.
+ * Do not simply allocate the structure and fill it in.
*/
-typedef struct parsed_file_name_s {
+#ifndef gx_io_device_DEFINED
+# define gx_io_device_DEFINED
+typedef struct gx_io_device_s gx_io_device;
+#endif
+
+typedef struct gs_parsed_file_name_s {
+ gs_memory_t *memory; /* allocator for terminated name string */
gx_io_device *iodev;
const char *fname;
uint len;
-} parsed_file_name;
+} gs_parsed_file_name_t;
/* Parse a file name into device and individual name. */
-int parse_file_name(P2(const ref *, parsed_file_name *));
+int gs_parse_file_name(P3(gs_parsed_file_name_t *, const char *, uint));
/* Parse a real (non-device) file name and convert to a C string. */
-int parse_real_file_name(P3(const ref *, parsed_file_name *, client_name_t));
+int gs_parse_real_file_name(P5(gs_parsed_file_name_t *, const char *, uint,
+ gs_memory_t *, client_name_t));
/* Convert a file name to a C string by adding a null terminator. */
-int terminate_file_name(P2(parsed_file_name *, client_name_t));
+int gs_terminate_file_name(P3(gs_parsed_file_name_t *, gs_memory_t *,
+ client_name_t));
/* Free a file name that was copied to a C string. */
-void free_file_name(P2(parsed_file_name *, client_name_t));
+void gs_free_file_name(P2(gs_parsed_file_name_t *, client_name_t));
-#endif /* fname_INCLUDED */
+#endif /* gsfname_INCLUDED */
diff --git a/gs/src/gsfont.c b/gs/src/gsfont.c
index 54b397e87..a081aad4f 100644
--- a/gs/src/gsfont.c
+++ b/gs/src/gsfont.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1989, 1995, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1989, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -22,13 +22,14 @@
#include "memory_.h"
#include "gserrors.h"
#include "gsstruct.h"
+#include "gsutil.h"
#include "gxfixed.h"
#include "gxmatrix.h"
#include "gzstate.h" /* must precede gxdevice */
#include "gxdevice.h" /* must precede gxfont */
-#include "gschar.h"
#include "gxfont.h"
#include "gxfcache.h"
+#include "gxpath.h" /* for default implementation */
/* Imported procedures */
void gs_purge_font_from_char_caches(P2(gs_font_dir *, const gs_font *));
@@ -47,6 +48,24 @@ void gs_purge_font_from_char_caches(P2(gs_font_dir *, const gs_font *));
#define cmax_SMALL 500 /* cmax - # of cached chars */
#define blimit_SMALL 100 /* blimit/upper - max size of a single cached char */
+/* Define a default procedure vector for fonts. */
+const gs_font_procs gs_font_procs_default = {
+ gs_no_define_font, /* (actually a default) */
+ gs_no_make_font, /* (actually a default) */
+ gs_default_font_info,
+ gs_no_encode_char,
+ gs_no_enumerate_glyph,
+ gs_default_glyph_info,
+ gs_no_glyph_outline,
+ gs_default_init_fstack,
+ gs_default_next_char_glyph,
+ gs_no_build_char,
+ {
+ 0, /* glyph_name */
+ 0 /* known_encode */
+ } /* callbacks */
+};
+
private_st_font_dir();
private struct_proc_enum_ptrs(font_enum_ptrs);
private struct_proc_reloc_ptrs(font_reloc_ptrs);
@@ -74,10 +93,10 @@ public_st_gs_font_ptr_element();
* relocation phase of the GC. */
/* Font directory GC procedures */
-#define dir ((gs_font_dir *)vptr)
private
-ENUM_PTRS_BEGIN(font_dir_enum_ptrs)
-{ /* Enumerate pointers from cached characters to f/m pairs, */
+ENUM_PTRS_WITH(font_dir_enum_ptrs, gs_font_dir *dir)
+{
+ /* Enumerate pointers from cached characters to f/m pairs, */
/* and mark the cached character glyphs. */
/* See gxfcache.h for why we do this here. */
uint cci = index - st_font_dir_max_ptrs;
@@ -96,8 +115,9 @@ ENUM_PTRS_BEGIN(font_dir_enum_ptrs)
if (cc != 0 && !--count) {
(*dir->ccache.mark_glyph)
(cc->code, dir->ccache.mark_glyph_data);
- dir->enum_index = cci;
- dir->enum_offset = offset;
+ /****** HACK: break const. We'll fix this someday. ******/
+ ((gs_font_dir *)dir)->enum_index = cci;
+ ((gs_font_dir *)dir)->enum_offset = offset;
ENUM_RETURN(cc_pair(cc) - cc->pair_index);
}
}
@@ -107,9 +127,9 @@ return 0;
font_dir_do_ptrs(e1)
#undef e1
ENUM_PTRS_END
-private RELOC_PTRS_BEGIN(font_dir_reloc_ptrs);
- /* Relocate the pointers from cached characters to f/m pairs. */
- /* See gxfcache.h for why we do this here. */
+private RELOC_PTRS_WITH(font_dir_reloc_ptrs, gs_font_dir *dir);
+ /* Relocate the pointers from cached characters to f/m pairs. */
+ /* See gxfcache.h for why we do this here. */
{
int chi;
@@ -123,17 +143,15 @@ private RELOC_PTRS_BEGIN(font_dir_reloc_ptrs);
cc->pair_index);
}
}
- /* We have to relocate the cached characters before we */
- /* relocate dir->ccache.table! */
+ /* We have to relocate the cached characters before we */
+ /* relocate dir->ccache.table! */
RELOC_PTR(gs_font_dir, orig_fonts);
#define r1(i,elt) RELOC_PTR(gs_font_dir, elt);
font_dir_do_ptrs(r1)
#undef r1
RELOC_PTRS_END
-#undef dir
/* GC procedures for fonts */
-#define pfont ((gs_font *)vptr)
/*
* When we finalize a base font, we unlink it from the orig_fonts list;
* when we finalize a scaled font, we unlink it from scaled_fonts.
@@ -142,20 +160,24 @@ RELOC_PTRS_END
void
gs_font_finalize(void *vptr)
{
+ gs_font *const pfont = vptr;
gs_font **ppfirst;
gs_font *next = pfont->next;
gs_font *prev = pfont->prev;
if_debug4('u', "[u]unlinking font 0x%lx, base=0x%lx, prev=0x%lx, next=0x%lx\n",
(ulong) pfont, (ulong) pfont->base, (ulong) prev, (ulong) next);
+ /* Notify clients that the font is being freed. */
+ gs_notify_all(&pfont->notify_list, NULL);
if (pfont->dir == 0)
ppfirst = 0;
else if (pfont->base == pfont)
ppfirst = &pfont->dir->orig_fonts;
- else { /*
- * Track the number of cached scaled fonts. Only decrement the
- * count if we didn't do this already in gs_makefont.
- */
+ else {
+ /*
+ * Track the number of cached scaled fonts. Only decrement the
+ * count if we didn't do this already in gs_makefont.
+ */
if (next || prev || pfont->dir->scaled_fonts == pfont)
pfont->dir->ssize--;
ppfirst = &pfont->dir->scaled_fonts;
@@ -171,30 +193,24 @@ gs_font_finalize(void *vptr)
prev->next = next;
} else if (ppfirst != 0 && *ppfirst == pfont)
*ppfirst = next;
+ gs_notify_release(&pfont->notify_list);
}
private
-ENUM_PTRS_BEGIN(font_enum_ptrs) return 0;
-
+ENUM_PTRS_WITH(font_enum_ptrs, gs_font *pfont) return ENUM_USING(st_gs_notify_list, &pfont->notify_list, sizeof(gs_notify_list_t), index - 5);
/* We don't enumerate next or prev of base fonts. */
/* See above for details. */
-case 0:
-ENUM_RETURN((pfont->base == pfont ? 0 : pfont->next));
-case 1:
-ENUM_RETURN((pfont->base == pfont ? 0 : pfont->prev));
-ENUM_PTR(2, gs_font, dir);
-ENUM_PTR(3, gs_font, base);
-ENUM_PTR(4, gs_font, client_data);
+case 0: ENUM_RETURN((pfont->base == pfont ? 0 : pfont->next));
+case 1: ENUM_RETURN((pfont->base == pfont ? 0 : pfont->prev));
+ENUM_PTR3(2, gs_font, dir, base, client_data);
ENUM_PTRS_END
-private RELOC_PTRS_BEGIN(font_reloc_ptrs);
+private RELOC_PTRS_WITH(font_reloc_ptrs, gs_font *pfont);
+RELOC_USING(st_gs_notify_list, &pfont->notify_list, sizeof(gs_notify_list_t));
/* We *do* always relocate next and prev. */
/* Again, see above for details. */
RELOC_PTR(gs_font, next);
RELOC_PTR(gs_font, prev);
-RELOC_PTR(gs_font, dir);
-RELOC_PTR(gs_font, base);
-RELOC_PTR(gs_font, client_data);
+RELOC_PTR3(gs_font, dir, base, client_data);
RELOC_PTRS_END
-#undef pfont
/* Allocate a font directory */
private bool
@@ -232,9 +248,9 @@ gs_font_dir *
gs_font_dir_alloc2_limits(gs_memory_t * struct_mem, gs_memory_t * bits_mem,
uint smax, uint bmax, uint mmax, uint cmax, uint upper)
{
- register gs_font_dir *pdir =
- gs_alloc_struct(struct_mem, gs_font_dir, &st_font_dir,
- "font_dir_alloc(dir)");
+ gs_font_dir *pdir =
+ gs_alloc_struct(struct_mem, gs_font_dir, &st_font_dir,
+ "font_dir_alloc(dir)");
int code;
if (pdir == 0)
@@ -252,11 +268,79 @@ gs_font_dir_alloc2_limits(gs_memory_t * struct_mem, gs_memory_t * bits_mem,
return pdir;
}
-/* Macro for linking an element at the head of a chain */
-#define link_first(first, elt)\
- if ( (elt->next = first) != NULL ) first->prev = elt;\
- elt->prev = 0;\
- first = elt
+/* Allocate and minimally initialize a font. */
+gs_font *
+gs_font_alloc(gs_memory_t *mem, gs_memory_type_ptr_t pstype,
+ const gs_font_procs *procs, gs_font_dir *dir,
+ client_name_t cname)
+{
+ gs_font *pfont = gs_alloc_struct(mem, gs_font, pstype, cname);
+
+ if (pfont == 0)
+ return 0;
+ pfont->next = pfont->prev = 0;
+ pfont->memory = mem;
+ pfont->dir = dir;
+ gs_notify_init(&pfont->notify_list, gs_memory_stable(mem));
+ pfont->id = gs_next_ids(1);
+ pfont->base = pfont;
+ pfont->client_data = 0;
+ /* not FontMatrix, FontType */
+ pfont->BitmapWidths = false;
+ pfont->ExactSize = pfont->InBetweenSize = pfont->TransformedChar =
+ fbit_use_outlines;
+ pfont->WMode = 0;
+ pfont->PaintType = 0;
+ pfont->StrokeWidth = 0;
+ pfont->procs = *procs;
+ /* not key_name, font_name */
+ return pfont;
+}
+/* Allocate and minimally initialize a base font. */
+gs_font_base *
+gs_font_base_alloc(gs_memory_t *mem, gs_memory_type_ptr_t pstype,
+ const gs_font_procs *procs, gs_font_dir *dir,
+ client_name_t cname)
+{
+ gs_font_base *pfont =
+ (gs_font_base *)gs_font_alloc(mem, pstype, procs, dir, cname);
+
+ if (pfont == 0)
+ return 0;
+ pfont->FontBBox.p.x = pfont->FontBBox.p.y =
+ pfont->FontBBox.q.x = pfont->FontBBox.q.y = 0;
+ uid_set_invalid(&pfont->UID);
+ pfont->encoding_index = pfont->nearest_encoding_index = -1;
+ return pfont;
+}
+
+/*
+ * Register/unregister a client for notification by a font. Currently
+ * the clients are only notified when a font is freed. Note that any
+ * such client must unregister itself when *it* is freed.
+ */
+int
+gs_font_notify_register(gs_font *font, gs_notify_proc_t proc, void *proc_data)
+{
+ return gs_notify_register(&font->notify_list, proc, proc_data);
+}
+int
+gs_font_notify_unregister(gs_font *font, gs_notify_proc_t proc, void *proc_data)
+{
+ return gs_notify_unregister(&font->notify_list, proc, proc_data);
+}
+
+/* Link an element at the head of a chain. */
+private void
+font_link_first(gs_font **pfirst, gs_font *elt)
+{
+ gs_font *first = elt->next = *pfirst;
+
+ if (first)
+ first->prev = elt;
+ elt->prev = 0;
+ *pfirst = elt;
+}
/* definefont */
/* Use this only for original (unscaled) fonts! */
@@ -273,17 +357,11 @@ gs_definefont(gs_font_dir * pdir, gs_font * pfont)
pfont->base = 0;
return code;
}
- link_first(pdir->orig_fonts, pfont);
+ font_link_first(&pdir->orig_fonts, pfont);
if_debug2('m', "[m]defining font 0x%lx, next=0x%lx\n",
(ulong) pfont, (ulong) pfont->next);
return 0;
}
-/* Default (vacuous) definefont handler. */
-int
-gs_no_define_font(gs_font_dir * pdir, gs_font * pfont)
-{
- return 0;
-}
/* scalefont */
int
@@ -301,7 +379,7 @@ int
gs_makefont(gs_font_dir * pdir, const gs_font * pfont,
const gs_matrix * pmat, gs_font ** ppfont)
{
-#define pbfont ((const gs_font_base *)pfont)
+ const gs_font_base *const pbfont = (const gs_font_base *)pfont;
int code;
gs_font *prev = 0;
gs_font *pf_out = pdir->scaled_fonts;
@@ -366,12 +444,13 @@ gs_makefont(gs_font_dir * pdir, const gs_font * pfont,
if (code < 0)
return code;
if (can_cache) {
- if (pdir->ssize >= pdir->smax && prev != 0) { /*
- * We must discard a cached scaled font.
- * prev points to the last (oldest) font.
- * (We can't free it, because there might be
- * other references to it.)
- */
+ if (pdir->ssize >= pdir->smax && prev != 0) {
+ /*
+ * We must discard a cached scaled font.
+ * prev points to the last (oldest) font.
+ * (We can't free it, because there might be
+ * other references to it.)
+ */
if_debug1('m', "[m]discarding font 0x%lx\n",
(ulong) prev);
if (prev->prev != 0)
@@ -391,43 +470,13 @@ gs_makefont(gs_font_dir * pdir, const gs_font * pfont,
}
}
pdir->ssize++;
- link_first(pdir->scaled_fonts, pf_out);
+ font_link_first(&pdir->scaled_fonts, pf_out);
} else { /* Prevent garbage pointers. */
pf_out->next = pf_out->prev = 0;
}
if_debug2('m', "[m]new font=0x%lx can_cache=%s\n",
(ulong) * ppfont, (can_cache ? "true" : "false"));
return 1;
-#undef pbfont
-}
-/* Default (vacuous) makefont handler. */
-int
-gs_no_make_font(gs_font_dir * pdir, const gs_font * pfont,
- const gs_matrix * pmat, gs_font ** ppfont)
-{
- return 0;
-}
-/* Makefont handler for base fonts, which must copy the XUID. */
-int
-gs_base_make_font(gs_font_dir * pdir, const gs_font * pfont,
- const gs_matrix * pmat, gs_font ** ppfont)
-{
-#define pbfont ((gs_font_base *)*ppfont)
- if (uid_is_XUID(&pbfont->UID)) {
- uint xsize = uid_XUID_size(&pbfont->UID);
- long *xvalues = (long *)
- gs_alloc_byte_array(pbfont->memory, xsize, sizeof(long),
- "gs_base_make_font(XUID)");
-
- if (xvalues == 0)
- return_error(gs_error_VMerror);
- memcpy(xvalues, uid_XUID_values(&pbfont->UID),
- xsize * sizeof(long));
-
- pbfont->UID.xvalues = xvalues;
- }
-#undef pbfont
- return 0;
}
/* Set the current font. This is provided only for the benefit of cshow, */
@@ -550,3 +599,200 @@ gs_purge_font(gs_font * pfont)
gs_purge_font_from_char_caches(pdir, pfont);
}
+
+/* ---------------- Default font procedures ---------------- */
+
+/* ------ Font-level procedures ------ */
+
+/* Default (vacuous) definefont handler. */
+int
+gs_no_define_font(gs_font_dir * pdir, gs_font * pfont)
+{
+ return 0;
+}
+
+/* Default (vacuous) makefont handler. */
+int
+gs_no_make_font(gs_font_dir * pdir, const gs_font * pfont,
+ const gs_matrix * pmat, gs_font ** ppfont)
+{
+ return 0;
+}
+/* Makefont handler for base fonts, which must copy the XUID. */
+int
+gs_base_make_font(gs_font_dir * pdir, const gs_font * pfont,
+ const gs_matrix * pmat, gs_font ** ppfont)
+{
+ gs_font_base *const pbfont = (gs_font_base *)*ppfont;
+
+ if (uid_is_XUID(&pbfont->UID)) {
+ uint xsize = uid_XUID_size(&pbfont->UID);
+ long *xvalues = (long *)
+ gs_alloc_byte_array(pbfont->memory, xsize, sizeof(long),
+ "gs_base_make_font(XUID)");
+
+ if (xvalues == 0)
+ return_error(gs_error_VMerror);
+ memcpy(xvalues, uid_XUID_values(&pbfont->UID),
+ xsize * sizeof(long));
+
+ pbfont->UID.xvalues = xvalues;
+ }
+ return 0;
+}
+
+/* Default font info procedure */
+int
+gs_default_font_info(gs_font *font, const gs_point *pscale, int members,
+ gs_font_info_t *info)
+{
+ int wmode = font->WMode;
+ gs_font_base *bfont = (gs_font_base *)font;
+ gs_point scale;
+ gs_matrix smat;
+ const gs_matrix *pmat;
+
+ if (pscale == 0) {
+ scale.x = scale.y = 0;
+ pmat = 0;
+ } else {
+ scale = *pscale;
+ gs_make_scaling(scale.x, scale.y, &smat);
+ pmat = &smat;
+ }
+ info->members = 0;
+ if (members & FONT_INFO_FLAGS)
+ info->Flags_returned = 0;
+ if (font->FontType == ft_composite)
+ return 0; /* nothing available */
+ if ((members & FONT_INFO_FLAGS) &&
+ (info->Flags_requested & FONT_IS_FIXED_WIDTH)
+ ) {
+ /*
+ * Scan the glyph space to compute the fixed width if any.
+ */
+ gs_glyph notdef = gs_no_glyph;
+ gs_glyph glyph;
+ int fixed_width = 0;
+ int index, code;
+
+ for (index = 0;
+ (code = font->procs.enumerate_glyph(font, &index, GLYPH_SPACE_NAME, &glyph)) >= 0 &&
+ index != 0;
+ ) {
+ gs_glyph_info_t glyph_info;
+ gs_const_string gnstr;
+
+ code = font->procs.glyph_info(font, glyph, pmat,
+ (GLYPH_INFO_WIDTH0 << wmode),
+ &glyph_info);
+ if (code < 0)
+ return code;
+ if (notdef == gs_no_glyph) {
+ gnstr.data = (const byte *)
+ bfont->procs.callbacks.glyph_name(glyph, &gnstr.size);
+ if (gnstr.size == 7 && !memcmp(gnstr.data, ".notdef", 7)) {
+ notdef = glyph;
+ info->MissingWidth = glyph_info.width[wmode].x;
+ info->members |= FONT_INFO_MISSING_WIDTH;
+ }
+ }
+ if (glyph_info.width[wmode].y != 0)
+ fixed_width = min_int;
+ else if (fixed_width == 0)
+ fixed_width = glyph_info.width[wmode].x;
+ else if (glyph_info.width[wmode].x != fixed_width)
+ fixed_width = min_int;
+ }
+ if (code < 0)
+ return code;
+ if (fixed_width > 0) {
+ info->Flags |= FONT_IS_FIXED_WIDTH;
+ info->members |= FONT_INFO_AVG_WIDTH | FONT_INFO_MAX_WIDTH |
+ FONT_INFO_MISSING_WIDTH;
+ info->AvgWidth = info->MaxWidth = info->MissingWidth = fixed_width;
+ }
+ info->Flags_returned |= FONT_IS_FIXED_WIDTH;
+ }
+ return 0;
+}
+
+/* ------ Glyph-level procedures ------ */
+
+/* Dummy character encoding procedure */
+gs_glyph
+gs_no_encode_char(gs_font *pfont, gs_char chr, gs_glyph_space_t glyph_space)
+{
+ return gs_no_glyph;
+}
+
+/* Dummy glyph enumeration procedure */
+int
+gs_no_enumerate_glyph(gs_font *font, int *pindex, gs_glyph_space_t glyph_space,
+ gs_glyph *pglyph)
+{
+ return_error(gs_error_undefined);
+}
+
+/* Default glyph info procedure */
+int
+gs_default_glyph_info(gs_font *font, gs_glyph glyph, const gs_matrix *pmat,
+ int members, gs_glyph_info_t *info)
+{
+ gx_path *ppath = gx_path_alloc(font->memory, "glyph_path");
+ int returned = 0;
+ int code;
+
+ if (ppath == 0)
+ return_error(gs_error_VMerror);
+ code = gx_path_add_point(ppath, fixed_0, fixed_0);
+ if (code < 0)
+ goto out;
+ code = font->procs.glyph_outline(font, glyph, pmat, ppath);
+ if (code < 0)
+ goto out;
+ if (members & GLYPH_INFO_WIDTHS) {
+ int wmode = font->WMode;
+ int wmask = GLYPH_INFO_WIDTH0 << wmode;
+
+ if (members & wmask) {
+ gs_fixed_point pt;
+
+ code = gx_path_current_point(ppath, &pt);
+ if (code < 0)
+ goto out;
+ info->width[wmode].x = fixed2float(pt.x);
+ info->width[wmode].y = fixed2float(pt.y);
+ returned |= wmask;
+ }
+ }
+ if (members & GLYPH_INFO_BBOX) {
+ gs_fixed_rect bbox;
+
+ code = gx_path_bbox(ppath, &bbox);
+ if (code < 0)
+ goto out;
+ info->bbox.p.x = fixed2float(bbox.p.x);
+ info->bbox.p.y = fixed2float(bbox.p.y);
+ info->bbox.q.x = fixed2float(bbox.q.x);
+ info->bbox.q.y = fixed2float(bbox.q.y);
+ returned |= GLYPH_INFO_BBOX;
+ }
+ if (members & GLYPH_INFO_NUM_PIECES) {
+ info->num_pieces = 0;
+ returned |= GLYPH_INFO_NUM_PIECES;
+ }
+ returned |= members & GLYPH_INFO_PIECES; /* no pieces stored */
+ out:
+ gx_path_free(ppath, "gs_default_glyph_bbox");
+ info->members = returned;
+ return code;
+}
+
+/* Dummy glyph outline procedure */
+int
+gs_no_glyph_outline(gs_font *font, gs_glyph glyph, const gs_matrix *pmat,
+ gx_path *ppath)
+{
+ return_error(gs_error_undefined);
+}
diff --git a/gs/src/gsfont0.c b/gs/src/gsfont0.c
index 905e7eb95..c0d2103b8 100644
--- a/gs/src/gsfont0.c
+++ b/gs/src/gsfont0.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1994, 1996, 1997 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1994, 1996, 1997, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -26,7 +26,6 @@
#include "gsmatrix.h"
#include "gxdevice.h"
#include "gxdevmem.h"
-#include "gxchar.h"
#include "gxfcache.h" /* gs_font_dir */
#include "gxfont.h"
#include "gxfont0.h"
@@ -36,25 +35,25 @@ private struct_proc_enum_ptrs(font_type0_enum_ptrs);
private struct_proc_reloc_ptrs(font_type0_reloc_ptrs);
public_st_gs_font_type0();
-#define pfont ((gs_font_type0 *)vptr)
private
-ENUM_PTRS_BEGIN(font_type0_enum_ptrs) ENUM_PREFIX(st_gs_font, gs_type0_data_max_ptrs);
-
+ENUM_PTRS_WITH(font_type0_enum_ptrs, gs_font_type0 *pfont)
+ENUM_PREFIX(st_gs_font, gs_type0_data_max_ptrs);
ENUM_PTR(0, gs_font_type0, data.Encoding);
ENUM_PTR(1, gs_font_type0, data.FDepVector);
case 2:
switch (pfont->data.FMapType)
{
case fmap_SubsVector:
-ENUM_RETURN_CONST_STRING_PTR(gs_font_type0,
- data.SubsVector);
+ ENUM_RETURN_CONST_STRING_PTR(gs_font_type0,
+ data.SubsVector);
case fmap_CMap:
-ENUM_RETURN_PTR(gs_font_type0, data.CMap);
+ ENUM_RETURN_PTR(gs_font_type0, data.CMap);
default:
-ENUM_RETURN(0);
+ ENUM_RETURN(0);
}
ENUM_PTRS_END
-private RELOC_PTRS_BEGIN(font_type0_reloc_ptrs) RELOC_PREFIX(st_gs_font);
+private RELOC_PTRS_WITH(font_type0_reloc_ptrs, gs_font_type0 *pfont)
+RELOC_PREFIX(st_gs_font);
RELOC_PTR(gs_font_type0, data.Encoding);
RELOC_PTR(gs_font_type0, data.FDepVector);
switch (pfont->data.FMapType)
@@ -69,7 +68,6 @@ break;
;
}
RELOC_PTRS_END
-#undef pfont
/* Adjust a composite font by concatenating a given matrix */
/* to the FontMatrix of all descendant composite fonts. */
diff --git a/gs/src/gsfunc.c b/gs/src/gsfunc.c
index 49dbcff9e..ad6f3b7d7 100644
--- a/gs/src/gsfunc.c
+++ b/gs/src/gsfunc.c
@@ -22,7 +22,7 @@
#include "gserrors.h"
#include "gxfunc.h"
-/* GC descriptor */
+/* GC descriptors */
public_st_function();
/* Generic free_params implementation. */
@@ -39,7 +39,7 @@ fn_common_free(gs_function_t * pfn, bool free_params, gs_memory_t * mem)
{
if (free_params)
gs_function_free_params(pfn, mem);
- gs_free_object(mem, pfn, "fn_xxx_free");
+ gs_free_object(mem, pfn, "fn_common_free");
}
/* Check the values of m, n, Domain, and (if supplied) Range. */
@@ -59,3 +59,86 @@ fn_check_mnDR(const gs_function_params_t * params, int m, int n)
return_error(gs_error_rangecheck);
return 0;
}
+
+/* Get the monotonicity of a function over its Domain. */
+int
+fn_domain_is_monotonic(const gs_function_t *pfn, gs_function_effort_t effort)
+{
+#define MAX_M 16 /* arbitrary */
+ float lower[MAX_M], upper[MAX_M];
+ int i;
+
+ if (pfn->params.m > MAX_M)
+ return gs_error_undefined;
+ for (i = 0; i < pfn->params.m; ++i) {
+ lower[i] = pfn->params.Domain[2 * i];
+ upper[i] = pfn->params.Domain[2 * i + 1];
+ }
+ return gs_function_is_monotonic(pfn, lower, upper, effort);
+}
+
+/* ---------------- Vanilla functions ---------------- */
+
+/* GC descriptor */
+private_st_function_Va();
+
+/*
+ * Test whether a Vanilla function is monotonic. (This information is
+ * provided at function definition time.)
+ */
+private int
+fn_Va_is_monotonic(const gs_function_t * pfn_common,
+ const float *lower, const float *upper,
+ gs_function_effort_t effort)
+{
+ const gs_function_Va_t *const pfn =
+ (const gs_function_Va_t *)pfn_common;
+
+ return pfn->params.is_monotonic;
+}
+
+/* Free the parameters of a Vanilla function. */
+void
+gs_function_Va_free_params(gs_function_Va_params_t * params,
+ gs_memory_t * mem)
+{
+ gs_free_object(mem, params->eval_data, "eval_data");
+ fn_common_free_params((gs_function_params_t *) params, mem);
+}
+
+/* Allocate and initialize a Vanilla function. */
+int
+gs_function_Va_init(gs_function_t ** ppfn,
+ const gs_function_Va_params_t * params,
+ gs_memory_t * mem)
+{
+ static const gs_function_head_t function_Va_head = {
+ function_type_Vanilla,
+ {
+ NULL, /* filled in from params */
+ (fn_is_monotonic_proc_t) fn_Va_is_monotonic,
+ (fn_free_params_proc_t) gs_function_Va_free_params,
+ fn_common_free
+ }
+ };
+ int code;
+
+ *ppfn = 0; /* in case of error */
+ code = fn_check_mnDR((const gs_function_params_t *)params, 1, params->n);
+ if (code < 0)
+ return code;
+ {
+ gs_function_Va_t *pfn =
+ gs_alloc_struct(mem, gs_function_Va_t, &st_function_Va,
+ "gs_function_Va_init");
+
+ if (pfn == 0)
+ return_error(gs_error_VMerror);
+ pfn->params = *params;
+ pfn->head = function_Va_head;
+ pfn->head.procs.evaluate = params->eval_proc;
+ pfn->head.is_monotonic = params->is_monotonic;
+ *ppfn = (gs_function_t *) pfn;
+ }
+ return 0;
+}
diff --git a/gs/src/gsfunc.h b/gs/src/gsfunc.h
index 30f3fe762..e31513a15 100644
--- a/gs/src/gsfunc.h
+++ b/gs/src/gsfunc.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1997, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -42,6 +42,13 @@ typedef int gs_function_type_t;
int n; /* # of outputs */\
const float *Range /* 2 x n, optional except for type 0 */
+/* Define calculation effort values (currently only used for monotonicity). */
+typedef enum {
+ EFFORT_EASY = 0,
+ EFFORT_MODERATE = 1,
+ EFFORT_ESSENTIAL = 2
+} gs_function_effort_t;
+
/* Define a generic function, for use as the target type of pointers. */
typedef struct gs_function_params_s {
gs_function_params_common;
@@ -52,17 +59,21 @@ typedef int (*fn_evaluate_proc_t)(P3(const gs_function_t * pfn,
typedef int (*fn_is_monotonic_proc_t)(P4(const gs_function_t * pfn,
const float *lower,
const float *upper,
- bool must_know));
+ gs_function_effort_t effort));
typedef void (*fn_free_params_proc_t)(P2(gs_function_params_t * params,
gs_memory_t * mem));
typedef void (*fn_free_proc_t)(P3(gs_function_t * pfn,
bool free_params, gs_memory_t * mem));
-typedef struct gs_function_head_s {
- gs_function_type_t type;
+typedef struct gs_function_procs_s {
fn_evaluate_proc_t evaluate;
fn_is_monotonic_proc_t is_monotonic;
fn_free_params_proc_t free_params;
fn_free_proc_t free;
+} gs_function_procs_t;
+typedef struct gs_function_head_s {
+ gs_function_type_t type;
+ gs_function_procs_t procs;
+ bool is_monotonic; /* cached when function is created */
} gs_function_head_t;
struct gs_function_s {
gs_function_head_t head;
@@ -107,24 +118,64 @@ void gs_function_XxYy_free_params(P2(gs_function_XxYy_params_t *params,
/* Evaluate a function. */
#define gs_function_evaluate(pfn, in, out)\
- (*(pfn)->head.evaluate)(pfn, in, out)
+ (*(pfn)->head.procs.evaluate)(pfn, in, out)
/*
* Test whether a function is monotonic on a given (closed) interval. If
- * must_know is true, returns 0 for false, 1 for true, gs_error_rangecheck
- * if any part of the interval is outside the function's domain; if
- * must_know is false, may also return gs_error_undefined to mean "can't
- * determine quickly". If lower[i] > upper[i], the result is not defined.
+ * the test requires too much effort, the procedure may return
+ * gs_error_undefined; normally, it returns 0 for false, >0 for true,
+ * gs_error_rangecheck if any part of the interval is outside the function's
+ * domain. If lower[i] > upper[i], the result is not defined.
+ *
+ * Note that this is a very unsophisticated test: it returns false for
+ * situations where a function is monotonic in individual inputs and/or
+ * outputs but not for all inputs and/or outputs in the same direction. We
+ * only use it for fast checks.
*/
-#define gs_function_is_monotonic(pfn, lower, upper, must_know)\
- (*(pfn)->head.is_monotonic)(pfn, lower, upper, must_know)
+#define gs_function_is_monotonic(pfn, lower, upper, effort)\
+ (*(pfn)->head.procs.is_monotonic)(pfn, lower, upper, effort)
+#define FN_MONOTONIC_INCREASING 1
+#define FN_MONOTONIC_DECREASING 2
/* Free function parameters. */
#define gs_function_free_params(pfn, mem)\
- (*(pfn)->head.free_params)(&(pfn)->params, mem)
+ (*(pfn)->head.procs.free_params)(&(pfn)->params, mem)
/* Free a function's implementation, optionally including its parameters. */
#define gs_function_free(pfn, free_params, mem)\
- (*(pfn)->head.free)(pfn, free_params, mem)
+ (*(pfn)->head.procs.free)(pfn, free_params, mem)
+
+/* ---------------- Vanilla functions ---------------- */
+
+/*
+ * The simplest type of functions, these just store closure data.
+ * The client provides the evaluation procedure.
+ */
+
+#define function_type_Vanilla (-1)
+
+typedef struct gs_function_Va_params_s {
+ gs_function_params_common;
+ fn_evaluate_proc_t eval_proc;
+ void *eval_data;
+ bool is_monotonic;
+} gs_function_Va_params_t;
+
+typedef struct gs_function_Va_s {
+ gs_function_head_t head;
+ gs_function_Va_params_t params;
+} gs_function_Va_t;
+
+#define private_st_function_Va() /* in gsfunc.c */\
+ gs_private_st_suffix_add1(st_function_Va, gs_function_Va_t,\
+ "gs_function_Va_t", function_Va_enum_ptrs, function_Va_reloc_ptrs,\
+ st_function, params.eval_data)
+
+int gs_function_Va_init(P3(gs_function_t ** ppfn,
+ const gs_function_Va_params_t * params,
+ gs_memory_t * mem));
+
+void gs_function_Va_free_params(P2(gs_function_Va_params_t * params,
+ gs_memory_t * mem));
#endif /* gsfunc_INCLUDED */
diff --git a/gs/src/gsfunc0.c b/gs/src/gsfunc0.c
index a015a9dd3..6fcfe5653 100644
--- a/gs/src/gsfunc0.c
+++ b/gs/src/gsfunc0.c
@@ -256,15 +256,67 @@ fn_Sd_evaluate(const gs_function_t * pfn_common, const float *in, float *out)
}
/* Test whether a Sampled function is monotonic. */
-/* Since this can be very time-consuming, we only do it if necessary. */
private int
fn_Sd_is_monotonic(const gs_function_t * pfn_common,
- const float *lower, const float *upper, bool must_know)
+ const float *lower, const float *upper,
+ gs_function_effort_t effort)
{
- if (!must_know)
- return gs_error_undefined; /* don't know */
-/****** NYI ******/
- return gs_error_undefined;
+ const gs_function_Sd_t *const pfn =
+ (const gs_function_Sd_t *)pfn_common;
+ float d0 = pfn->params.Domain[0], d1 = pfn->params.Domain[1];
+ float v0 = lower[0], v1 = upper[0];
+ float e0, e1, w0, w1;
+ float r0[max_Sd_n], r1[max_Sd_n];
+ int dir = 0;
+ int i, code;
+
+ /*
+ * Testing this in general is very time-consuming, so we don't bother.
+ * However, we do implement it correctly for one special case that is
+ * important in practice: for 1-input functions when the lower and
+ * upper values are in the same sample cell.
+ */
+ if (pfn->params.m > 1)
+ return gs_error_undefined;
+ if (lower[0] > pfn->params.Domain[1] ||
+ upper[0] < pfn->params.Domain[0]
+ )
+ return gs_error_rangecheck;
+ if (pfn->params.Encode)
+ e0 = pfn->params.Encode[0], e1 = pfn->params.Encode[1];
+ else
+ e0 = 0, e1 = pfn->params.Size[0];
+ w0 = (v0 - d0) * (e1 - e0) / (d1 - d0) + e0;
+ if (w0 < 0)
+ w0 = 0;
+ else if (w0 >= pfn->params.Size[0] - 1)
+ w0 = pfn->params.Size[0] - 1;
+ w1 = (v1 - d0) * (e1 - e0) / (d1 - d0) + e0;
+ if (w1 < 0)
+ w1 = 0;
+ else if (w1 >= pfn->params.Size[0] - 1)
+ w1 = pfn->params.Size[0] - 1;
+ if ((int)w0 != (int)w1)
+ return gs_error_undefined; /* not in the same sample */
+ code = gs_function_evaluate(pfn_common, lower, r0);
+ if (code < 0)
+ return code;
+ gs_function_evaluate(pfn_common, upper, r1);
+ if (code < 0)
+ return code;
+ for (i = 0; i < pfn->params.n; ++i) {
+ float diff = r1[i] - r0[i];
+ int code;
+
+ if (diff == 0)
+ continue;
+ code = (diff < 0 ? FN_MONOTONIC_DECREASING : FN_MONOTONIC_INCREASING);
+ if (dir == 0)
+ dir = code;
+ else if (dir != code)
+ return 0;
+ }
+ return dir;
}
/* Free the parameters of a Sampled function. */
@@ -282,13 +334,14 @@ int
gs_function_Sd_init(gs_function_t ** ppfn,
const gs_function_Sd_params_t * params, gs_memory_t * mem)
{
- static const gs_function_head_t function_Sd_head =
- {
+ static const gs_function_head_t function_Sd_head = {
function_type_Sampled,
- (fn_evaluate_proc_t) fn_Sd_evaluate,
- (fn_is_monotonic_proc_t) fn_Sd_is_monotonic,
- (fn_free_params_proc_t) gs_function_Sd_free_params,
- fn_common_free
+ {
+ (fn_evaluate_proc_t) fn_Sd_evaluate,
+ (fn_is_monotonic_proc_t) fn_Sd_is_monotonic,
+ (fn_free_params_proc_t) gs_function_Sd_free_params,
+ fn_common_free
+ }
};
int code;
int i;
@@ -326,8 +379,8 @@ gs_function_Sd_init(gs_function_t ** ppfn,
return_error(gs_error_rangecheck);
{
gs_function_Sd_t *pfn =
- gs_alloc_struct(mem, gs_function_Sd_t, &st_function_Sd,
- "gs_function_Sd_init");
+ gs_alloc_struct(mem, gs_function_Sd_t, &st_function_Sd,
+ "gs_function_Sd_init");
if (pfn == 0)
return_error(gs_error_VMerror);
@@ -335,6 +388,8 @@ gs_function_Sd_init(gs_function_t ** ppfn,
if (params->Order == 0)
pfn->params.Order = 1; /* default */
pfn->head = function_Sd_head;
+ pfn->head.is_monotonic =
+ fn_domain_is_monotonic((gs_function_t *)pfn, EFFORT_MODERATE);
*ppfn = (gs_function_t *) pfn;
}
return 0;
diff --git a/gs/src/gsfunc3.c b/gs/src/gsfunc3.c
index 6806a9336..4ff933cb8 100644
--- a/gs/src/gsfunc3.c
+++ b/gs/src/gsfunc3.c
@@ -59,7 +59,7 @@ private int
fn_ElIn_evaluate(const gs_function_t * pfn_common, const float *in, float *out)
{
const gs_function_ElIn_t *const pfn =
- (const gs_function_ElIn_t *)pfn_common;
+ (const gs_function_ElIn_t *)pfn_common;
double arg = in[0], raised;
int i;
@@ -83,6 +83,7 @@ fn_ElIn_evaluate(const gs_function_t * pfn_common, const float *in, float *out)
value = r1;
}
out[i] = value;
+ if_debug3('~', "[~]ElIn %g => [%d]%g\n", arg, i, out[i]);
}
return 0;
}
@@ -90,16 +91,37 @@ fn_ElIn_evaluate(const gs_function_t * pfn_common, const float *in, float *out)
/* Test whether an Exponential function is monotonic. (They always are.) */
private int
fn_ElIn_is_monotonic(const gs_function_t * pfn_common,
- const float *lower, const float *upper, bool must_know)
+ const float *lower, const float *upper,
+ gs_function_effort_t effort)
{
const gs_function_ElIn_t *const pfn =
(const gs_function_ElIn_t *)pfn_common;
+ int i;
+ int dir = 0;
if (lower[0] > pfn->params.Domain[1] ||
upper[0] < pfn->params.Domain[0]
)
return_error(gs_error_rangecheck);
- return 1;
+ if (pfn->params.C0 == 0 && pfn->params.C1 == 0)
+ return FN_MONOTONIC_INCREASING;
+ if (effort <= EFFORT_EASY)
+ return gs_error_undefined;
+ for (i = 0; i < pfn->params.n; ++i) {
+ double diff = pfn->params.C1[i] - pfn->params.C0[i];
+ int code;
+
+ if (diff == 0)
+ continue;
+ code = (diff > 0 ? FN_MONOTONIC_INCREASING : FN_MONOTONIC_DECREASING);
+ if (code <= 0)
+ return code;
+ if (dir == 0)
+ dir = code;
+ else if (dir != code)
+ return 0;
+ }
+ return dir;
}
/* Free the parameters of an Exponential Interpolation function. */
@@ -118,13 +140,14 @@ gs_function_ElIn_init(gs_function_t ** ppfn,
const gs_function_ElIn_params_t * params,
gs_memory_t * mem)
{
- static const gs_function_head_t function_ElIn_head =
- {
+ static const gs_function_head_t function_ElIn_head = {
function_type_ExponentialInterpolation,
- (fn_evaluate_proc_t) fn_ElIn_evaluate,
- (fn_is_monotonic_proc_t) fn_ElIn_is_monotonic,
- (fn_free_params_proc_t) gs_function_ElIn_free_params,
- fn_common_free
+ {
+ (fn_evaluate_proc_t) fn_ElIn_evaluate,
+ (fn_is_monotonic_proc_t) fn_ElIn_is_monotonic,
+ (fn_free_params_proc_t) gs_function_ElIn_free_params,
+ fn_common_free
+ }
};
int code;
@@ -145,14 +168,16 @@ gs_function_ElIn_init(gs_function_t ** ppfn,
return_error(gs_error_rangecheck);
} {
gs_function_ElIn_t *pfn =
- gs_alloc_struct(mem, gs_function_ElIn_t, &st_function_ElIn,
- "gs_function_ElIn_init");
+ gs_alloc_struct(mem, gs_function_ElIn_t, &st_function_ElIn,
+ "gs_function_ElIn_init");
if (pfn == 0)
return_error(gs_error_VMerror);
pfn->params = *params;
pfn->params.m = 1;
pfn->head = function_ElIn_head;
+ pfn->head.is_monotonic =
+ fn_domain_is_monotonic((gs_function_t *)pfn, EFFORT_MODERATE);
*ppfn = (gs_function_t *) pfn;
}
return 0;
@@ -172,7 +197,7 @@ private int
fn_1ItSg_evaluate(const gs_function_t * pfn_common, const float *in, float *out)
{
const gs_function_1ItSg_t *const pfn =
- (const gs_function_1ItSg_t *)pfn_common;
+ (const gs_function_1ItSg_t *)pfn_common;
float arg = in[0], b0, b1, e0, encoded;
int k = pfn->params.k;
int i;
@@ -193,23 +218,67 @@ fn_1ItSg_evaluate(const gs_function_t * pfn_common, const float *in, float *out)
e0 = pfn->params.Encode[2 * i];
encoded =
(arg - b0) * (pfn->params.Encode[2 * i + 1] - e0) / (b1 - b0) + e0;
+ if_debug3('~', "[~]1ItSg %g in %d => %g\n", arg, i, encoded);
return gs_function_evaluate(pfn->params.Functions[i], &encoded, out);
}
/* Test whether a 1-Input Stitching function is monotonic. */
private int
fn_1ItSg_is_monotonic(const gs_function_t * pfn_common,
- const float *lower, const float *upper, bool must_know)
+ const float *lower, const float *upper,
+ gs_function_effort_t effort)
{
const gs_function_1ItSg_t *const pfn =
- (const gs_function_1ItSg_t *)pfn_common;
+ (const gs_function_1ItSg_t *)pfn_common;
+ float v0 = lower[0], v1 = upper[0];
+ float d0 = pfn->params.Domain[0], d1 = pfn->params.Domain[1];
+ int k = pfn->params.k;
+ int i;
+ int dir = 0;
- if (lower[0] > pfn->params.Domain[1] ||
- upper[0] < pfn->params.Domain[0]
- )
+ if (v0 > d1 || v1 < d0)
return_error(gs_error_rangecheck);
-/****** NYI ******/
- return gs_error_undefined;
+ if (v0 < d0)
+ v0 = d0;
+ if (v1 > d1)
+ v1 = d1;
+ for (i = 0; i < pfn->params.k; ++i) {
+ float b0 = (i == 0 ? d0 : pfn->params.Bounds[i - 1]);
+ float b1 = (i == k - 1 ? d1 : pfn->params.Bounds[i]);
+ float e0, e1;
+ float w0, w1;
+ int code;
+
+ if (v0 >= b1 || v1 <= b0)
+ continue;
+ e0 = pfn->params.Encode[2 * i];
+ e1 = pfn->params.Encode[2 * i + 1];
+ w0 = (max(v0, b0) - b0) * (e1 - e0) / (b1 - b0) + e0;
+ w1 = (min(v1, b1) - b0) * (e1 - e0) / (b1 - b0) + e0;
+ /* Note that w0 > w1 is now possible if e0 > e1. */
+ if (w0 > w1) {
+ code = gs_function_is_monotonic(pfn->params.Functions[i],
+ &w0, &w1, effort);
+ switch (code) {
+ case FN_MONOTONIC_INCREASING:
+ code = FN_MONOTONIC_DECREASING; break;
+ case FN_MONOTONIC_DECREASING:
+ code = FN_MONOTONIC_INCREASING; break;
+ default:
+ break;
+ }
+ } else {
+ code = gs_function_is_monotonic(pfn->params.Functions[i],
+ &w0, &w1, effort);
+ }
+ if (code <= 0)
+ return code;
+ if (dir == 0)
+ dir = code;
+ else if (dir != code)
+ return 0;
+ }
+ return dir;
}
/* Free the parameters of a 1-Input Stitching function. */
@@ -228,13 +297,14 @@ int
gs_function_1ItSg_init(gs_function_t ** ppfn,
const gs_function_1ItSg_params_t * params, gs_memory_t * mem)
{
- static const gs_function_head_t function_1ItSg_head =
- {
+ static const gs_function_head_t function_1ItSg_head = {
function_type_1InputStitching,
- (fn_evaluate_proc_t) fn_1ItSg_evaluate,
- (fn_is_monotonic_proc_t) fn_1ItSg_is_monotonic,
- (fn_free_params_proc_t) gs_function_1ItSg_free_params,
- fn_common_free
+ {
+ (fn_evaluate_proc_t) fn_1ItSg_evaluate,
+ (fn_is_monotonic_proc_t) fn_1ItSg_is_monotonic,
+ (fn_free_params_proc_t) gs_function_1ItSg_free_params,
+ fn_common_free
+ }
};
int n = (params->Range == 0 ? 0 : params->n);
float prev = params->Domain[0];
@@ -262,8 +332,8 @@ gs_function_1ItSg_init(gs_function_t ** ppfn,
fn_check_mnDR((const gs_function_params_t *)params, 1, n);
{
gs_function_1ItSg_t *pfn =
- gs_alloc_struct(mem, gs_function_1ItSg_t, &st_function_1ItSg,
- "gs_function_1ItSg_init");
+ gs_alloc_struct(mem, gs_function_1ItSg_t, &st_function_1ItSg,
+ "gs_function_1ItSg_init");
if (pfn == 0)
return_error(gs_error_VMerror);
@@ -271,6 +341,8 @@ gs_function_1ItSg_init(gs_function_t ** ppfn,
pfn->params.m = 1;
pfn->params.n = n;
pfn->head = function_1ItSg_head;
+ pfn->head.is_monotonic =
+ fn_domain_is_monotonic((gs_function_t *)pfn, EFFORT_MODERATE);
*ppfn = (gs_function_t *) pfn;
}
return 0;
@@ -290,12 +362,12 @@ private int
fn_AdOt_evaluate(const gs_function_t * pfn_common, const float *in, float *out)
{
const gs_function_AdOt_t *const pfn =
- (const gs_function_AdOt_t *)pfn_common;
+ (const gs_function_AdOt_t *)pfn_common;
int i;
for (i = 0; i < pfn->params.n; ++i) {
int code =
- gs_function_evaluate(pfn->params.Functions[i], in, out + i);
+ gs_function_evaluate(pfn->params.Functions[i], in, out + i);
if (code < 0)
return code;
@@ -306,21 +378,27 @@ fn_AdOt_evaluate(const gs_function_t * pfn_common, const float *in, float *out)
/* Test whether an Arrayed Output function is monotonic. */
private int
fn_AdOt_is_monotonic(const gs_function_t * pfn_common,
- const float *lower, const float *upper, bool must_know)
+ const float *lower, const float *upper,
+ gs_function_effort_t effort)
{
const gs_function_AdOt_t *const pfn =
- (const gs_function_AdOt_t *)pfn_common;
+ (const gs_function_AdOt_t *)pfn_common;
int i;
+ int dir = 0;
for (i = 0; i < pfn->params.n; ++i) {
int code =
- gs_function_is_monotonic(pfn->params.Functions[i], lower, upper,
- must_know);
+ gs_function_is_monotonic(pfn->params.Functions[i], lower, upper,
+ effort);
if (code <= 0)
return code;
+ if (dir == 0)
+ dir = code;
+ else if (dir != code)
+ return 0;
}
- return 1;
+ return dir;
}
/* Free the parameters of an Arrayed Output function. */
@@ -337,13 +415,14 @@ int
gs_function_AdOt_init(gs_function_t ** ppfn,
const gs_function_AdOt_params_t * params, gs_memory_t * mem)
{
- static const gs_function_head_t function_AdOt_head =
- {
+ static const gs_function_head_t function_AdOt_head = {
function_type_ArrayedOutput,
- (fn_evaluate_proc_t) fn_AdOt_evaluate,
- (fn_is_monotonic_proc_t) fn_AdOt_is_monotonic,
- (fn_free_params_proc_t) gs_function_AdOt_free_params,
- fn_common_free
+ {
+ (fn_evaluate_proc_t) fn_AdOt_evaluate,
+ (fn_is_monotonic_proc_t) fn_AdOt_is_monotonic,
+ (fn_free_params_proc_t) gs_function_AdOt_free_params,
+ fn_common_free
+ }
};
int m = params->m, n = params->n;
int i;
@@ -359,8 +438,8 @@ gs_function_AdOt_init(gs_function_t ** ppfn,
}
{
gs_function_AdOt_t *pfn =
- gs_alloc_struct(mem, gs_function_AdOt_t, &st_function_AdOt,
- "gs_function_AdOt_init");
+ gs_alloc_struct(mem, gs_function_AdOt_t, &st_function_AdOt,
+ "gs_function_AdOt_init");
if (pfn == 0)
return_error(gs_error_VMerror);
@@ -368,6 +447,8 @@ gs_function_AdOt_init(gs_function_t ** ppfn,
pfn->params.Domain = 0;
pfn->params.Range = 0;
pfn->head = function_AdOt_head;
+ pfn->head.is_monotonic =
+ fn_domain_is_monotonic((gs_function_t *)pfn, EFFORT_MODERATE);
*ppfn = (gs_function_t *) pfn;
}
return 0;
diff --git a/gs/src/gshsb.h b/gs/src/gshsb.h
index c6fdd4bf2..ebe720ee3 100644
--- a/gs/src/gshsb.h
+++ b/gs/src/gshsb.h
@@ -22,6 +22,7 @@
#ifndef gshsb_INCLUDED
# define gshsb_INCLUDED
-int gs_sethsbcolor(P4(gs_state *, floatp, floatp, floatp)), gs_currenthsbcolor(P2(const gs_state *, float[3]));
+int gs_sethsbcolor(P4(gs_state *, floatp, floatp, floatp)),
+ gs_currenthsbcolor(P2(const gs_state *, float[3]));
#endif /* gshsb_INCLUDED */
diff --git a/gs/src/gsht1.c b/gs/src/gsht1.c
index fba3478d8..c6b943eaf 100644
--- a/gs/src/gsht1.c
+++ b/gs/src/gsht1.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1994, 1995, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -57,11 +57,8 @@ public_st_ht_component_element();
/* GC procedures */
-#define hptr ((gs_halftone_component *)vptr)
-
private
-ENUM_PTRS_BEGIN(halftone_component_enum_ptrs) return 0;
-
+ENUM_PTRS_WITH(halftone_component_enum_ptrs, gs_halftone_component *hptr) return 0;
case 0:
switch (hptr->type)
{
@@ -93,8 +90,7 @@ switch (hptr->type) {
return 0;
}
ENUM_PTRS_END
-
-private RELOC_PTRS_BEGIN(halftone_component_reloc_ptrs)
+private RELOC_PTRS_WITH(halftone_component_reloc_ptrs, gs_halftone_component *hptr)
{
switch (hptr->type) {
case ht_type_spot:
@@ -120,8 +116,6 @@ private RELOC_PTRS_BEGIN(halftone_component_reloc_ptrs)
}
RELOC_PTRS_END
-#undef hptr
-
/* setcolorscreen */
int
gs_setcolorscreen(gs_state * pgs, gs_colorscreen_halftone * pht)
@@ -213,19 +207,18 @@ gs_sethalftone_prepare(gs_state * pgs, gs_halftone * pht,
&phc[ci], gs_currentaccuratescreens(), mem);
if (code < 0)
break;
-#define sorder senum.order
- poc->corder = sorder;
+ poc->corder = senum.order;
poc->cname = cnames[i];
if (i == 0) /* Gray = Default */
- pdht->order = sorder;
+ pdht->order = senum.order;
else {
- uint tile_bytes =
- sorder.raster * (sorder.num_bits / sorder.width);
+ uint tile_bytes = senum.order.raster *
+ (senum.order.num_bits / senum.order.width);
uint num_tiles =
- max_tile_cache_bytes / tile_bytes + 1;
+ max_tile_cache_bytes / tile_bytes + 1;
gx_ht_cache *pcache =
- gx_ht_alloc_cache(mem, num_tiles,
- tile_bytes * num_tiles);
+ gx_ht_alloc_cache(mem, num_tiles,
+ tile_bytes * num_tiles);
if (pcache == 0) {
code = gs_note_error(gs_error_VMerror);
@@ -234,7 +227,6 @@ gs_sethalftone_prepare(gs_state * pgs, gs_halftone * pht,
poc->corder.cache = pcache;
gx_ht_init_cache(pcache, &poc->corder);
}
-#undef sorder
}
if (code < 0)
break;
diff --git a/gs/src/gshtscr.c b/gs/src/gshtscr.c
index ac69c90a2..3ee735e2d 100644
--- a/gs/src/gshtscr.c
+++ b/gs/src/gshtscr.c
@@ -35,10 +35,8 @@ static bool FORCE_STRIP_HALFTONES = false;
private_st_gs_screen_enum();
/* GC procedures */
-#define eptr ((gs_screen_enum *)vptr)
-
private
-ENUM_PTRS_BEGIN(screen_enum_enum_ptrs)
+ENUM_PTRS_WITH(screen_enum_enum_ptrs, gs_screen_enum *eptr)
{
if (index < 1 + st_ht_order_max_ptrs) {
gs_ptr_type_t ret =
@@ -54,8 +52,7 @@ ENUM_PTRS_BEGIN(screen_enum_enum_ptrs)
}
ENUM_PTR(0, gs_screen_enum, pgs);
ENUM_PTRS_END
-
-private RELOC_PTRS_BEGIN(screen_enum_reloc_ptrs)
+private RELOC_PTRS_WITH(screen_enum_reloc_ptrs, gs_screen_enum *eptr)
{
RELOC_PTR(gs_screen_enum, pgs);
RELOC_USING(st_halftone, &eptr->halftone, sizeof(gs_halftone));
@@ -63,8 +60,6 @@ private RELOC_PTRS_BEGIN(screen_enum_reloc_ptrs)
}
RELOC_PTRS_END
-#undef eptr
-
/* Define the default value of AccurateScreens that affects */
/* setscreen and setcolorscreen. */
private bool screen_accurate_screens;
@@ -96,6 +91,7 @@ gs_currentminscreenlevels(void)
}
/* Initialize the screen control statics at startup. */
+init_proc(gs_gshtscr_init); /* check prototype */
void
gs_gshtscr_init(gs_memory_t *mem)
{
diff --git a/gs/src/gsimage.c b/gs/src/gsimage.c
index 91866e97c..9bbd6c4fa 100644
--- a/gs/src/gsimage.c
+++ b/gs/src/gsimage.c
@@ -60,9 +60,8 @@ gs_private_st_composite(st_gs_image_enum, gs_image_enum, "gs_image_enum",
#define gs_image_enum_num_ptrs 2
/* GC procedures */
-#define eptr ((gs_image_enum *)vptr)
private
-ENUM_PTRS_BEGIN(gs_image_enum_enum_ptrs)
+ENUM_PTRS_WITH(gs_image_enum_enum_ptrs, gs_image_enum *eptr)
{
/* Enumerate the data planes. */
index -= gs_image_enum_num_ptrs;
@@ -76,7 +75,7 @@ ENUM_PTRS_BEGIN(gs_image_enum_enum_ptrs)
ENUM_PTR(0, gs_image_enum, dev);
ENUM_PTR(1, gs_image_enum, info);
ENUM_PTRS_END
-private RELOC_PTRS_BEGIN(gs_image_enum_reloc_ptrs)
+private RELOC_PTRS_WITH(gs_image_enum_reloc_ptrs, gs_image_enum *eptr)
{
int i;
@@ -88,7 +87,6 @@ private RELOC_PTRS_BEGIN(gs_image_enum_reloc_ptrs)
RELOC_STRING_PTR(gs_image_enum, planes[i].row);
}
RELOC_PTRS_END
-#undef eptr
/* Create an image enumerator given image parameters and a graphics state. */
int
diff --git a/gs/src/gsimpath.c b/gs/src/gsimpath.c
index b69930fc6..167e05ae4 100644
--- a/gs/src/gsimpath.c
+++ b/gs/src/gsimpath.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1989, 1992, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1989, 1992, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -21,6 +21,7 @@
#include "gx.h"
#include "gserrors.h"
#include "gsmatrix.h"
+#include "gspaint.h" /* for gs_imagepath prototype */
#include "gsstate.h"
#include "gspath.h"
diff --git a/gs/src/gsindent b/gs/src/gsindent
new file mode 100755
index 000000000..8f15e949f
--- /dev/null
+++ b/gs/src/gsindent
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+# This script formats C source code per the Ghostscript C style guide.
+# The perl invocations work around a bug in GNU indent.
+if [ $# -ne 0 ]; then
+ for f in $*
+ do
+ $0 < $f > /tmp/$$
+ cp -p $f $f.bak
+ if ( test ! -e $f~ ) then cp -p $f $f~; fi
+ mv /tmp/$$ $f
+ done
+ exit
+fi
+exec \
+perl -pe 's{(#.*/\*)(\*.*)}{$1&$2}' | \
+indent \
+--blank-lines-after-declarations \
+--no-blank-lines-after-procedures \
+--leave-optional-blank-lines \
+--braces-on-if-line \
+--indent-level4 \
+--case-indentation4 \
+--no-space-after-function-call-names \
+--dont-star-comments \
+--declaration-indentation0 \
+--procnames-start-lines \
+--continue-at-parentheses \
+--cuddle-else \
+--no-space-after-casts \
+--leave-preprocessor-space \
+- | \
+perl -pe 's{(#.*/\*)&(\*.*)}{$1$2}'
diff --git a/gs/src/gsiodev.c b/gs/src/gsiodev.c
index 70f559bc3..eba4d195a 100644
--- a/gs/src/gsiodev.c
+++ b/gs/src/gsiodev.c
@@ -63,6 +63,7 @@ const gx_io_device gs_iodev_os =
/* ------ Initialization ------ */
+init_proc(gs_iodev_init); /* check prototype */
void
gs_iodev_init(gs_memory_t * mem)
{ /* Make writable copies of all IODevices. */
diff --git a/gs/src/gsline.c b/gs/src/gsline.c
index 80a6991b5..6d2d5e936 100644
--- a/gs/src/gsline.c
+++ b/gs/src/gsline.c
@@ -285,6 +285,23 @@ gs_currentdashadapt(const gs_state * pgs)
return gs_imager_currentdashadapt((const gs_imager_state *)pgs);
}
+/* setcurvejoin */
+int
+gs_setcurvejoin(gs_state * pgs, int join)
+{
+ if (join < -1 || join > gs_line_join_max)
+ return_error(gs_error_rangecheck);
+ pgs_lp->curve_join = join;
+ return 0;
+}
+
+/* currentcurvejoin */
+int
+gs_currentcurvejoin(const gs_state * pgs)
+{
+ return pgs_lp->curve_join;
+}
+
/* Device-dependent */
/* setaccuratecurves */
diff --git a/gs/src/gsline.h b/gs/src/gsline.h
index fade79cf0..5584f996d 100644
--- a/gs/src/gsline.h
+++ b/gs/src/gsline.h
@@ -42,11 +42,15 @@ float gs_currentflat(P1(const gs_state *));
int gs_setstrokeadjust(P2(gs_state *, bool));
bool gs_currentstrokeadjust(P1(const gs_state *));
-/* Extensions */
-void gs_setaccuratecurves(P2(gs_state *, bool));
-bool gs_currentaccuratecurves(P1(const gs_state *));
+/* Extensions - device-independent */
void gs_setdashadapt(P2(gs_state *, bool));
bool gs_currentdashadapt(P1(const gs_state *));
+int gs_setcurvejoin(P2(gs_state *, int));
+int gs_currentcurvejoin(P1(const gs_state *));
+
+/* Extensions - device-dependent */
+void gs_setaccuratecurves(P2(gs_state *, bool));
+bool gs_currentaccuratecurves(P1(const gs_state *));
int gs_setdotlength(P3(gs_state *, floatp, bool));
float gs_currentdotlength(P1(const gs_state *));
bool gs_currentdotlength_absolute(P1(const gs_state *));
@@ -57,7 +61,6 @@ int gs_dotorientation(P1(gs_state *));
#ifndef gs_imager_state_DEFINED
# define gs_imager_state_DEFINED
typedef struct gs_imager_state_s gs_imager_state;
-
#endif
int gs_imager_setflat(P2(gs_imager_state *, floatp));
bool gs_imager_currentdashadapt(P1(const gs_imager_state *));
diff --git a/gs/src/gsmalloc.c b/gs/src/gsmalloc.c
index af6212337..bc504276c 100644
--- a/gs/src/gsmalloc.c
+++ b/gs/src/gsmalloc.c
@@ -16,7 +16,7 @@
all copies.
*/
-/*$Id: gsmalloc.c */
+
/* C heap allocator */
#include "malloc_.h"
#include "gdebug.h"
@@ -41,6 +41,7 @@
private gs_memory_proc_alloc_bytes(gs_heap_alloc_bytes);
private gs_memory_proc_resize_object(gs_heap_resize_object);
private gs_memory_proc_free_object(gs_heap_free_object);
+private gs_memory_proc_stable(gs_heap_stable);
private gs_memory_proc_status(gs_heap_status);
private gs_memory_proc_free_all(gs_heap_free_all);
@@ -62,6 +63,7 @@ private const gs_memory_procs_t gs_malloc_memory_procs =
gs_heap_alloc_bytes,
gs_heap_resize_object,
gs_heap_free_object,
+ gs_heap_stable,
gs_heap_status,
gs_heap_free_all,
gs_ignore_consolidate_free,
@@ -112,6 +114,7 @@ gs_malloc_memory_init(void)
gs_malloc_memory_t *mem =
(gs_malloc_memory_t *)malloc(sizeof(gs_malloc_memory_t));
+ mem->stable_memory = 0; /* just for tidyness, never referenced */
mem->procs = gs_malloc_memory_procs;
mem->allocated = 0;
mem->limit = max_long;
@@ -363,6 +366,11 @@ gs_heap_unregister_root(gs_memory_t * mem, gs_gc_root_t * rp,
client_name_t cname)
{
}
+private gs_memory_t *
+gs_heap_stable(gs_memory_t *mem)
+{
+ return mem; /* heap memory is stable */
+}
private void
gs_heap_status(gs_memory_t * mem, gs_memory_status_t * pstat)
{
diff --git a/gs/src/gsmatrix.c b/gs/src/gsmatrix.c
index 6b7e5c167..15ffb824f 100644
--- a/gs/src/gsmatrix.c
+++ b/gs/src/gsmatrix.c
@@ -370,6 +370,21 @@ gs_bbox_transform_inverse(const gs_rect * pbox_in, const gs_matrix * pmat,
#define f_fits_in_fixed(f) f_fits_in_bits(f, fixed_int_bits)
+/* Make a gs_matrix_fixed from a gs_matrix. */
+int
+gs_matrix_fixed_from_matrix(gs_matrix_fixed *pfmat, const gs_matrix *pmat)
+{
+ *(gs_matrix *)pfmat = *pmat;
+ if (f_fits_in_fixed(pmat->tx) && f_fits_in_fixed(pmat->ty)) {
+ pfmat->tx = fixed2float(pfmat->tx_fixed = float2fixed(pmat->tx));
+ pfmat->ty = fixed2float(pfmat->ty_fixed = float2fixed(pmat->ty));
+ pfmat->txy_fixed_valid = true;
+ } else {
+ pfmat->txy_fixed_valid = false;
+ }
+ return 0;
+}
+
/* Transform a point with a fixed-point result. */
int
gs_point_transform2fixed(const gs_matrix_fixed * pmat,
diff --git a/gs/src/gsmemlok.c b/gs/src/gsmemlok.c
index 4274c1611..9be594e03 100644
--- a/gs/src/gsmemlok.c
+++ b/gs/src/gsmemlok.c
@@ -32,6 +32,7 @@
private gs_memory_proc_alloc_bytes(gs_locked_alloc_bytes_immovable);
private gs_memory_proc_resize_object(gs_locked_resize_object);
private gs_memory_proc_free_object(gs_locked_free_object);
+private gs_memory_proc_stable(gs_locked_stable);
private gs_memory_proc_status(gs_locked_status);
private gs_memory_proc_free_all(gs_locked_free_all);
private gs_memory_proc_consolidate_free(gs_locked_consolidate_free);
@@ -59,6 +60,7 @@ private const gs_memory_procs_t locked_procs =
gs_locked_alloc_bytes_immovable,
gs_locked_resize_object,
gs_locked_free_object,
+ gs_locked_stable,
gs_locked_status,
gs_locked_free_all,
gs_locked_consolidate_free,
@@ -90,7 +92,7 @@ gs_memory_locked_init(
gs_memory_t * target /* allocator to monitor lock */
)
{
- /* Init the procedure vector from template */
+ lmem->stable_memory = 0;
lmem->procs = locked_procs;
lmem->target = target;
@@ -149,6 +151,11 @@ gs_locked_free_all(gs_memory_t * mem, uint free_mask, client_name_t cname)
gs_memory_t * const target = lmem->target;
/* Only free the structures and the allocator itself. */
+ if (mem->stable_memory) {
+ gs_memory_free_all(mem->stable_memory, free_mask, cname);
+ if (free_mask & FREE_ALL_ALLOCATOR)
+ mem->stable_memory = 0;
+ }
if (free_mask & FREE_ALL_STRUCTURES) {
/*
* Check for monitor == 0, in case this is called after a
@@ -342,6 +349,34 @@ gs_locked_unregister_root(gs_memory_t * mem, gs_gc_root_t * rp,
(lmem->target, rp, cname)
);
}
+private gs_memory_t *
+gs_locked_stable(gs_memory_t * mem)
+{
+ if (!mem->stable_memory) {
+ gs_memory_locked_t * const lmem = (gs_memory_locked_t *)mem;
+ gs_memory_t *stable;
+
+ gx_monitor_enter(lmem->monitor);
+ stable = gs_memory_stable(lmem->target);
+ if (stable == lmem->target)
+ mem->stable_memory = mem;
+ else {
+ gs_memory_locked_t *locked_stable = (gs_memory_locked_t *)
+ gs_alloc_bytes(stable, sizeof(*lmem), "gs_locked_stable");
+
+ if (locked_stable) {
+ int code = gs_memory_locked_init(locked_stable, stable);
+
+ if (code < 0)
+ gs_free_object(stable, locked_stable, "gs_locked_stable");
+ else
+ mem->stable_memory = (gs_memory_t *)locked_stable;
+ }
+ }
+ gx_monitor_leave(lmem->monitor);
+ }
+ return mem->stable_memory;
+}
private void
gs_locked_status(gs_memory_t * mem, gs_memory_status_t * pstat)
{
diff --git a/gs/src/gsmemory.c b/gs/src/gsmemory.c
index 2ee34ff32..83fa386a9 100644
--- a/gs/src/gsmemory.c
+++ b/gs/src/gsmemory.c
@@ -48,12 +48,12 @@ public_st_const_string_element();
/* GC procedures for bytestrings */
gs_ptr_type_t
-enum_bytestring(const void **pep, const gs_bytestring *pbs)
+enum_bytestring(enum_ptr_t *pep, const gs_bytestring *pbs)
{
return (pbs->bytes ? ENUM_OBJ(pbs->bytes) : ENUM_STRING(pbs));
}
gs_ptr_type_t
-enum_const_bytestring(const void **pep, const gs_const_bytestring *pbs)
+enum_const_bytestring(enum_ptr_t *pep, const gs_const_bytestring *pbs)
{
return (pbs->bytes ? ENUM_OBJ(pbs->bytes) : ENUM_CONST_STRING(pbs));
}
@@ -182,7 +182,7 @@ gs_register_struct_root(gs_memory_t *mem, gs_gc_root_t *root,
#ifdef DEBUG
-const char *
+private const char *
rc_object_type_name(const void *vp, const rc_header *prc)
{
gs_memory_type_ptr_t pstype;
@@ -207,6 +207,35 @@ rc_object_type_name(const void *vp, const rc_header *prc)
return client_name_string(gs_struct_type_name(pstype));
}
+/* Trace reference count operations. */
+void
+rc_trace_init_free(const void *vp, const rc_header *prc)
+{
+ dprintf3("[^]%s 0x%lx init = %ld\n",
+ rc_object_type_name(vp, prc), (ulong)vp, (long)prc->ref_count);
+}
+void
+rc_trace_free_struct(const void *vp, const rc_header *prc, client_name_t cname)
+{
+ dprintf3("[^]%s 0x%lx => free (%s)\n",
+ rc_object_type_name(vp, prc),
+ (ulong)vp, client_name_string(cname));
+}
+void
+rc_trace_increment(const void *vp, const rc_header *prc)
+{
+ dprintf3("[^]%s 0x%lx ++ => %ld\n",
+ rc_object_type_name(vp, prc),
+ (ulong)vp, (long)prc->ref_count);
+}
+void
+rc_trace_adjust(const void *vp, const rc_header *prc, int delta)
+{
+ dprintf4("[^]%s 0x%lx %+d => %ld\n",
+ rc_object_type_name(vp, prc),
+ (ulong)vp, delta, (long)(prc->ref_count + delta));
+}
+
#endif /* DEBUG */
/* Normal freeing routine for reference-counted structures. */
@@ -226,21 +255,22 @@ ENUM_PTRS_BEGIN_PROC(basic_enum_ptrs)
if (index < psd->num_ptrs) {
const gc_ptr_element_t *ppe = &psd->ptrs[index];
- char *pptr = (char *)vptr + ppe->offset;
+ EV_CONST char *pptr = (EV_CONST char *)vptr + ppe->offset;
switch ((gc_ptr_type_index_t)ppe->type) {
case GC_ELT_OBJ:
- return ENUM_OBJ(*(void **)pptr);
+ return ENUM_OBJ(*(const void *EV_CONST *)pptr);
case GC_ELT_STRING:
- return ENUM_STRING((gs_string *) pptr);
+ return ENUM_STRING((const gs_string *)pptr);
case GC_ELT_CONST_STRING:
- return ENUM_CONST_STRING((gs_string *) pptr);
+ return ENUM_CONST_STRING((const gs_const_string *)pptr);
}
}
if (!psd->super_type)
return 0;
return ENUM_USING(*(psd->super_type),
- (void *)((char *)vptr + psd->super_offset),
+ (EV_CONST void *)
+ ((EV_CONST char *)vptr + psd->super_offset),
pstype->ssize, index - psd->num_ptrs);
}
ENUM_PTRS_END_PROC
diff --git a/gs/src/gsmemory.h b/gs/src/gsmemory.h
index c2c913b1f..faed82e53 100644
--- a/gs/src/gsmemory.h
+++ b/gs/src/gsmemory.h
@@ -43,7 +43,10 @@ typedef const gs_memory_struct_type_t *gs_memory_type_ptr_t;
/* Define the opaque type for an allocator. */
/* (The actual structure is defined later in this file.) */
+#ifndef gs_memory_DEFINED
+# define gs_memory_DEFINED
typedef struct gs_memory_s gs_memory_t;
+#endif
/* Define the opaque type for a pointer type. */
typedef struct gs_ptr_procs_s gs_ptr_procs_t;
@@ -80,6 +83,8 @@ typedef struct gs_memory_procs_s {
gs_memory_t_proc_resize_object(proc, gs_memory_t)
#define gs_memory_proc_free_object(proc)\
gs_memory_t_proc_free_object(proc, gs_memory_t)
+#define gs_memory_proc_stable(proc)\
+ gs_memory_t_proc_stable(proc, gs_memory_t)
#define gs_memory_proc_status(proc)\
gs_memory_t_proc_status(proc, gs_memory_t)
#define gs_memory_proc_free_all(proc)\
@@ -273,8 +278,10 @@ void *gs_raw_alloc_struct_immovable(P3(gs_raw_memory_t * rmem,
/*
* Define an abstract allocator instance.
* Subclasses may have state as well.
+ * Note that the initial part of this must match gs_raw_memory_t.
*/
#define gs_memory_common\
+ gs_memory_t *stable_memory;\
gs_memory_procs_t procs
struct gs_memory_s {
gs_memory_common;
diff --git a/gs/src/gsmemraw.h b/gs/src/gsmemraw.h
index ba6998b71..0ad51c881 100644
--- a/gs/src/gsmemraw.h
+++ b/gs/src/gsmemraw.h
@@ -118,12 +118,31 @@ typedef struct gs_raw_memory_s gs_raw_memory_t;
((mem)->procs.status(mem, pst))
/*
+ * Return the stable allocator for this allocator. The
+ * stable allocator allocates from the same heap and in
+ * the same VM space, but is not subject to save and restore.
+ * (It is the client's responsibility to avoid creating
+ * dangling pointers.)
+ *
+ * Note that the stable allocator may be the same allocator
+ * as this one.
+ */
+
+#define gs_memory_t_proc_stable(proc, mem_t)\
+ mem_t *proc(P1(mem_t *mem))
+
+#define gs_memory_stable(mem)\
+ ((mem)->procs.stable(mem))
+
+ /*
* Free one or more of: data memory acquired by the allocator
* (FREE_ALL_DATA), overhead structures other than the
* allocator itself (FREE_ALL_STRUCTURES), and the allocator
* itself (FREE_ALL_ALLOCATOR). Note that this requires
* allocators to keep track of all the memory they have ever
- * acquired, and where they acquired it.
+ * acquired, and where they acquired it. Note that this
+ * operation propagates to the stable allocator (if
+ * different).
*/
#define FREE_ALL_DATA 1
@@ -158,20 +177,20 @@ typedef struct gs_raw_memory_s gs_raw_memory_t;
gs_memory_t_proc_alloc_bytes((*alloc_bytes_immovable), mem_t);\
gs_memory_t_proc_resize_object((*resize_object), mem_t);\
gs_memory_t_proc_free_object((*free_object), mem_t);\
+ gs_memory_t_proc_stable((*stable), mem_t);\
gs_memory_t_proc_status((*status), mem_t);\
gs_memory_t_proc_free_all((*free_all), mem_t);\
gs_memory_t_proc_consolidate_free((*consolidate_free), mem_t)
-/* Define the procedure vector for a raw memory allocator. */
-typedef struct gs_raw_memory_procs_s {
- gs_raw_memory_procs(gs_raw_memory_t);
-} gs_raw_memory_procs_t;
-
/*
* Define an abstract raw-memory allocator instance.
- * Subclasses may have state as well.
+ * Subclasses may have additional state.
*/
+typedef struct gs_raw_memory_procs_s {
+ gs_raw_memory_procs(gs_raw_memory_t);
+} gs_raw_memory_procs_t;
struct gs_raw_memory_s {
+ gs_raw_memory_t *stable_memory; /* cache the stable allocator */
gs_raw_memory_procs_t procs;
};
diff --git a/gs/src/gsmemret.c b/gs/src/gsmemret.c
index 403559a08..ec5b1cd38 100644
--- a/gs/src/gsmemret.c
+++ b/gs/src/gsmemret.c
@@ -27,6 +27,7 @@
private gs_memory_proc_alloc_bytes(gs_retrying_alloc_bytes_immovable);
private gs_memory_proc_resize_object(gs_retrying_resize_object);
private gs_memory_proc_free_object(gs_forward_free_object);
+private gs_memory_proc_stable(gs_retrying_stable);
private gs_memory_proc_status(gs_forward_status);
private gs_memory_proc_free_all(gs_forward_free_all);
private gs_memory_proc_consolidate_free(gs_forward_consolidate_free);
@@ -53,6 +54,7 @@ private const gs_memory_procs_t retrying_procs = {
gs_retrying_alloc_bytes_immovable,
gs_retrying_resize_object,
gs_forward_free_object,
+ gs_retrying_stable,
gs_forward_status,
gs_forward_free_all,
gs_forward_consolidate_free,
@@ -91,6 +93,7 @@ gs_memory_retrying_init(
gs_memory_t * target /* allocator to wrap */
)
{
+ rmem->stable_memory = 0;
rmem->procs = retrying_procs;
rmem->target = target;
gs_memory_retrying_set_recover(rmem, no_recover_proc, NULL);
@@ -320,6 +323,31 @@ gs_forward_unregister_root(gs_memory_t * mem, gs_gc_root_t * rp,
{
DO_FORWARD(target->procs.unregister_root(target, rp, cname));
}
+private gs_memory_t *
+gs_retrying_stable(gs_memory_t * mem)
+{
+ if (!mem->stable_memory) {
+ gs_memory_retrying_t * const rmem = (gs_memory_retrying_t *)mem;
+ gs_memory_t *stable = gs_memory_stable(rmem->target);
+
+ if (stable == rmem->target)
+ mem->stable_memory = mem;
+ else {
+ gs_memory_retrying_t *retrying_stable = (gs_memory_retrying_t *)
+ gs_alloc_bytes(stable, sizeof(*rmem), "gs_retrying_stable");
+
+ if (retrying_stable) {
+ int code = gs_memory_retrying_init(retrying_stable, stable);
+
+ if (code < 0)
+ gs_free_object(stable, retrying_stable, "gs_retrying_stable");
+ else
+ mem->stable_memory = (gs_memory_t *)retrying_stable;
+ }
+ }
+ }
+ return mem->stable_memory;
+}
private void
gs_forward_status(gs_memory_t * mem, gs_memory_status_t * pstat)
{
diff --git a/gs/src/gsmisc.c b/gs/src/gsmisc.c
index 820196333..5db3fa91d 100644
--- a/gs/src/gsmisc.c
+++ b/gs/src/gsmisc.c
@@ -25,6 +25,7 @@
#include "string_.h"
#include "gx.h"
#include "gpcheck.h" /* for gs_return_check_interrupt */
+#include "gserror.h" /* for prototype */
#include "gserrors.h"
#include "gconfigv.h" /* for USE_ASM */
#include "gxfarith.h"
@@ -69,6 +70,7 @@ dprintf_file_tail(const char *file)
--tail;
return tail;
}
+#if __LINE__ /* compiler provides it */
void
dprintf_file_and_line(FILE * f, const char *file, int line)
{
@@ -76,12 +78,14 @@ dprintf_file_and_line(FILE * f, const char *file, int line)
fprintf(f, dprintf_file_and_line_format,
dprintf_file_tail(file), line);
}
+#else
void
-dprintf_file(FILE * f, const char *file)
+dprintf_file_only(FILE * f, const char *file)
{
if (gs_debug['/'])
fprintf(f, dprintf_file_only_format, dprintf_file_tail(file));
}
+#endif
void
printf_program_ident(FILE * f, const char *program_name,
long revision_number)
@@ -105,16 +109,19 @@ eprintf_program_ident(FILE * f, const char *program_name,
fputs(": ", f);
}
}
+#if __LINE__ /* compiler provides it */
void
lprintf_file_and_line(FILE * f, const char *file, int line)
{
fprintf(f, "%s(%d): ", file, line);
}
+#else
void
lprintf_file_only(FILE * f, const char *file)
{
fprintf(f, "%s(?): ", file);
}
+#endif
/* Log an error return. We always include this, in case other */
/* modules were compiled with DEBUG set. */
@@ -274,11 +281,11 @@ gs_memset(void *dest, register int ch, size_t len)
((long *)p)[0] = wd;
switch (count >> ARCH_LOG2_SIZEOF_LONG) {
case 3:
- ((long *)p)[2] = wd; p += sizeof(long);
+ *((long *)p) = wd; p += sizeof(long);
case 2:
- ((long *)p)[1] = wd; p += sizeof(long);
+ *((long *)p) = wd; p += sizeof(long);
case 1:
- ((long *)p)[0] = wd; p += sizeof(long);
+ *((long *)p) = wd; p += sizeof(long);
count &= sizeof(long) - 1;
case 0:
default: /* can't happen */
@@ -448,7 +455,7 @@ ilog2(int n)
"\000\000\001\001\002\002\002\002\003\003\003\003\003\003\003\003"[m] + l);
}
-#if defined(CHECK_FMUL2FIXED_VARS) && !USE_ASM
+#if defined(NEED_SET_FMUL2FIXED) && !USE_ASM
/*
* Floating multiply with fixed result, for avoiding floating point in
@@ -501,7 +508,7 @@ set_dfmul2fixed_(fixed * pr, ulong /*double lo */ xalo, long /*float */ b, long
b);
}
-#endif
+#endif /* NEED_SET_FMUL2FIXED */
#if USE_FPU_FIXED
diff --git a/gs/src/gsnogc.c b/gs/src/gsnogc.c
index 13028048e..c45fa74b9 100644
--- a/gs/src/gsnogc.c
+++ b/gs/src/gsnogc.c
@@ -299,6 +299,7 @@ sf_consolidate_free(gs_memory_t *mem)
* within the chunk if possible.
*/
+private void use_string_freelists(P1(gs_ref_memory_t *mem));
void
gs_nogc_reclaim(vm_spaces * pspaces, bool global)
{
@@ -311,17 +312,25 @@ gs_nogc_reclaim(vm_spaces * pspaces, bool global)
if (mem == 0 || mem == mem_prev)
continue;
mem_prev = mem;
-
- /*
- * Change the allocator to use string freelists in the future.
- */
- mem->procs.alloc_string = sf_alloc_string;
- if (mem->procs.free_string != gs_ignore_free_string)
- mem->procs.free_string = sf_free_string;
- mem->procs.enable_free = sf_enable_free;
- mem->procs.consolidate_free = sf_consolidate_free;
+ use_string_freelists(mem);
+ if (mem->stable_memory != (gs_memory_t *)mem &&
+ mem->stable_memory != 0
+ )
+ use_string_freelists((gs_ref_memory_t *)mem->stable_memory);
+ }
+}
+private void
+use_string_freelists(gs_ref_memory_t *mem)
+{
+ /*
+ * Change the allocator to use string freelists in the future.
+ */
+ mem->procs.alloc_string = sf_alloc_string;
+ if (mem->procs.free_string != gs_ignore_free_string)
+ mem->procs.free_string = sf_free_string;
+ mem->procs.enable_free = sf_enable_free;
+ mem->procs.consolidate_free = sf_consolidate_free;
/* Merge free objects, detecting entirely free chunks. */
- gs_consolidate_free((gs_memory_t *)mem);
- }
+ gs_consolidate_free((gs_memory_t *)mem);
}
diff --git a/gs/src/gsnorop.c b/gs/src/gsnorop.c
index bc0aacb93..b546f2c56 100644
--- a/gs/src/gsnorop.c
+++ b/gs/src/gsnorop.c
@@ -22,6 +22,9 @@
#include "gserrors.h"
#include "gsrop.h"
#include "gxdevcli.h"
+#include "gxdevice.h" /* for gx_default_*copy_rop prototypes */
+#include "gxdevmem.h" /* for gdevmem.h */
+#include "gdevmem.h" /* for mem_*_strip_copy_rop prototypes */
#include "gdevmrop.h"
/* Stub accessors to logical operation in graphics state. */
diff --git a/gs/src/gsnotify.c b/gs/src/gsnotify.c
new file mode 100644
index 000000000..33b3b7d89
--- /dev/null
+++ b/gs/src/gsnotify.c
@@ -0,0 +1,115 @@
+/* Copyright (C) 1999 Aladdin Enterprises. All rights reserved.
+
+ This file is part of Aladdin Ghostscript.
+
+ Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
+ or distributor accepts any responsibility for the consequences of using it,
+ or for whether it serves any particular purpose or works at all, unless he
+ or she says so in writing. Refer to the Aladdin Ghostscript Free Public
+ License (the "License") for full details.
+
+ Every copy of Aladdin Ghostscript must include a copy of the License,
+ normally in a plain ASCII text file named PUBLIC. The License grants you
+ the right to copy, modify and redistribute Aladdin Ghostscript, but only
+ under certain conditions described in the License. Among other things, the
+ License requires that the copyright notice and this notice be preserved on
+ all copies.
+ */
+
+
+/* Notification machinery implementation */
+#include "gx.h"
+#include "gserrors.h"
+#include "gsstruct.h"
+#include "gsnotify.h"
+
+/* GC descriptors */
+private_st_gs_notify_registration();
+public_st_gs_notify_list();
+
+/* Initialize a notification list. */
+void
+gs_notify_init(gs_notify_list_t *nlist, gs_memory_t *mem)
+{
+ nlist->first = 0;
+ nlist->memory = mem;
+}
+
+/* Register a client. */
+int
+gs_notify_register(gs_notify_list_t *nlist, gs_notify_proc_t proc,
+ void *proc_data)
+{
+ gs_notify_registration_t *nreg =
+ gs_alloc_struct(nlist->memory, gs_notify_registration_t,
+ &st_gs_notify_registration, "gs_notify_register");
+
+ if (nreg == 0)
+ return_error(gs_error_VMerror);
+ nreg->proc = proc;
+ nreg->proc_data = proc_data;
+ nreg->next = nlist->first;
+ nlist->first = nreg;
+ return 0;
+}
+
+/*
+ * Unregister a client. Return 1 if the client was registered, 0 if not.
+ * If proc_data is 0, unregister all registrations of that proc; otherwise,
+ * unregister only the registration of that procedure with that proc_data.
+ */
+int
+gs_notify_unregister(gs_notify_list_t *nlist, gs_notify_proc_t proc,
+ void *proc_data)
+{
+ gs_notify_registration_t **prev = &nlist->first;
+ gs_notify_registration_t *cur;
+ bool found = 0;
+
+ while ((cur = *prev) != 0)
+ if (cur->proc == proc &&
+ (proc_data == 0 || cur->proc_data == proc_data)
+ ) {
+ *prev = cur->next;
+ gs_free_object(nlist->memory, cur, "gs_notify_unregister");
+ found = 1;
+ } else
+ prev = &cur->next;
+ return found;
+}
+
+/*
+ * Notify the clients on a list. If an error occurs, return the first
+ * error code, but notify all clients regardless.
+ */
+int
+gs_notify_all(gs_notify_list_t *nlist, void *event_data)
+{
+ gs_notify_registration_t *cur;
+ gs_notify_registration_t *next;
+ int ecode = 0;
+
+ for (next = nlist->first; (cur = next) != 0;) {
+ int code;
+
+ next = cur->next;
+ code = cur->proc(cur->proc_data, event_data);
+ if (code < 0 && ecode == 0)
+ ecode = code;
+ }
+ return ecode;
+}
+
+/* Release a notification list. */
+void
+gs_notify_release(gs_notify_list_t *nlist)
+{
+ gs_memory_t *mem = nlist->memory;
+
+ while (nlist->first) {
+ gs_notify_registration_t *next = nlist->first->next;
+
+ gs_free_object(mem, nlist->first, "gs_notify_release");
+ nlist->first = next;
+ }
+}
diff --git a/gs/src/gsnotify.h b/gs/src/gsnotify.h
new file mode 100644
index 000000000..2e880e62d
--- /dev/null
+++ b/gs/src/gsnotify.h
@@ -0,0 +1,88 @@
+/* Copyright (C) 1999 Aladdin Enterprises. All rights reserved.
+
+ This file is part of Aladdin Ghostscript.
+
+ Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
+ or distributor accepts any responsibility for the consequences of using it,
+ or for whether it serves any particular purpose or works at all, unless he
+ or she says so in writing. Refer to the Aladdin Ghostscript Free Public
+ License (the "License") for full details.
+
+ Every copy of Aladdin Ghostscript must include a copy of the License,
+ normally in a plain ASCII text file named PUBLIC. The License grants you
+ the right to copy, modify and redistribute Aladdin Ghostscript, but only
+ under certain conditions described in the License. Among other things, the
+ License requires that the copyright notice and this notice be preserved on
+ all copies.
+ */
+
+
+/* Notification machinery */
+
+#ifndef gsnotify_INCLUDED
+# define gsnotify_INCLUDED
+
+#include "gsstype.h" /* for extern_st */
+
+/*
+ * An arbitrary number of clients may register themselves to be notified
+ * when an event occurs. Duplicate registrations are not detected. Clients
+ * must unregister themselves when they are being freed (finalized), if not
+ * before. Objects that provide notification must notify clients when the
+ * object is being freed (finalized): in this event, and only in this event,
+ * event_data = NULL.
+ */
+
+/* Define the structure used to keep track of registrations. */
+#define GS_NOTIFY_PROC(proc)\
+ int proc(P2(void *proc_data, void *event_data))
+typedef GS_NOTIFY_PROC((*gs_notify_proc_t));
+typedef struct gs_notify_registration_s gs_notify_registration_t;
+struct gs_notify_registration_s {
+ gs_notify_proc_t proc;
+ void *proc_data;
+ gs_notify_registration_t *next;
+};
+#define private_st_gs_notify_registration() /* in gsnotify.c */\
+ gs_private_st_ptrs2(st_gs_notify_registration, gs_notify_registration_t,\
+ "gs_notify_registration_t", notify_registration_enum_ptrs,\
+ notify_registration_reloc_ptrs, proc_data, next)
+
+/* Define a notification list. */
+typedef struct gs_notify_list_s {
+ gs_memory_t *memory; /* for allocating registrations */
+ gs_notify_registration_t *first;
+} gs_notify_list_t;
+/* The descriptor is public for GC of embedded instances. */
+extern_st(st_gs_notify_list);
+#define public_st_gs_notify_list() /* in gsnotify.c */\
+ gs_public_st_ptrs1(st_gs_notify_list, gs_notify_list_t,\
+ "gs_notify_list_t", notify_list_enum_ptrs, notify_list_reloc_ptrs,\
+ first)
+#define st_gs_notify_list_max_ptrs 1
+
+/* Initialize a notification list. */
+void gs_notify_init(P2(gs_notify_list_t *nlist, gs_memory_t *mem));
+
+/* Register a client. */
+int gs_notify_register(P3(gs_notify_list_t *nlist, gs_notify_proc_t proc,
+ void *proc_data));
+
+/*
+ * Unregister a client. Return 1 if the client was registered, 0 if not.
+ * If proc_data is 0, unregister all registrations of that proc; otherwise,
+ * unregister only the registration of that procedure with that proc_data.
+ */
+int gs_notify_unregister(P3(gs_notify_list_t *nlist, gs_notify_proc_t proc,
+ void *proc_data));
+
+/*
+ * Notify the clients on a list. If an error occurs, return the first
+ * error code, but notify all clients regardless.
+ */
+int gs_notify_all(P2(gs_notify_list_t *nlist, void *event_data));
+
+/* Release a notification list. */
+void gs_notify_release(P1(gs_notify_list_t *nlist));
+
+#endif /* gsnotify_INCLUDED */
diff --git a/gs/src/gsparam.h b/gs/src/gsparam.h
index 2f7c4cc39..da15778a8 100644
--- a/gs/src/gsparam.h
+++ b/gs/src/gsparam.h
@@ -496,7 +496,7 @@ void gs_c_param_list_set_target(P2(gs_c_param_list *, gs_param_list *));
/* Clients normally allocate the gs_c_param_list on the stack. */
void gs_c_param_list_write(P2(gs_c_param_list *, gs_memory_t *));
-void gs_c_param_list_rewrite(P1(gs_c_param_list *)); /* switch back to writing, no init */
+void gs_c_param_list_write_more(P1(gs_c_param_list *)); /* switch back to writing, no init */
void gs_c_param_list_read(P1(gs_c_param_list *)); /* switch to reading */
void gs_c_param_list_release(P1(gs_c_param_list *));
diff --git a/gs/src/gsparamx.c b/gs/src/gsparamx.c
index 97afd0933..90da8882b 100644
--- a/gs/src/gsparamx.c
+++ b/gs/src/gsparamx.c
@@ -98,3 +98,21 @@ param_put_int(gs_param_list * plist, gs_param_name param_name,
}
return ecode;
}
+
+/* Put a long value. */
+int
+param_put_long(gs_param_list * plist, gs_param_name param_name,
+ long *pval, int ecode)
+{
+ int code;
+
+ switch (code = param_read_long(plist, param_name, pval)) {
+ default:
+ ecode = code;
+ param_signal_error(plist, param_name, ecode);
+ case 0:
+ case 1:
+ break;
+ }
+ return ecode;
+}
diff --git a/gs/src/gsparamx.h b/gs/src/gsparamx.h
index 89ea85a15..3df29aa1e 100644
--- a/gs/src/gsparamx.h
+++ b/gs/src/gsparamx.h
@@ -35,5 +35,7 @@ int param_put_bool(P4(gs_param_list * plist, gs_param_name param_name,
bool * pval, int ecode));
int param_put_int(P4(gs_param_list * plist, gs_param_name param_name,
int * pval, int ecode));
+int param_put_long(P4(gs_param_list * plist, gs_param_name param_name,
+ long * pval, int ecode));
#endif /* gsparamx_INCLUDED */
diff --git a/gs/src/gspath.c b/gs/src/gspath.c
index c2051f8b2..b2b1883f1 100644
--- a/gs/src/gspath.c
+++ b/gs/src/gspath.c
@@ -23,6 +23,7 @@
#include "gxfixed.h"
#include "gxmatrix.h"
#include "gscoord.h" /* requires gsmatrix.h */
+#include "gspath.h" /* for checking prototypes */
#include "gzstate.h"
#include "gzpath.h"
#include "gxdevice.h" /* for gxcpath.h */
diff --git a/gs/src/gspcolor.c b/gs/src/gspcolor.c
index c5cbcc7b5..64cfa2565 100644
--- a/gs/src/gspcolor.c
+++ b/gs/src/gspcolor.c
@@ -36,7 +36,6 @@
#include "gxclip2.h"
#include "gspath.h"
#include "gxpath.h"
-#include "gxp1fill.h"
#include "gxpcolor.h"
#include "gzstate.h"
#include "gsimage.h"
@@ -291,11 +290,11 @@ gx_adjust_color_Pattern(const gs_client_color * pcc,
/* GC procedures */
-#define pcs ((gs_color_space *)vptr)
-
private
ENUM_PTRS_BEGIN_PROC(cs_Pattern_enum_ptrs)
{
+ EV_CONST gs_color_space *const pcs = vptr;
+
if (!pcs->params.pattern.has_base_space)
return 0;
return ENUM_USING(*pcs->params.pattern.base_space.type->stype,
@@ -303,7 +302,7 @@ ENUM_PTRS_BEGIN_PROC(cs_Pattern_enum_ptrs)
sizeof(pcs->params.pattern.base_space), index);
}
ENUM_PTRS_END_PROC
-private RELOC_PTRS_BEGIN(cs_Pattern_reloc_ptrs)
+private RELOC_PTRS_WITH(cs_Pattern_reloc_ptrs, gs_color_space *pcs)
{
if (!pcs->params.pattern.has_base_space)
return;
@@ -312,5 +311,3 @@ private RELOC_PTRS_BEGIN(cs_Pattern_reloc_ptrs)
sizeof(gs_paint_color_space));
}
RELOC_PTRS_END
-
-#undef pcs
diff --git a/gs/src/gsptype1.c b/gs/src/gsptype1.c
index e0d73bb1f..ff942622a 100644
--- a/gs/src/gsptype1.c
+++ b/gs/src/gsptype1.c
@@ -36,12 +36,11 @@
#include "gxclip2.h"
#include "gspath.h"
#include "gxpath.h"
-#include "gxp1fill.h"
#include "gxpcolor.h"
+#include "gxp1impl.h" /* requires gxpcolor.h */
#include "gzstate.h"
#include "gsimage.h"
#include "gsiparm4.h"
-#include "gscssub.h"
/* GC descriptors */
private_st_pattern1_template();
@@ -65,15 +64,10 @@ private RELOC_PTRS_BEGIN(pattern1_instance_reloc_ptrs) {
RELOC_SUPER(gs_pattern1_instance_t, st_pattern1_template, template);
} RELOC_PTRS_END
-/* Import the Pattern reloading procedure from gxpcmap.c. */
-int gx_pattern_load(P4(gx_device_color *, const gs_imager_state *,
- gx_device *, gs_color_select_t));
-
/* Define a PatternType 1 pattern. */
private pattern_proc_uses_base_space(gs_pattern1_uses_base_space);
private pattern_proc_make_pattern(gs_pattern1_make_pattern);
private pattern_proc_get_pattern(gs_pattern1_get_pattern);
-extern pattern_proc_remap_color(gs_pattern1_remap_color);
private const gs_pattern_type_t gs_pattern1_type = {
1, {
gs_pattern1_uses_base_space, gs_pattern1_make_pattern,
@@ -348,7 +342,7 @@ gs_private_st_suffix_add1(st_pixmap_info,
* Note that this routine does NOT release the data in the original pixmap;
* that remains the responsibility of the client.
*/
- void
+private void
free_pixmap_pattern(
gs_memory_t * pmem,
void * pvpinst,
@@ -531,16 +525,10 @@ gs_makepixmappattern(
if (!mask && (white_index >= (1 << pbitmap->pix_depth)))
pinst->uses_mask = false;
- /*
- * Since the PaintProcs don't reference the saved color space or
- * color, reset these so that there isn't an extra retained
- * reference to the Pattern object.
- */
- gs_setcolorspace(pinst->saved, gs_current_DeviceGray_space(pinst->saved));
/* overwrite the free procedure for the pattern instance */
- ppmap->free_proc = pinst->rc.free;
- pinst->rc.free = free_pixmap_pattern;
+ ppmap->free_proc = pinst->rc.free;
+ pinst->rc.free = free_pixmap_pattern;
}
gs_setmatrix(pgs, &smat);
return code;
@@ -640,9 +628,8 @@ const gx_device_color_type_t *const gx_dc_type_pattern = &gx_dc_pattern;
#define gx_dc_type_pattern (&gx_dc_pattern)
/* GC procedures */
-#define cptr ((gx_device_color *)vptr)
private
-ENUM_PTRS_BEGIN(dc_pattern_enum_ptrs)
+ENUM_PTRS_WITH(dc_pattern_enum_ptrs, gx_device_color *cptr)
{
return ENUM_USING(st_dc_pure_masked, vptr, size, index - 1);
}
@@ -653,7 +640,7 @@ case 0:
ENUM_RETURN((tile == 0 ? tile : tile - tile->index));
}
ENUM_PTRS_END
-private RELOC_PTRS_BEGIN(dc_pattern_reloc_ptrs)
+private RELOC_PTRS_WITH(dc_pattern_reloc_ptrs, gx_device_color *cptr)
{
gx_color_tile *tile = cptr->colors.pattern.p_tile;
@@ -665,7 +652,8 @@ private RELOC_PTRS_BEGIN(dc_pattern_reloc_ptrs)
RELOC_USING(st_dc_pure_masked, vptr, size);
}
RELOC_PTRS_END
-private ENUM_PTRS_BEGIN(dc_masked_enum_ptrs) ENUM_SUPER(gx_device_color, st_client_color, ccolor, 1);
+private ENUM_PTRS_WITH(dc_masked_enum_ptrs, gx_device_color *cptr)
+ENUM_SUPER(gx_device_color, st_client_color, ccolor, 1);
case 0:
{
gx_color_tile *mask = cptr->mask.m_tile;
@@ -673,7 +661,7 @@ case 0:
ENUM_RETURN((mask == 0 ? mask : mask - mask->index));
}
ENUM_PTRS_END
-private RELOC_PTRS_BEGIN(dc_masked_reloc_ptrs)
+private RELOC_PTRS_WITH(dc_masked_reloc_ptrs, gx_device_color *cptr)
{
gx_color_tile *mask = cptr->mask.m_tile;
@@ -699,7 +687,6 @@ private RELOC_PTRS_BEGIN(dc_binary_masked_reloc_ptrs)
RELOC_USING(st_dc_ht_binary, vptr, size);
}
RELOC_PTRS_END
-#undef cptr
/* Macros for pattern loading */
#define FINISH_PATTERN_LOAD\
diff --git a/gs/src/gsrefct.h b/gs/src/gsrefct.h
index a188cea71..179ec550e 100644
--- a/gs/src/gsrefct.h
+++ b/gs/src/gsrefct.h
@@ -26,6 +26,15 @@
* A reference-counted object must include the following header:
* rc_header rc;
* The header need not be the first element of the object.
+ *
+ * Reference-counted objects have a freeing procedure that gets called when
+ * the reference count reaches zero. In retrospect, we probably should have
+ * used finalization for this, but it's too difficult to change now.
+ * Because of the interaction between these two features, the freeing
+ * procedure for reference-counted objects that do use finalization must
+ * free the object itself first, before decrementing the reference counts
+ * of referenced objects (which of course requires saving pointers to those
+ * objects before freeing the containing object).
*/
typedef struct rc_header_s rc_header;
struct rc_header_s {
@@ -37,7 +46,14 @@ struct rc_header_s {
};
#ifdef DEBUG
-const char *rc_object_type_name(P2(const void *vp, const rc_header *prc));
+void rc_trace_init_free(P2(const void *vp, const rc_header *prc));
+void rc_trace_free_struct(P3(const void *vp, const rc_header *prc,
+ client_name_t cname));
+void rc_trace_increment(P2(const void *vp, const rc_header *prc));
+void rc_trace_adjust(P3(const void *vp, const rc_header *prc, int delta));
+#define IF_RC_DEBUG(call) if (gs_debug_c('^')) dlputs(""), call
+#else
+#define IF_RC_DEBUG(call) DO_NOTHING
#endif
/* ------ Allocate/free ------ */
@@ -49,8 +65,7 @@ rc_free_proc(rc_free_struct_only);
(vp)->rc.ref_count = rcinit;\
(vp)->rc.memory = mem;\
(vp)->rc.free = proc;\
- if_debug3('^', "[^]%s 0x%lx init = %d\n",\
- rc_object_type_name(vp, &(vp)->rc), (ulong)vp, rcinit);\
+ IF_RC_DEBUG(rc_trace_init_free(vp, &(vp)->rc));\
END
#define rc_init(vp, mem, rcinit)\
rc_init_free(vp, mem, rcinit, rc_free_struct_only)
@@ -70,9 +85,7 @@ rc_free_proc(rc_free_struct_only);
#define rc_free_struct(vp, cname)\
BEGIN\
- if_debug3('^', "[^]%s 0x%lx => free (%s)\n",\
- rc_object_type_name(vp, &(vp)->rc),\
- (ulong)vp, client_name_string(cname));\
+ IF_RC_DEBUG(rc_trace_free_struct(vp, &(vp)->rc, cname));\
(vp)->rc.free((vp)->rc.memory, (void *)(vp), cname);\
END
@@ -82,9 +95,7 @@ rc_free_proc(rc_free_struct_only);
#define RC_DO_INCREMENT(vp)\
BEGIN\
(vp)->rc.ref_count++;\
- if_debug3('^', "[^]%s 0x%lx ++ => %ld\n",\
- rc_object_type_name(vp, &(vp)->rc),\
- (ulong)vp, (long)(vp)->rc.ref_count);\
+ IF_RC_DEBUG(rc_trace_increment(vp, &(vp)->rc));\
END
#define rc_increment(vp)\
BEGIN\
@@ -103,9 +114,7 @@ rc_free_proc(rc_free_struct_only);
/* Guarantee that a structure is allocated and is not shared. */
#define RC_DO_ADJUST(vp, delta)\
BEGIN\
- if_debug4('^', "[^]%s 0x%lx %+d => %ld\n",\
- rc_object_type_name(vp, &(vp)->rc),\
- (ulong)vp, delta, (long)((vp)->rc.ref_count + (delta)));\
+ IF_RC_DEBUG(rc_trace_adjust(vp, &(vp)->rc, delta));\
(vp)->rc.ref_count += (delta);\
END
#define rc_unshare_struct(vp, typ, pstype, mem, errstat, cname)\
diff --git a/gs/src/gsropc.c b/gs/src/gsropc.c
index ef690bea8..9d9926e70 100644
--- a/gs/src/gsropc.c
+++ b/gs/src/gsropc.c
@@ -181,12 +181,9 @@ c_rop_create_default_compositor(const gs_composite_t * pcte,
*pcdev = (gx_device *) cdev;
if (cdev == 0)
return_error(gs_error_VMerror);
- *(gx_device *) cdev = *dev;
- cdev->dname = gs_composite_rop_device.dname;
- cdev->memory = mem;
- cdev->stype = &st_device_composite_rop;
- cdev->color_info = dev->color_info;
- assign_dev_procs(cdev, &gs_composite_rop_device);
+ gx_device_init((gx_device *)cdev,
+ (const gx_device *)&gs_composite_rop_device, mem, true);
+ gx_device_copy_params((gx_device *)cdev, dev);
/*
* Check for memory devices, and select the correct RasterOp
* implementation based on depth and device color space.
@@ -211,9 +208,6 @@ dcr_close(gx_device * dev)
/* ------ Imaging ------ */
/* Import the existing RasterOp implementations. */
-extern dev_proc_strip_copy_rop(mem_mono_strip_copy_rop);
-extern dev_proc_strip_copy_rop(mem_gray_strip_copy_rop);
-extern dev_proc_strip_copy_rop(mem_gray8_rgb24_strip_copy_rop);
extern dev_proc_strip_copy_rop(gx_default_strip_copy_rop);
private int
diff --git a/gs/src/gsshade.c b/gs/src/gsshade.c
index e9ea9192f..4191c052e 100644
--- a/gs/src/gsshade.c
+++ b/gs/src/gsshade.c
@@ -477,7 +477,7 @@ gs_shading_fill_path(const gs_shading_t *psh, /*const*/ gx_path *ppath,
gx_cpath_intersect(path_clip, ppath, gx_rule_winding_number, pis)) < 0
)
goto out;
- gx_make_clip_device(&path_dev, &path_dev, &path_clip->rect_list->list);
+ gx_make_clip_device(&path_dev, &path_clip->rect_list->list);
path_dev.target = dev;
dev = (gx_device *)&path_dev;
dev_proc(dev, open_device)(dev);
diff --git a/gs/src/gsstate.c b/gs/src/gsstate.c
index 1693bd50d..380368fd1 100644
--- a/gs/src/gsstate.c
+++ b/gs/src/gsstate.c
@@ -167,18 +167,18 @@ typedef struct gs_state_parts_s {
/* GC descriptors */
extern_st(st_imager_state);
-private_st_gs_state();
+public_st_gs_state();
/* GC procedures for gs_state */
-#define gsvptr ((gs_state *)vptr)
-private ENUM_PTRS_BEGIN(gs_state_enum_ptrs) ENUM_PREFIX(st_imager_state, gs_state_num_ptrs + 1);
+private ENUM_PTRS_WITH(gs_state_enum_ptrs, gs_state *gsvptr)
+ENUM_PREFIX(st_imager_state, gs_state_num_ptrs + 1);
#define e1(i,elt) ENUM_PTR(i,gs_state,elt);
gs_state_do_ptrs(e1)
case gs_state_num_ptrs: /* handle device specially */
ENUM_RETURN(gx_device_enum_ptr(gsvptr->device));
#undef e1
ENUM_PTRS_END
-private RELOC_PTRS_BEGIN(gs_state_reloc_ptrs)
+private RELOC_PTRS_WITH(gs_state_reloc_ptrs, gs_state *gsvptr)
{
RELOC_PREFIX(st_imager_state);
{
@@ -189,7 +189,6 @@ private RELOC_PTRS_BEGIN(gs_state_reloc_ptrs)
}
}
RELOC_PTRS_END
-#undef gsvptr
/* Copy client data, using the copy_for procedure if available, */
/* the copy procedure otherwise. */
@@ -204,6 +203,11 @@ gstate_copy_client_data(gs_state * pgs, void *dto, void *dfrom,
/* ------ Operations on the entire graphics state ------ */
+/* Define the initial value of the graphics state. */
+private const gs_imager_state gstate_initial = {
+ gs_imager_state_initial(1.0)
+};
+
/* Allocate and initialize a graphics state. */
gs_state *
gs_state_alloc(gs_memory_t * mem)
@@ -214,13 +218,7 @@ gs_state_alloc(gs_memory_t * mem)
if (pgs == 0)
return 0;
pgs->saved = 0;
- {
- static const gs_imager_state gstate_initial = {
- gs_imager_state_initial(1.0)
- };
-
- *(gs_imager_state *) pgs = gstate_initial;
- }
+ *(gs_imager_state *)pgs = gstate_initial;
/*
* Just enough of the state is initialized at this point
@@ -398,7 +396,7 @@ fail:
/* Restore the graphics state. Can fully empty graphics stack */
int /* return 0 if ok, 1 if stack was empty */
-gs_grestore_no_wraparound(gs_state * pgs)
+gs_grestore_only(gs_state * pgs)
{
gs_state *saved = pgs->saved;
void *pdata = pgs->client_data;
@@ -425,12 +423,13 @@ gs_grestore_no_wraparound(gs_state * pgs)
}
/* Restore the graphics state per PostScript semantics */
-int gs_grestore(gs_state * pgs)
+int
+gs_grestore(gs_state * pgs)
{
int code;
if (!pgs->saved)
return gs_gsave(pgs); /* shouldn't ever happen */
- code = gs_grestore_no_wraparound(pgs);
+ code = gs_grestore_only(pgs);
if (code < 0)
return code;
@@ -621,14 +620,15 @@ gs_initgraphics(gs_state * pgs)
if ((code = gs_newpath(pgs)) < 0 ||
(code = gs_initclip(pgs)) < 0 ||
(code = gs_setlinewidth(pgs, 1.0)) < 0 ||
- (code = gs_setlinecap(pgs, gs_cap_butt)) < 0 ||
- (code = gs_setlinejoin(pgs, gs_join_miter)) < 0 ||
+ (code = gs_setlinecap(pgs, gstate_initial.line_params.cap)) < 0 ||
+ (code = gs_setlinejoin(pgs, gstate_initial.line_params.join)) < 0 ||
+ (code = gs_setcurvejoin(pgs, gstate_initial.line_params.curve_join)) < 0 ||
(code = gs_setdash(pgs, (float *)0, 0, 0.0)) < 0 ||
(gs_setdashadapt(pgs, false),
(code = gs_setdotlength(pgs, 0.0, false))) < 0 ||
(code = gs_setdotorientation(pgs)) < 0 ||
(code = gs_setgray(pgs, 0.0)) < 0 ||
- (code = gs_setmiterlimit(pgs, 10.0)) < 0
+ (code = gs_setmiterlimit(pgs, gstate_initial.line_params.miter_limit)) < 0
)
return code;
gs_init_rop(pgs);
diff --git a/gs/src/gsstate.h b/gs/src/gsstate.h
index a95c34722..5d4d354be 100644
--- a/gs/src/gsstate.h
+++ b/gs/src/gsstate.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1989, 1995, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1989, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -26,7 +26,6 @@
#ifndef gs_state_DEFINED
# define gs_state_DEFINED
typedef struct gs_state_s gs_state;
-
#endif
/* Initial allocation and freeing */
@@ -35,7 +34,7 @@ int gs_state_free(P1(gs_state *));
/* Initialization, saving, restoring, and copying */
int gs_gsave(P1(gs_state *)), gs_grestore(P1(gs_state *)), gs_grestoreall(P1(gs_state *));
-int gs_grestore_no_wraparound(P1(gs_state *));
+int gs_grestore_only(P1(gs_state *));
int gs_gsave_for_save(P2(gs_state *, gs_state **)), gs_grestoreall_for_restore(P2(gs_state *, gs_state *));
gs_state *gs_gstate(P1(gs_state *));
gs_state *gs_state_copy(P2(gs_state *, gs_memory_t *));
@@ -72,5 +71,7 @@ int gs_setfilladjust(P3(gs_state *, floatp, floatp));
int gs_currentfilladjust(P2(const gs_state *, gs_point *));
void gs_setlimitclamp(P2(gs_state *, bool));
bool gs_currentlimitclamp(P1(const gs_state *));
+#include "gscpm.h"
+gs_in_cache_device_t gs_incachedevice(P1(const gs_state *));
#endif /* gsstate_INCLUDED */
diff --git a/gs/src/gsstruct.h b/gs/src/gsstruct.h
index 0632f2351..9421db3e1 100644
--- a/gs/src/gsstruct.h
+++ b/gs/src/gsstruct.h
@@ -98,14 +98,14 @@ struct gs_ptr_procs_s {
/* Unmark the referent of a pointer. */
#define ptr_proc_unmark(proc)\
- void proc(P2(void *, gc_state_t *))
+ void proc(P2(enum_ptr_t *, gc_state_t *))
ptr_proc_unmark((*unmark));
/* Mark the referent of a pointer. */
/* Return true iff it was unmarked before. */
#define ptr_proc_mark(proc)\
- bool proc(P2(void *, gc_state_t *))
+ bool proc(P2(enum_ptr_t *, gc_state_t *))
ptr_proc_mark((*mark));
/* Relocate a pointer. */
@@ -202,11 +202,11 @@ extern_st(st_gc_root_t);
/* Elements and arrays of const strings. */
#define private_st_const_string()\
- private const gc_ptr_element_t const_string_elts[] = {\
+ BASIC_PTRS(const_string_elts) {\
{ GC_ELT_CONST_STRING, 0 }\
};\
- gs__st_basic_with_final(private_st, st_const_string, gs_const_string,\
- "gs_const_string", 1, const_string_elts, const_string_sdata, 0, 0, 0)
+ gs__st_basic(private_st, st_const_string, gs_const_string,\
+ "gs_const_string", const_string_elts, const_string_sdata)
extern_st(st_const_string_element);
#define public_st_const_string_element()\
@@ -266,16 +266,22 @@ typedef struct gc_struct_data_s {
* proc_data points to a gc_struct_data_t. The standard defining form
* is:
- private const gc_ptr_element_t XXX[] = {
+ BASIC_PTRS(xxx_ptrs) {
... elements ...
};
- gs_(private|public)_st_basic(stname, stype, sname, XXX, YYY, supst, supoff);
+ gs_(private|public)_st_basic_super_final(stname, stype, sname, xxx_ptrs,
+ xxx_data, supst, supoff, pfinal);
+ gs_(private|public)_st_basic_super(stname, stype, sname, xxx_ptrs, xxx_data,
+ supst, supoff);
+ gs_(private|public)_st_basic(stname, stype, sname, xxx_ptrs, xxx_data);
*/
struct_proc_enum_ptrs(basic_enum_ptrs);
struct_proc_reloc_ptrs(basic_reloc_ptrs);
-#define gs__st_basic_with_final(scope_st, stname, stype, sname, nelts, elts, sdata, supst, supoff, pfinal)\
+#define BASIC_PTRS(elts)\
+ private const gc_ptr_element_t elts[] =
+#define gs__st_basic_with_super_final(scope_st, stname, stype, sname, nelts, elts, sdata, supst, supoff, pfinal)\
private const gc_struct_data_t sdata = {\
nelts, supoff, supst, elts\
};\
@@ -283,18 +289,27 @@ struct_proc_reloc_ptrs(basic_reloc_ptrs);
sizeof(stype), sname, 0, 0, basic_enum_ptrs, basic_reloc_ptrs,\
pfinal, &sdata\
}
-#define gs__st_basic_final(scope_st, stname, stype, sname, elts, sdata, supst, supoff, pfinal)\
- gs__st_basic_with_final(scope_st, stname, stype, sname, countof(elts), elts, sdata, supst, supoff, pfinal)
-#define gs_public_st_basic_final(stname, stype, sname, elts, sdata, supst, supoff, pfinal)\
- gs__st_basic_final(public_st, stname, stype, sname, elts, sdata, supst, supoff, pfinal)
-#define gs_private_st_basic_final(stname, stype, sname, elts, sdata, supst, supoff, pfinal)\
- gs__st_basic_final(private_st, stname, stype, sname, elts, sdata, supst, supoff, pfinal)
-#define gs__st_basic(scope_st, stname, stype, sname, elts, sdata, supst, supoff)\
- gs__st_basic_with_final(scope_st, stname, stype, sname, countof(elts), elts, sdata, supst, supoff, 0)
-#define gs_public_st_basic(stname, stype, sname, elts, sdata, supst, supoff)\
- gs__st_basic(public_st, stname, stype, sname, elts, sdata, supst, supoff)
-#define gs_private_st_basic(stname, stype, sname, elts, sdata, supst, supoff)\
- gs__st_basic(private_st, stname, stype, sname, elts, sdata, supst, supoff)
+ /* Basic objects with superclass and finalization. */
+#define gs__st_basic_super_final(scope_st, stname, stype, sname, elts, sdata, supst, supoff, pfinal)\
+ gs__st_basic_with_super_final(scope_st, stname, stype, sname, countof(elts), elts, sdata, supst, supoff, pfinal)
+#define gs_public_st_basic_super_final(stname, stype, sname, elts, sdata, supst, supoff, pfinal)\
+ gs__st_basic_super_final(public_st, stname, stype, sname, elts, sdata, supst, supoff, pfinal)
+#define gs_private_st_basic_super_final(stname, stype, sname, elts, sdata, supst, supoff, pfinal)\
+ gs__st_basic_super_final(private_st, stname, stype, sname, elts, sdata, supst, supoff, pfinal)
+ /* Basic objects with only superclass. */
+#define gs__st_basic_super(scope_st, stname, stype, sname, elts, sdata, supst, supoff)\
+ gs__st_basic_super_final(scope_st, stname, stype, sname, elts, sdata, supst, supoff, 0)
+#define gs_public_st_basic_super(stname, stype, sname, elts, sdata, supst, supoff)\
+ gs__st_basic_super(public_st, stname, stype, sname, elts, sdata, supst, supoff)
+#define gs_private_st_basic_super(stname, stype, sname, elts, sdata, supst, supoff)\
+ gs__st_basic_super(private_st, stname, stype, sname, elts, sdata, supst, supoff)
+ /* Basic objects with no frills. */
+#define gs__st_basic(scope_st, stname, stype, sname, elts, sdata)\
+ gs__st_basic_super(scope_st, stname, stype, sname, elts, sdata, 0, 0)
+#define gs_public_st_basic(stname, stype, sname, elts, sdata)\
+ gs__st_basic(public_st, stname, stype, sname, elts, sdata)
+#define gs_private_st_basic(stname, stype, sname, elts, sdata)\
+ gs__st_basic(private_st, stname, stype, sname, elts, sdata)
/*
* The simplest kind of composite structure is one with a fixed set of
@@ -302,10 +317,10 @@ struct_proc_reloc_ptrs(basic_reloc_ptrs);
* defining this kind of structure conveniently, either all at once in
* the structure definition macro, or using the following template:
- ENUM_PTRS_WITH(xxx_enum_ptrs, stype *myptr) return 0;
+ ENUM_PTRS_WITH(xxx_enum_ptrs, stype *const myptr) return 0;
... ENUM_PTR(i, xxx, elt); ...
ENUM_PTRS_END
- RELOC_PTRS_WITH(xxx_reloc_ptrs, stype *myptr)
+ RELOC_PTRS_WITH(xxx_reloc_ptrs, stype *const myptr)
{
...
RELOC_VAR(myptr->elt);
@@ -324,10 +339,10 @@ struct_proc_reloc_ptrs(basic_reloc_ptrs);
#ifdef __PROTOTYPES__
# define ENUM_PTRS_BEGIN_PROC(proc)\
- gs_ptr_type_t proc(EV_CONST void *vptr, uint size, int index, const void **pep, const gs_memory_struct_type_t *pstype, gc_state_t *gcst)
+ gs_ptr_type_t proc(EV_CONST void *vptr, uint size, int index, enum_ptr_t *pep, const gs_memory_struct_type_t *pstype, gc_state_t *gcst)
#else
# define ENUM_PTRS_BEGIN_PROC(proc)\
- gs_ptr_type_t proc(vptr, size, index, pep, pstype, gcst) EV_CONST void *vptr; uint size; int index; const void **pep; const gs_memory_struct_type_t *pstype; gc_state_t *gcst;
+ gs_ptr_type_t proc(vptr, size, index, pep, pstype, gcst) EV_CONST void *vptr; uint size; int index; enum_ptr_t *pep; const gs_memory_struct_type_t *pstype; gc_state_t *gcst;
#endif
#define ENUM_PTRS_BEGIN(proc)\
ENUM_PTRS_BEGIN_PROC(proc)\
@@ -338,18 +353,22 @@ struct_proc_reloc_ptrs(basic_reloc_ptrs);
/* Enumerate elements */
-#define ENUM_OBJ(ptr) /* pointer to object */\
- (*pep = (const void *)(ptr), ptr_struct_type)
-#define ENUM_STRING(ptr) /* pointer to gs_string */\
- (*pep = (const void *)(ptr), ptr_string_type)
-#define ENUM_CONST_STRING(ptr) /* pointer to gs_const_string */\
- (*pep = (const void *)(ptr), ptr_const_string_type)
+#define ENUM_OBJ(optr) /* pointer to object */\
+ (pep->ptr = (const void *)(optr), ptr_struct_type)
+#define ENUM_STRING2(sdata, ssize) /* gs_string */\
+ (pep->ptr = sdata, pep->size = ssize, ptr_string_type)
+#define ENUM_STRING(sptr) /* pointer to gs_string */\
+ ENUM_STRING2((sptr)->data, (sptr)->size)
+#define ENUM_CONST_STRING2(sdata, ssize) /* gs_const_string */\
+ (pep->ptr = sdata, pep->size = ssize, ptr_const_string_type)
+#define ENUM_CONST_STRING(sptr) /* pointer to gs_const_string */\
+ ENUM_CONST_STRING2((sptr)->data, (sptr)->size)
extern gs_ptr_type_t
- enum_bytestring(P2(const void **pep, const gs_bytestring *pbs));
+ enum_bytestring(P2(enum_ptr_t *pep, const gs_bytestring *pbs));
#define ENUM_BYTESTRING(ptr) /* pointer to gs_bytestring */\
enum_bytestring(pep, ptr)
extern gs_ptr_type_t
- enum_const_bytestring(P2(const void **pep, const gs_const_bytestring *pbs));
+ enum_const_bytestring(P2(enum_ptr_t *pep, const gs_const_bytestring *pbs));
#define ENUM_CONST_BYTESTRING(ptr) /* pointer to gs_const_bytestring */\
enum_const_bytestring(pep, ptr)
@@ -619,10 +638,10 @@ extern void reloc_const_bytestring(P2(gs_const_bytestring *pbs, gc_state_t *gcst
/* Structures with 1 pointer. */
#define gs__st_ptrs1(scope_st, stname, stype, sname, penum, preloc, e1)\
- private const gc_ptr_element_t penum[] = {\
+ BASIC_PTRS(penum) {\
GC_OBJ_ELT(stype, e1)\
};\
- gs__st_basic(scope_st, stname, stype, sname, penum, preloc, 0, 0)
+ gs__st_basic(scope_st, stname, stype, sname, penum, preloc)
#define gs_public_st_ptrs1(stname, stype, sname, penum, preloc, e1)\
gs__st_ptrs1(public_st, stname, stype, sname, penum, preloc, e1)
#define gs_private_st_ptrs1(stname, stype, sname, penum, preloc, e1)\
@@ -631,10 +650,10 @@ extern void reloc_const_bytestring(P2(gs_const_bytestring *pbs, gc_state_t *gcst
/* Structures with 1 string. */
#define gs__st_strings1(scope_st, stname, stype, sname, penum, preloc, e1)\
- private const gc_ptr_element_t penum[] = {\
+ BASIC_PTRS(penum) {\
GC_STRING_ELT(stype, e1)\
};\
- gs__st_basic(scope_st, stname, stype, sname, penum, preloc, 0, 0)
+ gs__st_basic(scope_st, stname, stype, sname, penum, preloc)
#define gs_public_st_strings1(stname, stype, sname, penum, preloc, e1)\
gs__st_strings1(public_st, stname, stype, sname, penum, preloc, e1)
#define gs_private_st_strings1(stname, stype, sname, penum, preloc, e1)\
@@ -643,46 +662,22 @@ extern void reloc_const_bytestring(P2(gs_const_bytestring *pbs, gc_state_t *gcst
/* Structures with 1 const string. */
#define gs__st_const_strings1(scope_st, stname, stype, sname, penum, preloc, e1)\
- private const gc_ptr_element_t penum[] = {\
+ BASIC_PTRS(penum) {\
GC_CONST_STRING_ELT(stype, e1)\
};\
- gs__st_basic(scope_st, stname, stype, sname, penum, preloc, 0, 0)
+ gs__st_basic(scope_st, stname, stype, sname, penum, preloc)
#define gs_public_st_const_strings1(stname, stype, sname, penum, preloc, e1)\
gs__st_const_strings1(public_st, stname, stype, sname, penum, preloc, e1)
#define gs_private_st_const_strings1(stname, stype, sname, penum, preloc, e1)\
gs__st_const_strings1(private_st, stname, stype, sname, penum, preloc, e1)
- /* Structures with 1 pointer and 1 string. */
-
-#define gs__st_ptrs1_strings1(scope_st, stname, stype, sname, penum, preloc, e1, e2)\
- private const gc_ptr_element_t penum[] = {\
- GC_OBJ_ELT(stype, e1), GC_STRING_ELT(stype, e2)\
- };\
- gs__st_basic(scope_st, stname, stype, sname, penum, preloc, 0, 0)
-#define gs_public_st_ptrs1_strings1(stname, stype, sname, penum, preloc, e1, e2)\
- gs__st_ptrs1_strings1(public_st, stname, stype, sname, penum, preloc, e1, e2)
-#define gs_private_st_ptrs1_strings1(stname, stype, sname, penum, preloc, e1, e2)\
- gs__st_ptrs1_strings1(private_st, stname, stype, sname, penum, preloc, e1, e2)
-
- /* Structures with 1 pointer and 2 strings. */
-
-#define gs__st_ptrs1_strings2(scope_st, stname, stype, sname, penum, preloc, e1, e2, e3)\
- private const gc_ptr_element_t penum[] = {\
- GC_OBJ_ELT(stype, e1), GC_STRING_ELT(stype, e2), GC_STRING_ELT(stype, e3)\
- };\
- gs__st_basic(scope_st, stname, stype, sname, penum, preloc, 0, 0)
-#define gs_public_st_ptrs1_strings2(stname, stype, sname, penum, preloc, e1, e2, e3)\
- gs__st_ptrs1_strings2(public_st, stname, stype, sname, penum, preloc, e1, e2, e3)
-#define gs_private_st_ptrs1_strings2(stname, stype, sname, penum, preloc, e1, e2, e3)\
- gs__st_ptrs1_strings2(private_st, stname, stype, sname, penum, preloc, e1, e2, e3)
-
/* Structures with 2 const strings. */
#define gs__st_const_strings2(scope_st, stname, stype, sname, penum, preloc, e1, e2)\
- private const gc_ptr_element_t penum[] = {\
+ BASIC_PTRS(penum) {\
GC_CONST_STRING_ELT(stype, e1), GC_CONST_STRING_ELT(stype, e2)\
};\
- gs__st_basic(scope_st, stname, stype, sname, penum, preloc, 0, 0)
+ gs__st_basic(scope_st, stname, stype, sname, penum, preloc)
#define gs_public_st_const_strings2(stname, stype, sname, penum, preloc, e1, e2)\
gs__st_const_strings2(public_st, stname, stype, sname, penum, preloc, e1, e2)
#define gs_private_st_const_strings2(stname, stype, sname, penum, preloc, e1, e2)\
@@ -691,10 +686,10 @@ extern void reloc_const_bytestring(P2(gs_const_bytestring *pbs, gc_state_t *gcst
/* Structures with 2 pointers. */
#define gs__st_ptrs2(scope_st, stname, stype, sname, penum, preloc, e1, e2)\
- private const gc_ptr_element_t penum[] = {\
+ BASIC_PTRS(penum) {\
GC_OBJ_ELT2(stype, e1, e2)\
};\
- gs__st_basic(scope_st, stname, stype, sname, penum, preloc, 0, 0)
+ gs__st_basic(scope_st, stname, stype, sname, penum, preloc)
#define gs_public_st_ptrs2(stname, stype, sname, penum, preloc, e1, e2)\
gs__st_ptrs2(public_st, stname, stype, sname, penum, preloc, e1, e2)
#define gs_private_st_ptrs2(stname, stype, sname, penum, preloc, e1, e2)\
@@ -703,10 +698,10 @@ extern void reloc_const_bytestring(P2(gs_const_bytestring *pbs, gc_state_t *gcst
/* Structures with 3 pointers. */
#define gs__st_ptrs3(scope_st, stname, stype, sname, penum, preloc, e1, e2, e3)\
- private const gc_ptr_element_t penum[] = {\
+ BASIC_PTRS(penum) {\
GC_OBJ_ELT3(stype, e1, e2, e3)\
};\
- gs__st_basic(scope_st, stname, stype, sname, penum, preloc, 0, 0)
+ gs__st_basic(scope_st, stname, stype, sname, penum, preloc)
#define gs_public_st_ptrs3(stname, stype, sname, penum, preloc, e1, e2, e3)\
gs__st_ptrs3(public_st, stname, stype, sname, penum, preloc, e1, e2, e3)
#define gs_private_st_ptrs3(stname, stype, sname, penum, preloc, e1, e2, e3)\
@@ -715,10 +710,10 @@ extern void reloc_const_bytestring(P2(gs_const_bytestring *pbs, gc_state_t *gcst
/* Structures with 4 pointers. */
#define gs__st_ptrs4(scope_st, stname, stype, sname, penum, preloc, e1, e2, e3, e4)\
- private const gc_ptr_element_t penum[] = {\
+ BASIC_PTRS(penum) {\
GC_OBJ_ELT3(stype, e1, e2, e3), GC_OBJ_ELT(stype, e4)\
};\
- gs__st_basic(scope_st, stname, stype, sname, penum, preloc, 0, 0)
+ gs__st_basic(scope_st, stname, stype, sname, penum, preloc)
#define gs_public_st_ptrs4(stname, stype, sname, penum, preloc, e1, e2, e3, e4)\
gs__st_ptrs4(public_st, stname, stype, sname, penum, preloc, e1, e2, e3, e4)
#define gs_private_st_ptrs4(stname, stype, sname, penum, preloc, e1, e2, e3, e4)\
@@ -727,10 +722,10 @@ extern void reloc_const_bytestring(P2(gs_const_bytestring *pbs, gc_state_t *gcst
/* Structures with 5 pointers. */
#define gs__st_ptrs5(scope_st, stname, stype, sname, penum, preloc, e1, e2, e3, e4, e5)\
- private const gc_ptr_element_t penum[] = {\
+ BASIC_PTRS(penum) {\
GC_OBJ_ELT3(stype, e1, e2, e3), GC_OBJ_ELT2(stype, e4, e5)\
};\
- gs__st_basic(scope_st, stname, stype, sname, penum, preloc, 0, 0)
+ gs__st_basic(scope_st, stname, stype, sname, penum, preloc)
#define gs_public_st_ptrs5(stname, stype, sname, penum, preloc, e1, e2, e3, e4, e5)\
gs__st_ptrs5(public_st, stname, stype, sname, penum, preloc, e1, e2, e3, e4, e5)
#define gs_private_st_ptrs5(stname, stype, sname, penum, preloc, e1, e2, e3, e4, e5)\
@@ -739,10 +734,10 @@ extern void reloc_const_bytestring(P2(gs_const_bytestring *pbs, gc_state_t *gcst
/* Structures with 6 pointers. */
#define gs__st_ptrs6(scope_st, stname, stype, sname, penum, preloc, e1, e2, e3, e4, e5, e6)\
- private const gc_ptr_element_t penum[] = {\
+ BASIC_PTRS(penum) {\
GC_OBJ_ELT3(stype, e1, e2, e3), GC_OBJ_ELT3(stype, e4, e5, e6)\
};\
- gs__st_basic(scope_st, stname, stype, sname, penum, preloc, 0, 0)
+ gs__st_basic(scope_st, stname, stype, sname, penum, preloc)
#define gs_public_st_ptrs6(stname, stype, sname, penum, preloc, e1, e2, e3, e4, e5, e6)\
gs__st_ptrs6(public_st, stname, stype, sname, penum, preloc, e1, e2, e3, e4, e5, e6)
#define gs_private_st_ptrs6(stname, stype, sname, penum, preloc, e1, e2, e3, e4, e5, e6)\
@@ -753,7 +748,7 @@ extern void reloc_const_bytestring(P2(gs_const_bytestring *pbs, gc_state_t *gcst
/* Suffix subclasses with no additional pointers. */
#define gs__st_suffix_add0(scope_st, stname, stype, sname, penum, preloc, supstname)\
- gs__st_basic_with_final(scope_st, stname, stype, sname, 0, 0, preloc, &supstname, 0, 0)
+ gs__st_basic_with_super_final(scope_st, stname, stype, sname, 0, 0, preloc, &supstname, 0, 0)
#define gs_public_st_suffix_add0(stname, stype, sname, penum, preloc, supstname)\
gs__st_suffix_add0(public_st, stname, stype, sname, penum, preloc, supstname)
#define gs_private_st_suffix_add0(stname, stype, sname, penum, preloc, supstname)\
@@ -795,10 +790,10 @@ extern void reloc_const_bytestring(P2(gs_const_bytestring *pbs, gc_state_t *gcst
/* Suffix subclasses with 1 additional pointer. */
#define gs__st_suffix_add1(scope_st, stname, stype, sname, penum, preloc, supstname, e1)\
- private const gc_ptr_element_t penum[] = {\
+ BASIC_PTRS(penum) {\
GC_OBJ_ELT(stype, e1)\
};\
- gs__st_basic(scope_st, stname, stype, sname, penum, preloc, &supstname, 0)
+ gs__st_basic_super(scope_st, stname, stype, sname, penum, preloc, &supstname, 0)
#define gs_public_st_suffix_add1(stname, stype, sname, penum, preloc, supstname, e1)\
gs__st_suffix_add1(public_st, stname, stype, sname, penum, preloc, supstname, e1)
#define gs_private_st_suffix_add1(stname, stype, sname, penum, preloc, supstname, e1)\
@@ -808,10 +803,10 @@ extern void reloc_const_bytestring(P2(gs_const_bytestring *pbs, gc_state_t *gcst
/* See above regarding finalization and subclasses. */
#define gs__st_suffix_add1_final(scope_st, stname, stype, sname, penum, preloc, pfinal, supstname, e1)\
- private const gc_ptr_element_t penum[] = {\
+ BASIC_PTRS(penum) {\
GC_OBJ_ELT(stype, e1)\
};\
- gs__st_basic_final(scope_st, stname, stype, sname, penum, preloc, &supstname, 0, pfinal)
+ gs__st_basic_super_final(scope_st, stname, stype, sname, penum, preloc, &supstname, 0, pfinal)
#define gs_public_st_suffix_add1_final(stname, stype, sname, penum, preloc, pfinal, supstname, e1)\
gs__st_suffix_add1_final(public_st, stname, stype, sname, penum, preloc, pfinal, supstname, e1)
#define gs_private_st_suffix_add1_final(stname, stype, sname, penum, preloc, pfinal, supstname, e1)\
@@ -820,10 +815,10 @@ extern void reloc_const_bytestring(P2(gs_const_bytestring *pbs, gc_state_t *gcst
/* Suffix subclasses with 2 additional pointers. */
#define gs__st_suffix_add2(scope_st, stname, stype, sname, penum, preloc, supstname, e1, e2)\
- private const gc_ptr_element_t penum[] = {\
+ BASIC_PTRS(penum) {\
GC_OBJ_ELT2(stype, e1, e2)\
};\
- gs__st_basic(scope_st, stname, stype, sname, penum, preloc, &supstname, 0)
+ gs__st_basic_super(scope_st, stname, stype, sname, penum, preloc, &supstname, 0)
#define gs_public_st_suffix_add2(stname, stype, sname, penum, preloc, supstname, e1, e2)\
gs__st_suffix_add2(public_st, stname, stype, sname, penum, preloc, supstname, e1, e2)
#define gs_private_st_suffix_add2(stname, stype, sname, penum, preloc, supstname, e1, e2)\
@@ -833,10 +828,10 @@ extern void reloc_const_bytestring(P2(gs_const_bytestring *pbs, gc_state_t *gcst
/* See above regarding finalization and subclasses. */
#define gs__st_suffix_add2_final(scope_st, stname, stype, sname, penum, preloc, pfinal, supstname, e1, e2)\
- private const gc_ptr_element_t penum[] = {\
+ BASIC_PTRS(penum) {\
GC_OBJ_ELT2(stype, e1, e2)\
};\
- gs__st_basic_final(scope_st, stname, stype, sname, penum, preloc, &supstname, 0, pfinal)
+ gs__st_basic_super_final(scope_st, stname, stype, sname, penum, preloc, &supstname, 0, pfinal)
#define gs_public_st_suffix_add2_final(stname, stype, sname, penum, preloc, pfinal, supstname, e1, e2)\
gs__st_suffix_add2_final(public_st, stname, stype, sname, penum, preloc, pfinal, supstname, e1, e2)
#define gs_private_st_suffix_add2_final(stname, stype, sname, penum, preloc, pfinal, supstname, e1, e2)\
@@ -845,10 +840,10 @@ extern void reloc_const_bytestring(P2(gs_const_bytestring *pbs, gc_state_t *gcst
/* Suffix subclasses with 3 additional pointers. */
#define gs__st_suffix_add3(scope_st, stname, stype, sname, penum, preloc, supstname, e1, e2, e3)\
- private const gc_ptr_element_t penum[] = {\
+ BASIC_PTRS(penum) {\
GC_OBJ_ELT3(stype, e1, e2, e3)\
};\
- gs__st_basic(scope_st, stname, stype, sname, penum, preloc, &supstname, 0)
+ gs__st_basic_super(scope_st, stname, stype, sname, penum, preloc, &supstname, 0)
#define gs_public_st_suffix_add3(stname, stype, sname, penum, preloc, supstname, e1, e2, e3)\
gs__st_suffix_add3(public_st, stname, stype, sname, penum, preloc, supstname, e1, e2, e3)
#define gs_private_st_suffix_add3(stname, stype, sname, penum, preloc, supstname, e1, e2, e3)\
@@ -858,10 +853,10 @@ extern void reloc_const_bytestring(P2(gs_const_bytestring *pbs, gc_state_t *gcst
/* See above regarding finalization and subclasses. */
#define gs__st_suffix_add3_final(scope_st, stname, stype, sname, penum, preloc, pfinal, supstname, e1, e2, e3)\
- private const gc_ptr_element_t penum[] = {\
+ BASIC_PTRS(penum) {\
GC_OBJ_ELT3(stype, e1, e2, e3)\
};\
- gs__st_basic_final(scope_st, stname, stype, sname, penum, preloc, &supstname, 0, pfinal)
+ gs__st_basic_super_final(scope_st, stname, stype, sname, penum, preloc, &supstname, 0, pfinal)
#define gs_public_st_suffix_add3_final(stname, stype, sname, penum, preloc, pfinal, supstname, e1, e2, e3)\
gs__st_suffix_add3_final(public_st, stname, stype, sname, penum, preloc, pfinal, supstname, e1, e2, e3)
#define gs_private_st_suffix_add3_final(stname, stype, sname, penum, preloc, pfinal, supstname, e1, e2, e3)\
@@ -870,21 +865,46 @@ extern void reloc_const_bytestring(P2(gs_const_bytestring *pbs, gc_state_t *gcst
/* Suffix subclasses with 4 additional pointers. */
#define gs__st_suffix_add4(scope_st, stname, stype, sname, penum, preloc, supstname, e1, e2, e3, e4)\
- private const gc_ptr_element_t penum[] = {\
+ BASIC_PTRS(penum) {\
GC_OBJ_ELT3(stype, e1, e2, e3), GC_OBJ_ELT(stype, e4)\
};\
- gs__st_basic(scope_st, stname, stype, sname, penum, preloc, &supstname, 0)
+ gs__st_basic_super(scope_st, stname, stype, sname, penum, preloc, &supstname, 0)
#define gs_public_st_suffix_add4(stname, stype, sname, penum, preloc, supstname, e1, e2, e3, e4)\
gs__st_suffix_add4(public_st, stname, stype, sname, penum, preloc, supstname, e1, e2, e3, e4)
#define gs_private_st_suffix_add4(stname, stype, sname, penum, preloc, supstname, e1, e2, e3, e4)\
gs__st_suffix_add4(private_st, stname, stype, sname, penum, preloc, supstname, e1, e2, e3, e4)
+ /* Suffix subclasses with 4 additional pointers and finalization. */
+ /* See above regarding finalization and subclasses. */
+
+#define gs__st_suffix_add4_final(scope_st, stname, stype, sname, penum, preloc, pfinal, supstname, e1, e2, e3, e4)\
+ BASIC_PTRS(penum) {\
+ GC_OBJ_ELT3(stype, e1, e2, e3), GC_OBJ_ELT(stype, e4)\
+ };\
+ gs__st_basic_super_final(scope_st, stname, stype, sname, penum, preloc, &supstname, 0, pfinal)
+#define gs_public_st_suffix_add4_final(stname, stype, sname, penum, preloc, pfinal, supstname, e1, e2, e3, e4)\
+ gs__st_suffix_add4_final(public_st, stname, stype, sname, penum, preloc, pfinal, supstname, e1, e2, e3, e4)
+#define gs_private_st_suffix_add4_final(stname, stype, sname, penum, preloc, pfinal, supstname, e1, e2, e3, e4)\
+ gs__st_suffix_add4_final(private_st, stname, stype, sname, penum, preloc, pfinal, supstname, e1, e2, e3, e4)
+
+ /* Suffix subclasses with 6 additional pointers. */
+
+#define gs__st_suffix_add6(scope_st, stname, stype, sname, penum, preloc, supstname, e1, e2, e3, e4, e5, e6)\
+ BASIC_PTRS(penum) {\
+ GC_OBJ_ELT3(stype, e1, e2, e3), GC_OBJ_ELT3(stype, e4, e5, e6)\
+ };\
+ gs__st_basic_super(scope_st, stname, stype, sname, penum, preloc, &supstname, 0)
+#define gs_public_st_suffix_add6(stname, stype, sname, penum, preloc, supstname, e1, e2, e3, e4, e5, e6)\
+ gs__st_suffix_add6(public_st, stname, stype, sname, penum, preloc, supstname, e1, e2, e3, e4, e5, e6)
+#define gs_private_st_suffix_add6(stname, stype, sname, penum, preloc, supstname, e1, e2, e3, e4, e5, e6)\
+ gs__st_suffix_add6(private_st, stname, stype, sname, penum, preloc, supstname, e1, e2, e3, e4, e5, e6)
+
/* ---------------- General subclasses ---------------- */
/* General subclasses with no additional pointers. */
#define gs__st_ptrs_add0(scope_st, stname, stype, sname, penum, preloc, supstname, member)\
- gs__st_basic_with_final(scope_st, stname, stype, sname, 0, 0, preloc, &supstname, offset_of(stype, member), 0)
+ gs__st_basic_with_super_final(scope_st, stname, stype, sname, 0, 0, preloc, &supstname, offset_of(stype, member), 0)
#define gs_public_st_ptrs_add0(stname, stype, sname, penum, preloc, supstname, member)\
gs__st_ptrs_add0(public_st, stname, stype, sname, penum, preloc, supstname, member)
#define gs_private_st_ptrs_add0(stname, stype, sname, penum, preloc, supstname, member)\
@@ -893,10 +913,10 @@ extern void reloc_const_bytestring(P2(gs_const_bytestring *pbs, gc_state_t *gcst
/* General subclasses with 1 additional pointer. */
#define gs__st_ptrs_add1(scope_st, stname, stype, sname, penum, preloc, supstname, member, e1)\
- private const gc_ptr_element_t penum[] = {\
+ BASIC_PTRS(penum) {\
GC_OBJ_ELT(stype, e1)\
};\
- gs__st_basic(scope_st, stname, stype, sname, penum, preloc, &supstname, offset_of(stype, member))
+ gs__st_basic_super(scope_st, stname, stype, sname, penum, preloc, &supstname, offset_of(stype, member))
#define gs_public_st_ptrs_add1(stname, stype, sname, penum, preloc, supstname, member, e1)\
gs__st_ptrs_add1(public_st, stname, stype, sname, penum, preloc, supstname, member, e1)
#define gs_private_st_ptrs_add1(stname, stype, sname, penum, preloc, supstname, member, e1)\
@@ -905,10 +925,10 @@ extern void reloc_const_bytestring(P2(gs_const_bytestring *pbs, gc_state_t *gcst
/* General subclasses with 2 additional pointers. */
#define gs__st_ptrs_add2(scope_st, stname, stype, sname, penum, preloc, supstname, member, e1, e2)\
- private const gc_ptr_element_t penum[] = {\
+ BASIC_PTRS(penum) {\
GC_OBJ_ELT2(stype, e1, e2)\
};\
- gs__st_basic(scope_st, stname, stype, sname, penum, preloc, &supstname, offset_of(stype, member))
+ gs__st_basic_super(scope_st, stname, stype, sname, penum, preloc, &supstname, offset_of(stype, member))
#define gs_public_st_ptrs_add2(stname, stype, sname, penum, preloc, supstname, member, e1, e2)\
gs__st_ptrs_add2(public_st, stname, stype, sname, penum, preloc, supstname, member, e1, e2)
#define gs_private_st_ptrs_add2(stname, stype, sname, penum, preloc, supstname, member, e1, e2)\
diff --git a/gs/src/gsstype.h b/gs/src/gsstype.h
index 23e822a24..5b1c1cb61 100644
--- a/gs/src/gsstype.h
+++ b/gs/src/gsstype.h
@@ -26,14 +26,21 @@
typedef struct gc_state_s gc_state_t;
/*
- * The first argument of enum_ptrs procedures is logically const *.
- * Unfortunately, actually declaring it as such would produce many compiler
- * warnings from places that cast this argument to a non-const non-void
- * pointer type. For the moment, we define EV_CONST as empty, with the
- * intention of changing it to const at some future time.
+ * Define the structure used to return an enumerated pointer. Ordinary
+ * object pointers use only the ptr element; strings also use size.
*/
-/*#define EV_CONST const */
-#define EV_CONST /* */
+typedef struct enum_ptr_s {
+ const void *ptr;
+ uint size;
+} enum_ptr_t;
+
+/*
+ * The first argument of enum_ptrs procedures formerly was not const *, and
+ * EV_CONST was defined as empty. Unfortunately, changing EV_CONST to const
+ * produced many compiler warnings from places that cast this argument to a
+ * non-const non-void pointer type.
+ */
+#define EV_CONST const
/* Define the procedures for structure types. */
@@ -47,7 +54,7 @@ typedef struct gc_state_s gc_state_t;
#define struct_proc_enum_ptrs(proc)\
gs_ptr_type_t proc(P6(EV_CONST void /*obj_header_t*/ *ptr, uint size,\
- int index, const void **pep, const gs_memory_struct_type_t *pstype,\
+ int index, enum_ptr_t *pep, const gs_memory_struct_type_t *pstype,\
gc_state_t *gcst))
/* Relocate all the pointers in this structure. */
diff --git a/gs/src/gssubst b/gs/src/gssubst
new file mode 100755
index 000000000..a3c80c9cf
--- /dev/null
+++ b/gs/src/gssubst
@@ -0,0 +1,23 @@
+#!/usr/bin/tclsh
+
+if {$argc < 2} {
+ puts stderr "Usage: $argv0 (-t type | -u word | fromword toword) file ..."
+ puts stderr " -t word = word word_t"
+ puts stderr " -u word = word WORD"
+ exit 1
+}
+set a0 [lindex $argv 0]
+set a1 [lindex $argv 1]
+switch -- $a0 {
+ -t {set from $a1; set to ${from}_t}
+ -u {set from $a1; set to [string toupper ${from}]}
+ default {set from $a0; set to $a1}
+}
+puts "$from => $to"
+flush stdout
+set tmp /tmp/[pid]
+foreach f [lreplace $argv 0 1] {
+ if {![file exists $f~]} {exec cp -p $f $f~}
+ exec perl -pe "s\{\\b${from}\\b\}\{${to}\}g" < $f > $tmp
+ exec mv $tmp $f
+}
diff --git a/gs/src/gstext.c b/gs/src/gstext.c
index a4a419c3b..162f5b650 100644
--- a/gs/src/gstext.c
+++ b/gs/src/gstext.c
@@ -18,7 +18,7 @@
/* Driver text interface support */
-#include "std.h"
+#include "memory_.h"
#include "gstypes.h"
#include "gdebug.h"
#include "gserror.h"
@@ -27,6 +27,7 @@
#include "gsstruct.h"
#include "gstypes.h"
#include "gxdevcli.h"
+#include "gxfont.h" /* for init_fstack */
#include "gxpath.h"
#include "gxtext.h"
#include "gzstate.h"
@@ -35,21 +36,11 @@
public_st_gs_text_params();
public_st_gs_text_enum();
-#define tptr ((gs_text_params_t *)vptr)
-
private
-ENUM_PTRS_BEGIN(text_params_enum_ptrs) return 0;
-
+ENUM_PTRS_WITH(text_params_enum_ptrs, gs_text_params_t *tptr) return 0;
case 0:
if (tptr->operation & TEXT_FROM_STRING) {
- /*
- * We only need the string descriptor temporarily, but we can't
- * put it in a local variable, because that would create a dangling
- * pointer as soon as we return.
- */
- tptr->gc_string.data = tptr->data.bytes;
- tptr->gc_string.size = tptr->size;
- return ENUM_CONST_STRING(&tptr->gc_string);
+ return ENUM_CONST_STRING2(tptr->data.bytes, tptr->size);
}
if (tptr->operation & TEXT_FROM_BYTES)
return ENUM_OBJ(tptr->data.bytes);
@@ -59,14 +50,13 @@ if (tptr->operation & TEXT_FROM_GLYPHS)
return ENUM_OBJ(tptr->data.glyphs);
return ENUM_OBJ(NULL);
case 1:
-return ENUM_OBJ(tptr->operation & TEXT_REPLACE_X_WIDTHS ?
+return ENUM_OBJ(tptr->operation & TEXT_REPLACE_WIDTHS ?
tptr->x_widths : NULL);
case 2:
-return ENUM_OBJ(tptr->operation & TEXT_REPLACE_Y_WIDTHS ?
+return ENUM_OBJ(tptr->operation & TEXT_REPLACE_WIDTHS ?
tptr->y_widths : NULL);
ENUM_PTRS_END
-
-private RELOC_PTRS_BEGIN(text_params_reloc_ptrs)
+private RELOC_PTRS_WITH(text_params_reloc_ptrs, gs_text_params_t *tptr)
{
if (tptr->operation & TEXT_FROM_STRING) {
gs_const_string str;
@@ -81,44 +71,49 @@ private RELOC_PTRS_BEGIN(text_params_reloc_ptrs)
RELOC_OBJ_VAR(tptr->data.chars);
else if (tptr->operation & TEXT_FROM_GLYPHS)
RELOC_OBJ_VAR(tptr->data.glyphs);
- if (tptr->operation & TEXT_REPLACE_X_WIDTHS)
+ if (tptr->operation & TEXT_REPLACE_WIDTHS) {
RELOC_OBJ_VAR(tptr->x_widths);
- if (tptr->operation & TEXT_REPLACE_Y_WIDTHS)
RELOC_OBJ_VAR(tptr->y_widths);
+ }
}
RELOC_PTRS_END
-#undef tptr
-
-#define eptr ((gs_text_enum_t *)vptr)
-
-private ENUM_PTRS_BEGIN(text_enum_enum_ptrs) ENUM_USING(st_gs_text_params, &eptr->text, sizeof(eptr->text), index - 7);
+private ENUM_PTRS_WITH(text_enum_enum_ptrs, gs_text_enum_t *eptr)
+{
+ index -= 7;
+ if (index <= eptr->fstack.depth)
+ ENUM_RETURN(eptr->fstack.items[index].font);
+ index -= eptr->fstack.depth + 1;
+ return ENUM_USING(st_gs_text_params, &eptr->text, sizeof(eptr->text), index);
+}
case 0: return ENUM_OBJ(gx_device_enum_ptr(eptr->dev));
ENUM_PTR3(1, gs_text_enum_t, pis, orig_font, path);
ENUM_PTR3(4, gs_text_enum_t, pdcolor, pcpath, current_font);
ENUM_PTRS_END
-private RELOC_PTRS_BEGIN(text_enum_reloc_ptrs)
+private RELOC_PTRS_WITH(text_enum_reloc_ptrs, gs_text_enum_t *eptr)
{
+ int i;
+
RELOC_USING(st_gs_text_params, &eptr->text, sizeof(eptr->text));
- gx_device_reloc_ptr(eptr->dev, gcst);
+ eptr->dev = gx_device_reloc_ptr(eptr->dev, gcst);
RELOC_PTR3(gs_text_enum_t, pis, orig_font, path);
RELOC_PTR3(gs_text_enum_t, pdcolor, pcpath, current_font);
+ for (i = 0; i <= eptr->fstack.depth; i++)
+ RELOC_PTR(gs_text_enum_t, fstack.items[i].font);
}
RELOC_PTRS_END
-#undef eptr
-
/* Begin processing text. */
int
gx_device_text_begin(gx_device * dev, gs_imager_state * pis,
- const gs_text_params_t * text, const gs_font * font,
+ const gs_text_params_t * text, gs_font * font,
gx_path * path, /* unless DO_NONE & !RETURN_WIDTH */
const gx_device_color * pdcolor, /* DO_DRAW */
const gx_clip_path * pcpath, /* DO_DRAW */
gs_memory_t * mem, gs_text_enum_t ** ppte)
{
- if (TEXT_OPERATION_IS_INVALID(text->operation))
+ if (TEXT_PARAMS_ARE_INVALID(text))
return_error(gs_error_rangecheck);
{
gx_path *tpath =
@@ -128,25 +123,72 @@ gx_device_text_begin(gx_device * dev, gs_imager_state * pis,
(text->operation & TEXT_DO_DRAW ? pdcolor : 0);
const gx_clip_path *tcpath =
(text->operation & TEXT_DO_DRAW ? pcpath : 0);
- int code = dev_proc(dev, text_begin)
+ return dev_proc(dev, text_begin)
(dev, pis, text, font, tpath, tcolor, tcpath, mem, ppte);
- gs_text_enum_t *pte = *ppte;
+ }
+}
- if (code < 0)
- return code;
- pte->text = *text;
- pte->dev = dev;
- pte->pis = pis;
- pte->orig_font = font;
- pte->path = tpath;
- pte->pdcolor = tcolor;
- pte->pcpath = tcpath;
- pte->memory = mem;
- /* text_begin procedure sets procs, rc */
- pte->current_font = font;
- pte->scale.x = pte->scale.y = 0;
- pte->index = 0;
- return code;
+/*
+ * Initialize a newly created text enumerator. Implementations of
+ * text_begin must call this just after allocating the enumerator.
+ */
+private int
+gs_text_enum_init_dynamic(gs_text_enum_t *pte, gs_font *font)
+{
+ pte->current_font = font;
+ pte->index = 0;
+ pte->xy_index = 0;
+ return font->procs.init_fstack(pte, font);
+}
+int
+gs_text_enum_init(gs_text_enum_t *pte, const gs_text_enum_procs_t *procs,
+ gx_device *dev, gs_imager_state *pis,
+ const gs_text_params_t *text, gs_font *font, gx_path *path,
+ const gx_device_color *pdcolor, const gx_clip_path *pcpath,
+ gs_memory_t *mem)
+{
+ int code;
+
+ pte->text = *text;
+ pte->dev = dev;
+ pte->pis = pis;
+ pte->orig_font = font;
+ pte->path = path;
+ pte->pdcolor = pdcolor;
+ pte->pcpath = pcpath;
+ pte->memory = mem;
+ pte->procs = procs;
+ /* text_begin procedure sets rc */
+ /* init_dynamic sets current_font */
+ pte->log2_scale.x = pte->log2_scale.y = 0;
+ /* init_dynamic sets index, xy_index, fstack */
+ code = gs_text_enum_init_dynamic(pte, font);
+ if (code >= 0)
+ rc_increment(dev);
+ return code;
+}
+
+/*
+ * Copy the dynamically changing elements from one enumerator to another.
+ * This is useful primarily for enumerators that sometimes pass the
+ * operation to a subsidiary enumerator.
+ */
+void
+gs_text_enum_copy_dynamic(gs_text_enum_t *pto, const gs_text_enum_t *pfrom,
+ bool for_return)
+{
+ int depth = pfrom->fstack.depth;
+
+ pto->current_font = pfrom->current_font;
+ pto->index = pfrom->index;
+ pto->xy_index = pfrom->xy_index;
+ pto->fstack.depth = depth;
+ if (depth >= 0)
+ memcpy(pto->fstack.items, pfrom->fstack.items,
+ (depth + 1) * sizeof(pto->fstack.items[0]));
+ if (for_return) {
+ pto->cmap_code = pfrom->cmap_code;
+ pto->returned = pfrom->returned;
}
}
@@ -244,8 +286,7 @@ gs_xyshow_begin(gs_state * pgs, const byte * str, uint size,
{
gs_text_params_t text;
- text.operation = TEXT_FROM_STRING |
- TEXT_REPLACE_X_WIDTHS | TEXT_REPLACE_Y_WIDTHS |
+ text.operation = TEXT_FROM_STRING | TEXT_REPLACE_WIDTHS |
TEXT_DO_DRAW | TEXT_RETURN_WIDTH;
text.data.bytes = str, text.size = size;
text.x_widths = x_widths;
@@ -270,7 +311,7 @@ gs_cshow_begin(gs_state * pgs, const byte * str, uint size,
{
gs_text_params_t text;
- text.operation = TEXT_FROM_STRING | TEXT_DO_NONE;
+ text.operation = TEXT_FROM_STRING | TEXT_DO_NONE | TEXT_INTERVENE;
text.data.bytes = str, text.size = size;
return gs_text_begin(pgs, &text, mem, ppte);
}
@@ -319,6 +360,27 @@ gs_glyphpath_begin(gs_state * pgs, gs_glyph glyph, bool stroke_path,
return gs_text_begin(pgs, &text, mem, ppte);
}
+/* Restart processing with different parameters. */
+int
+gs_text_restart(gs_text_enum_t *pte, const gs_text_params_t *text)
+{
+ gs_text_enum_t tenum;
+
+ tenum = *pte;
+ tenum.text = *text;
+ gs_text_enum_init_dynamic(&tenum, pte->orig_font);
+ return gs_text_resync(pte, &tenum);
+}
+
+/*
+ * Resync text processing with new parameters and string position.
+ */
+int
+gs_text_resync(gs_text_enum_t *pte, const gs_text_enum_t *pfrom)
+{
+ return pte->procs->resync(pte, pfrom);
+}
+
/* Process text after 'begin'. */
int
gs_text_process(gs_text_enum_t * pte)
@@ -326,8 +388,81 @@ gs_text_process(gs_text_enum_t * pte)
return pte->procs->process(pte);
}
+/* Access elements of the enumerator. */
+gs_font *
+gs_text_current_font(const gs_text_enum_t *pte)
+{
+ return pte->current_font;
+}
+gs_char
+gs_text_current_char(const gs_text_enum_t *pte)
+{
+ return pte->returned.current_char;
+}
+gs_char
+gs_text_next_char(const gs_text_enum_t *pte)
+{
+ return pte->returned.current_char; /****** WRONG ******/
+}
+gs_glyph
+gs_text_current_glyph(const gs_text_enum_t *pte)
+{
+ return pte->returned.current_glyph;
+}
+int
+gs_text_total_width(const gs_text_enum_t *pte, gs_point *pwidth)
+{
+ *pwidth = pte->returned.total_width;
+ return 0;
+}
+
+/* Assuming REPLACE_WIDTHS is set, return the width of the i'th character. */
+int
+gs_text_replaced_width(const gs_text_params_t *text, uint index,
+ gs_point *pwidth)
+{
+ const float *x_widths = text->x_widths;
+ const float *y_widths = text->y_widths;
+
+ if (index > text->size)
+ return_error(gs_error_rangecheck);
+ if (x_widths == y_widths) {
+ if (x_widths) {
+ index *= 2;
+ pwidth->x = x_widths[index];
+ pwidth->y = x_widths[index + 1];
+ }
+ else
+ pwidth->x = pwidth->y = 0;
+ } else {
+ pwidth->x = (x_widths ? x_widths[index] : 0.0);
+ pwidth->y = (y_widths ? y_widths[index] : 0.0);
+ }
+ return 0;
+}
+
+/* Determine whether only the width is needed. */
+bool
+gs_text_is_width_only(const gs_text_enum_t * pte)
+{
+ return pte->procs->is_width_only(pte);
+}
+
+/* Return the width of the current character. */
+int
+gs_text_current_width(const gs_text_enum_t * pte, gs_point *pwidth)
+{
+ return pte->procs->current_width(pte, pwidth);
+}
+
/* Set text metrics and optionally enable caching. */
int
+gs_text_set_cache(gs_text_enum_t * pte, const double *values,
+ gs_text_cache_control_t control)
+{
+ return pte->procs->set_cache(pte, values, control);
+}
+int
gs_text_setcharwidth(gs_text_enum_t * pte, const double wxy[2])
{
return pte->procs->set_cache(pte, wxy, TEXT_SET_CHAR_WIDTH);
@@ -343,9 +478,76 @@ gs_text_setcachedevice2(gs_text_enum_t * pte, const double wbox2[10])
return pte->procs->set_cache(pte, wbox2, TEXT_SET_CACHE_DEVICE2);
}
+/* Retry processing the last character without caching. */
+int
+gs_text_retry(gs_text_enum_t * pte)
+{
+ return pte->procs->retry(pte);
+}
+
/* Release the text processing structures. */
void
+gx_default_text_release(gs_text_enum_t *pte, client_name_t cname)
+{
+ rc_decrement_only(pte->dev, cname);
+}
+void
+rc_free_text_enum(gs_memory_t * mem, void *obj, client_name_t cname)
+{
+ gs_text_enum_t *pte = obj;
+
+ pte->procs->release(pte, cname);
+ rc_free_struct_only(mem, obj, cname);
+}
+void
gs_text_release(gs_text_enum_t * pte, client_name_t cname)
{
rc_decrement_only(pte, cname);
}
+
+/* ---------------- Default font rendering procedures ---------------- */
+
+/* Default fstack initialization procedure. */
+int
+gs_default_init_fstack(gs_text_enum_t *pte, gs_font *pfont)
+{
+ pte->fstack.depth = -1;
+ return 0;
+}
+
+/* Default next-glyph procedure. */
+int
+gs_default_next_char_glyph(gs_text_enum_t *pte, gs_char *pchr, gs_glyph *pglyph)
+{
+ if (pte->index >= pte->text.size)
+ return 2;
+ if (pte->text.operation & (TEXT_FROM_STRING | TEXT_FROM_BYTES)) {
+ /* ordinary string */
+ *pchr = pte->text.data.bytes[pte->index];
+ *pglyph = gs_no_glyph;
+ } else if (pte->text.operation & TEXT_FROM_SINGLE_GLYPH) {
+ /* glyphshow or glyphpath */
+ *pchr = gs_no_char;
+ *pglyph = pte->text.data.d_glyph;
+ } else if (pte->text.operation & TEXT_FROM_GLYPHS) {
+ *pchr = gs_no_char;
+ *pglyph = pte->text.data.glyphs[pte->index];
+ } else if (pte->text.operation & TEXT_FROM_SINGLE_CHAR) {
+ *pchr = pte->text.data.d_char;
+ *pglyph = gs_no_glyph;
+ } else if (pte->text.operation & TEXT_FROM_CHARS) {
+ *pchr = pte->text.data.chars[pte->index];
+ *pglyph = gs_no_glyph;
+ } else
+ return_error(gs_error_rangecheck); /* shouldn't happen */
+ pte->index++;
+ return 0;
+}
+
+/* Dummy (ineffective) BuildChar/BuildGlyph procedure */
+int
+gs_no_build_char(gs_text_enum_t *pte, gs_state *pgs, gs_font *pfont,
+ gs_char chr, gs_glyph glyph)
+{
+ return 1; /* failure, but not error */
+}
diff --git a/gs/src/gstext.h b/gs/src/gstext.h
index 57e954ffb..e6d010327 100644
--- a/gs/src/gstext.h
+++ b/gs/src/gstext.h
@@ -23,15 +23,14 @@
# define gstext_INCLUDED
#include "gsccode.h"
-#include "gsrefct.h"
+#include "gscpm.h"
/*
- * Note that like get_params and get_hardware_params, but unlike all other
- * driver procedures, text display must return information to the generic
- * code:
- * *show except [x][y]show: the string escapement a.k.a. "width").
- * charpath, .glyphpath: the entire character description.
- * .charboxpath: the character bounding box.
+ * Note that text display must return information to the generic code:
+ * If TEXT_RETURN_WIDTH or TEXT_DO_CHARWIDTH, the string escapement
+ * (a.k.a. "width");
+ * If TEXT_DO_*_CHARPATH, the entire character description;
+ * If TEXT_DO_*_CHARBOXPATH, the character bounding box.
*/
/*
@@ -43,18 +42,18 @@
* - FROM_SINGLE with size != 1.
* - Both ADD_TO and REPLACE.
*/
-#define TEXT_HAS_MORE_THAN_ONE_(op, any_)\
- ( ((op) & any_) & (((op) & any_) - 1) )
+#define TEXT_HAS_MORE_THAN_ONE_(op, any)\
+ ( ((op) & any) & (((op) & any) - 1) )
#define TEXT_OPERATION_IS_INVALID(op)\
- (!((op) & TEXT_FROM_ANY_) ||\
- !((op) & TEXT_DO_ANY_) ||\
- TEXT_HAS_MORE_THAN_ONE_(op, TEXT_FROM_ANY_) ||\
- TEXT_HAS_MORE_THAN_ONE_(op, TEXT_DO_ANY_) ||\
- (((op) & TEXT_ADD_ANY_) && ((op) & TEXT_REPLACE_ANY_))\
+ (!((op) & TEXT_FROM_ANY) ||\
+ !((op) & TEXT_DO_ANY) ||\
+ TEXT_HAS_MORE_THAN_ONE_(op, TEXT_FROM_ANY) ||\
+ TEXT_HAS_MORE_THAN_ONE_(op, TEXT_DO_ANY) ||\
+ (((op) & TEXT_ADD_ANY) && ((op) & TEXT_REPLACE_WIDTHS))\
)
#define TEXT_PARAMS_ARE_INVALID(params)\
- (TEXT_OPERATION_IS_INVALID(op) ||\
- ( ((op) & TEXT_FROM_ANY_SINGLE_) && ((params)->size != 1) )\
+ (TEXT_OPERATION_IS_INVALID((params)->operation) ||\
+ ( ((params)->operation & TEXT_FROM_ANY_SINGLE) && ((params)->size != 1) )\
)
/* Define the representation of the text itself. */
@@ -64,31 +63,29 @@
#define TEXT_FROM_GLYPHS 0x00008
#define TEXT_FROM_SINGLE_CHAR 0x00010
#define TEXT_FROM_SINGLE_GLYPH 0x00020
-#define TEXT_FROM_ANY_SINGLE_ /* internal use only, see above */\
+#define TEXT_FROM_ANY_SINGLE /* only for testing and masking */\
(TEXT_FROM_SINGLE_CHAR | TEXT_FROM_SINGLE_GLYPH)
-#define TEXT_FROM_ANY_ /* internal use only, see above */\
+#define TEXT_FROM_ANY /* only for testing and masking */\
(TEXT_FROM_STRING | TEXT_FROM_BYTES | TEXT_FROM_CHARS | TEXT_FROM_GLYPHS |\
- TEXT_FROM_ANY_SINGLE_)
+ TEXT_FROM_ANY_SINGLE)
/* Define how to compute escapements. */
#define TEXT_ADD_TO_ALL_WIDTHS 0x00040
#define TEXT_ADD_TO_SPACE_WIDTH 0x00080
-#define TEXT_ADD_ANY_ /* internal use only, see above */\
+#define TEXT_ADD_ANY /* only for testing and masking */\
(TEXT_ADD_TO_ALL_WIDTHS | TEXT_ADD_TO_SPACE_WIDTH)
-#define TEXT_REPLACE_X_WIDTHS 0x00100
-#define TEXT_REPLACE_Y_WIDTHS 0x00200
-#define TEXT_REPLACE_ANY_ /* internal use only, see above */\
- (TEXT_REPLACE_X_WIDTHS | TEXT_REPLACE_Y_WIDTHS)
+#define TEXT_REPLACE_WIDTHS 0x00100
/* Define what result should be produced. */
-#define TEXT_DO_NONE 0x00400 /* stringwidth or cshow only */
-#define TEXT_DO_DRAW 0x00800
+#define TEXT_DO_NONE 0x00200 /* stringwidth or cshow only */
+#define TEXT_DO_DRAW 0x00400
+#define TEXT_DO_CHARWIDTH 0x00800 /* rmoveto by width */
#define TEXT_DO_FALSE_CHARPATH 0x01000
#define TEXT_DO_TRUE_CHARPATH 0x02000
#define TEXT_DO_FALSE_CHARBOXPATH 0x04000
#define TEXT_DO_TRUE_CHARBOXPATH 0x08000
-#define TEXT_DO_ANY_CHARPATH\
- (TEXT_DO_FALSE_CHARPATH | TEXT_DO_TRUE_CHARPATH |\
+#define TEXT_DO_ANY_CHARPATH /* only for testing and masking */\
+ (TEXT_DO_CHARWIDTH | TEXT_DO_FALSE_CHARPATH | TEXT_DO_TRUE_CHARPATH |\
TEXT_DO_FALSE_CHARBOXPATH | TEXT_DO_TRUE_CHARBOXPATH)
-#define TEXT_DO_ANY_ /* internal use only, see above */\
+#define TEXT_DO_ANY /* only for testing and masking */\
(TEXT_DO_NONE | TEXT_DO_DRAW | TEXT_DO_ANY_CHARPATH)
/* Define whether the client intervenes between characters. */
#define TEXT_INTERVENE 0x10000
@@ -110,7 +107,8 @@ typedef struct gs_text_params_s {
gs_char d_char; /* FROM_SINGLE_CHAR */
gs_glyph d_glyph; /* FROM_SINGLE_GLYPH */
} data;
- uint size; /* number of data elements */
+ uint size; /* number of data elements, */
+ /* must be 1 if FROM_SINGLE */
/* The following are used only in the indicated cases. */
gs_point delta_all; /* ADD_TO_ALL_WIDTHS */
gs_point delta_space; /* ADD_TO_SPACE_WIDTH */
@@ -120,11 +118,9 @@ typedef struct gs_text_params_s {
} space;
/* If x_widths == y_widths, widths are taken in pairs. */
/* Either one may be NULL, meaning widths = 0. */
- const float *x_widths; /* REPLACE_X_WIDTHS */
- const float *y_widths; /* REPLACE_Y_WIDTHS */
- uint widths_size; /* REPLACE_X_WIDTHS, REPLACE_Y_WIDTHS */
- /* The following are for internal use only, not by clients. */
- gs_const_string gc_string; /* for use only during GC */
+ const float *x_widths; /* REPLACE_WIDTHS */
+ const float *y_widths; /* REPLACE_WIDTHS */
+ uint widths_size; /****** PROBABLY NOT NEEDED ******/
} gs_text_params_t;
#define st_gs_text_params_max_ptrs 3
@@ -133,11 +129,18 @@ typedef struct gs_text_params_s {
gs_public_st_composite(st_gs_text_params, gs_text_params_t,\
"gs_text_params", text_params_enum_ptrs, text_params_reloc_ptrs)
+/* Assuming REPLACE_WIDTHS is set, return the width of the i'th character. */
+int gs_text_replaced_width(P3(const gs_text_params_t *text, uint index,
+ gs_point *pwidth));
+
/*
* Define the abstract type for the structure that tracks the state of text
* processing.
*/
+#ifndef gs_text_enum_DEFINED
+# define gs_text_enum_DEFINED
typedef struct gs_text_enum_s gs_text_enum_t;
+#endif
/* Abstract types */
#ifndef gx_device_DEFINED
@@ -166,18 +169,19 @@ typedef struct gx_clip_path_s gx_clip_path;
#endif
/*
- * Define the driver procedure for text.
+ * Define the driver procedure for text. This procedure must allocate
+ * the enumerator (see gxtext.h) and initialize the procs and rc members.
*/
#define dev_t_proc_text_begin(proc, dev_t)\
int proc(P9(dev_t *dev,\
gs_imager_state *pis,\
const gs_text_params_t *text,\
- const gs_font *font,\
- gx_path *path, /* unless DO_NONE & !RETURN_WIDTH */\
+ gs_font *font,\
+ gx_path *path, /* unless DO_NONE */\
const gx_device_color *pdcolor, /* if DO_DRAW */\
const gx_clip_path *pcpath, /* if DO_DRAW */\
gs_memory_t *memory,\
- gs_text_enum_t **ppenum))
+ gs_text_enum_t **ppte))
#define dev_proc_text_begin(proc)\
dev_t_proc_text_begin(proc, gx_device)
@@ -226,6 +230,16 @@ int
gs_memory_t *, gs_text_enum_t **));
/*
+ * Restart text processing with new parameters.
+ */
+int gs_text_restart(P2(gs_text_enum_t *pte, const gs_text_params_t *text));
+
+/*
+ * Resync text processing with new parameters and string position.
+ */
+int gs_text_resync(P2(gs_text_enum_t *pte, const gs_text_enum_t *pfrom));
+
+/*
* Define the possible return values from gs_text_process. The client
* should call text_process until it returns 0 (successful completion) or a
* negative (error) value.
@@ -233,32 +247,61 @@ int
/*
* The client must render a character: obtain the code from
- * gs_text_current_char, do whatever is necessary, and then
+ * gs_text_current_char/glyph, do whatever is necessary, and then
* call gs_text_process again.
*/
#define TEXT_PROCESS_RENDER 1
/*
* The client has asked to intervene between characters.
- * Obtain the current and next codes from gs_text_current_char
+ * Obtain the current and next codes from gs_text_current_char/glyph
* and gs_text_next_char, do whatever is necessary, and then
* call gs_text_process again.
*/
#define TEXT_PROCESS_INTERVENE 2
/* Process text after 'begin'. */
-int gs_text_process(P1(gs_text_enum_t * penum));
+int gs_text_process(P1(gs_text_enum_t *pte));
+
+/* Access elements of the enumerator. */
+gs_font *gs_text_current_font(P1(const gs_text_enum_t *pte));
+gs_char gs_text_current_char(P1(const gs_text_enum_t *pte));
+gs_char gs_text_next_char(P1(const gs_text_enum_t *pte));
+gs_glyph gs_text_current_glyph(P1(const gs_text_enum_t *pte));
+int gs_text_total_width(P2(const gs_text_enum_t *pte, gs_point *pwidth));
+
+/*
+ * After the implementation returned TEXT_PROCESS_RENDER, determine
+ * whether it needs the entire character description, or only the width
+ * (escapement).
+ */
+bool gs_text_is_width_only(P1(const gs_text_enum_t *pte));
+
+/*
+ * Return the width of the current character (in user space coordinates).
+ */
+int gs_text_current_width(P2(const gs_text_enum_t *pte, gs_point *pwidth));
/*
* Set text metrics and optionally enable caching. Return 1 iff the
* cache device was just installed.
*/
+typedef enum {
+ TEXT_SET_CHAR_WIDTH, /* wx wy */
+ TEXT_SET_CACHE_DEVICE, /* wx wy llx lly urx ury */
+ TEXT_SET_CACHE_DEVICE2 /* w0x w0y llx lly urx ury w1x w1y vx vy */
+} gs_text_cache_control_t;
int
- gs_text_setcharwidth(P2(gs_text_enum_t * penum, const double wxy[2])),
- gs_text_setcachedevice(P2(gs_text_enum_t * penum, const double wbox[6])),
- gs_text_setcachedevice2(P2(gs_text_enum_t * penum, const double wbox2[10]));
+ gs_text_set_cache(P3(gs_text_enum_t *pte, const double *values,
+ gs_text_cache_control_t control)),
+ gs_text_setcharwidth(P2(gs_text_enum_t *pte, const double wxy[2])),
+ gs_text_setcachedevice(P2(gs_text_enum_t *pte, const double wbox[6])),
+ gs_text_setcachedevice2(P2(gs_text_enum_t *pte, const double wbox2[10]));
+
+/* Retry processing of the last character. */
+int gs_text_retry(P1(gs_text_enum_t *pte));
/* Release the text processing structures. */
-void gs_text_release(P2(gs_text_enum_t * penum, client_name_t cname));
+void gs_text_release(P2(gs_text_enum_t *pte, client_name_t cname));
#endif /* gstext_INCLUDED */
diff --git a/gs/src/gstype1.c b/gs/src/gstype1.c
index e0a7281fc..f7b707ad9 100644
--- a/gs/src/gstype1.c
+++ b/gs/src/gstype1.c
@@ -477,6 +477,10 @@ rsbw: /* Give the caller the opportunity to intervene. */
replace_stem_hints(pcis);
csp -= 2;
inext;
+ case 12:
+ case 13:
+ /* Counter control isn't implemented. */
+ cnext;
case 14:
num_results = 1;
blend:{
diff --git a/gs/src/gstype1.h b/gs/src/gstype1.h
index 8b322b3bb..3837b3fbd 100644
--- a/gs/src/gstype1.h
+++ b/gs/src/gstype1.h
@@ -31,9 +31,6 @@ typedef struct gs_type1_state_s gs_type1_state;
# define gx_path_DEFINED
typedef struct gx_path_s gx_path;
#endif
-#ifndef gs_show_enum_s_DEFINED
-struct gs_show_enum_s;
-#endif
#ifndef gs_font_type1_DEFINED
# define gs_font_type1_DEFINED
typedef struct gs_font_type1_s gs_font_type1;
diff --git a/gs/src/gstype2.c b/gs/src/gstype2.c
index ec4b5da43..69d1a76c7 100644
--- a/gs/src/gstype2.c
+++ b/gs/src/gstype2.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996, 1997, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1996, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -411,19 +411,27 @@ gs_type2_interpret(gs_type1_state * pcis, const gs_const_string * str,
* A hintmask at the beginning of the CharString is
* equivalent to vstemhm + hintmask. For simplicity, we use
* this interpretation everywhere.
+ *
+ * Even though the Adobe documentation doesn't say this,
+ * it appears that the same holds true for cntrmask.
*/
+ case c2_cntrmask:
pcis->have_hintmask = true;
check_first_operator(!((csp - cstack) & 1));
type2_vstem(pcis, csp, cstack);
+ /*
+ * We should clear the stack here only if this is the
+ * initial mask operator that includes the implicit
+ * vstemhm, but currently this is too much trouble to
+ * detect.
+ */
clear;
- /* (falls through) */
- case c2_cntrmask:
{
byte mask[max_total_stem_hints / 8];
int i;
- if_debug3('1', "[1]mask[%d:%dv,%dh]", pcis->num_hints,
- pcis->vstem_hints.count, pcis->hstem_hints.count);
+ if_debug3('1', "[1]mask[%d:%dh,%dv]", pcis->num_hints,
+ pcis->hstem_hints.count, pcis->vstem_hints.count);
for (i = 0; i < pcis->num_hints; ++cip, i += 8) {
charstring_next(*cip, state, mask[i >> 3], encrypted);
if_debug1('1', " 0x%02x", mask[i >> 3]);
diff --git a/gs/src/gstype42.c b/gs/src/gstype42.c
index 620ab8072..91214f49e 100644
--- a/gs/src/gstype42.c
+++ b/gs/src/gstype42.c
@@ -33,6 +33,10 @@
/* Structure descriptor */
public_st_gs_font_type42();
+/* Forward references */
+private int append_outline(P4(uint glyph_index, const gs_matrix_fixed * pmat,
+ gx_path * ppath, gs_font_type42 * pfont));
+
/* Set up a pointer to a substring of the font data. */
/* Free variables: pfont, string_proc. */
#define ACCESS(base, length, vptr)\
@@ -52,6 +56,81 @@ u32(const byte *p)
return ((ulong)U16(p) << 16) + U16((p) + 2);
}
+/* Define the bits in the component glyph flags. */
+#define cg_argsAreWords 1
+#define cg_argsAreXYValues 2
+#define cg_haveScale 8
+#define cg_moreComponents 32
+#define cg_haveXYScale 64
+#define cg_have2x2 128
+#define cg_useMyMetrics 512
+
+/*
+ * Parse the definition of one component of a composite glyph. We don't
+ * bother to parse the component index, since the caller can do this so
+ * easily.
+ */
+private void
+parse_component(const byte **pdata, uint *pflags, gs_matrix_fixed *psmat,
+ const gs_font_type42 *pfont, const gs_matrix_fixed *pmat)
+{
+ const byte *glyph = *pdata;
+ uint flags;
+ double factor = 1.0 / pfont->data.unitsPerEm;
+ gs_matrix_fixed mat;
+ gs_matrix scale_mat;
+
+ flags = U16(glyph);
+ glyph += 4;
+ mat = *pmat;
+ if (flags & cg_argsAreXYValues) {
+ int arg1, arg2;
+ gs_fixed_point pt;
+
+ if (flags & cg_argsAreWords)
+ arg1 = S16(glyph), arg2 = S16(glyph + 2), glyph += 4;
+ else
+ arg1 = S8(glyph), arg2 = S8(glyph + 1), glyph += 2;
+ gs_point_transform2fixed(pmat, arg1 * factor,
+ arg2 * factor, &pt);
+ /****** HACK: WE KNOW ABOUT FIXED MATRICES ******/
+ mat.tx = fixed2float(mat.tx_fixed = pt.x);
+ mat.ty = fixed2float(mat.ty_fixed = pt.y);
+ } else {
+ /****** WE DON'T HANDLE POINT MATCHING YET ******/
+ glyph += (flags & cg_argsAreWords ? 4 : 2);
+ }
+#define S2_14(p) (S16(p) / 16384.0)
+ if (flags & cg_haveScale) {
+ scale_mat.xx = scale_mat.yy = S2_14(glyph);
+ scale_mat.xy = scale_mat.yx = 0;
+ glyph += 2;
+ } else if (flags & cg_haveXYScale) {
+ scale_mat.xx = S2_14(glyph);
+ scale_mat.yy = S2_14(glyph + 2);
+ scale_mat.xy = scale_mat.yx = 0;
+ glyph += 4;
+ } else if (flags & cg_have2x2) {
+ scale_mat.xx = S2_14(glyph);
+ scale_mat.xy = S2_14(glyph + 2);
+ scale_mat.yx = S2_14(glyph + 4);
+ scale_mat.yy = S2_14(glyph + 6);
+ glyph += 8;
+ } else
+ goto no_scale;
+#undef S2_14
+ scale_mat.tx = 0;
+ scale_mat.ty = 0;
+ /* The scale doesn't affect mat.t{x,y}, so we don't */
+ /* need to update the fixed components. */
+ gs_matrix_multiply(&scale_mat, (const gs_matrix *)&mat,
+ (gs_matrix *)&mat);
+no_scale:
+ *pdata = glyph;
+ *pflags = flags;
+ *psmat = mat;
+}
+
/* Define the default implementation for getting the outline data for */
/* a glyph, using indexToLocFormat and the loca and glyf tables. */
/* Set pglyph->data = 0 if the glyph is empty. */
@@ -90,8 +169,135 @@ default_get_outline(gs_font_type42 * pfont, uint glyph_index,
return 0;
}
+/* Parse a glyph into pieces, if any. */
+private int
+parse_pieces(gs_font_type42 *pfont, gs_glyph glyph, gs_glyph *pieces,
+ int *pnum_pieces)
+{
+ uint glyph_index = glyph - gs_min_cid_glyph;
+ gs_const_string glyph_string;
+ int code = pfont->data.get_outline(pfont, glyph_index, &glyph_string);
+
+ if (code < 0)
+ return code;
+ if (glyph_string.size != 0 && S16(glyph_string.data) == -1) {
+ /* This is a composite glyph. */
+ int i = 0;
+ uint flags = cg_moreComponents;
+ const byte *glyph = glyph_string.data + 10;
+ gs_matrix_fixed mat;
+
+ memset(&mat, 0, sizeof(mat)); /* arbitrary */
+ for (i = 0; flags & cg_moreComponents; ++i) {
+ if (pieces)
+ pieces[i] = U16(glyph + 2) + gs_min_cid_glyph;
+ parse_component(&glyph, &flags, &mat, pfont, &mat);
+ }
+ *pnum_pieces = i;
+ } else
+ *pnum_pieces = 0;
+ return 0;
+}
+
+/* Define the font procedures for a Type 42 font. */
+int
+gs_type42_glyph_outline(gs_font *font, gs_glyph glyph, const gs_matrix *pmat,
+ gx_path *ppath)
+{
+ gs_font_type42 *const pfont = (gs_font_type42 *)font;
+ uint glyph_index = glyph - gs_min_cid_glyph;
+ gs_fixed_point origin;
+ int code;
+ gs_glyph_info_t info;
+ gs_matrix_fixed fmat;
+ static const gs_matrix imat = { identity_matrix_body };
+
+ if (pmat == 0)
+ pmat = &imat;
+ if ((code = gs_matrix_fixed_from_matrix(&fmat, pmat)) < 0 ||
+ (code = gx_path_current_point(ppath, &origin)) < 0 ||
+ (code = append_outline(glyph_index, &fmat, ppath, pfont)) < 0 ||
+ (code = font->procs.glyph_info(font, glyph, pmat,
+ GLYPH_INFO_WIDTH, &info)) < 0
+ )
+ return code;
+ if (pmat) {
+ if ((code = gs_point_transform(info.width[0].x, info.width[0].y,
+ pmat, &info.width[0])) < 0)
+ return code;
+ }
+ return gx_path_add_point(ppath, origin.x + float2fixed(info.width[0].x),
+ origin.y + float2fixed(info.width[0].y));
+}
+int
+gs_type42_glyph_info(gs_font *font, gs_glyph glyph, const gs_matrix *pmat,
+ int members, gs_glyph_info_t *info)
+{
+ gs_font_type42 *const pfont = (gs_font_type42 *)font;
+ uint glyph_index = glyph - gs_min_cid_glyph;
+ int default_members =
+ members & ~(GLYPH_INFO_WIDTHS | GLYPH_INFO_NUM_PIECES |
+ GLYPH_INFO_PIECES);
+ gs_const_string outline;
+ int code = 0;
+
+ if (default_members) {
+ code = gs_default_glyph_info(font, glyph, pmat, default_members, info);
+
+ if (code < 0)
+ return code;
+ } else if ((code = pfont->data.get_outline(pfont, glyph_index, &outline)) < 0)
+ return code; /* non-existent glyph */
+ else
+ info->members = 0;
+ if (members & GLYPH_INFO_WIDTH) {
+ float sbw[4];
+
+ code = gs_type42_get_metrics(pfont, glyph_index, sbw);
+ if (code < 0)
+ return code;
+ if (pmat)
+ code = gs_point_transform(sbw[2], sbw[3], pmat, &info->width[0]);
+ else
+ info->width[0].x = sbw[2], info->width[0].y = sbw[3];
+ info->members |= GLYPH_INFO_WIDTH;
+ }
+ if (members & (GLYPH_INFO_NUM_PIECES | GLYPH_INFO_PIECES)) {
+ gs_glyph *pieces =
+ (members & GLYPH_INFO_PIECES ? info->pieces : (gs_glyph *)0);
+ int code = parse_pieces(pfont, glyph, pieces, &info->num_pieces);
+
+ if (code < 0)
+ return code;
+ info->members |= members & (GLYPH_INFO_NUM_PIECES | GLYPH_INFO_PIECES);
+ }
+ return code;
+}
+int
+gs_type42_enumerate_glyph(gs_font *font, int *pindex,
+ gs_glyph_space_t glyph_space, gs_glyph *pglyph)
+{
+ gs_font_type42 *const pfont = (gs_font_type42 *)font;
+
+ while (++*pindex <= pfont->data.numGlyphs) {
+ gs_const_string outline;
+ uint glyph_index = *pindex - 1;
+ int code = pfont->data.get_outline(pfont, glyph_index, &outline);
+
+ if (code < 0)
+ return code;
+ if (outline.data == 0)
+ continue; /* empty (undefined) glyph */
+ *pglyph = glyph_index + gs_min_cid_glyph;
+ return 0;
+ }
+ /* We are done. */
+ *pindex = 0;
+ return 0;
+}
+
/* Initialize the cached values in a Type 42 font. */
-/* Note that this initializes get_outline as well. */
+/* Note that this initializes get_outline and the font procedures as well. */
int
gs_type42_font_init(gs_font_type42 * pfont)
{
@@ -103,11 +309,12 @@ gs_type42_font_init(gs_font_type42 * pfont)
uint i;
int code;
byte head_box[8];
+ ulong loca_size = 0;
ACCESS(0, 12, OffsetTable);
{
static const byte version1_0[4] = {0, 1, 0, 0};
- static const byte * const version_true = (const byte *)"true";
+ static const byte version_true[4] = {'t', 'r', 'u', 'e'};
if (memcmp(OffsetTable, version1_0, 4) &&
memcmp(OffsetTable, version_true, 4))
@@ -135,12 +342,16 @@ gs_type42_font_init(gs_font_type42 * pfont)
ACCESS(offset, 36, hhea);
pfont->data.numLongMetrics = U16(hhea + 34);
- } else if (!memcmp(tab, "hmtx", 4))
- pfont->data.hmtx = offset,
- pfont->data.hmtx_length = (uint) u32(tab + 12);
- else if (!memcmp(tab, "loca", 4))
+ } else if (!memcmp(tab, "hmtx", 4)) {
+ pfont->data.hmtx = offset;
+ pfont->data.hmtx_length = (uint)u32(tab + 12);
+ } else if (!memcmp(tab, "loca", 4)) {
pfont->data.loca = offset;
+ loca_size = u32(tab + 12);
+ }
}
+ loca_size >>= pfont->data.indexToLocFormat + 1;
+ pfont->data.numGlyphs = (loca_size == 0 ? 0 : loca_size - 1);
/*
* If the font doesn't have a valid FontBBox, compute one from the
* 'head' information. Since the Adobe PostScript driver sometimes
@@ -160,84 +371,12 @@ gs_type42_font_init(gs_font_type42 * pfont)
pfont->FontBBox.q.y = S16(head_box + 6) / upem;
}
pfont->data.get_outline = default_get_outline;
+ pfont->procs.glyph_outline = gs_type42_glyph_outline;
+ pfont->procs.glyph_info = gs_type42_glyph_info;
+ pfont->procs.enumerate_glyph = gs_type42_enumerate_glyph;
return 0;
}
-/* Define the bits in the component glyph flags. */
-#define cg_argsAreWords 1
-#define cg_argsAreXYValues 2
-#define cg_haveScale 8
-#define cg_moreComponents 32
-#define cg_haveXYScale 64
-#define cg_have2x2 128
-#define cg_useMyMetrics 512
-
-/*
- * Parse the definition of one component of a composite glyph. We don't
- * bother to parse the component index, since the caller can do this so
- * easily.
- */
-private void
-parse_component(const byte **pdata, uint *pflags, gs_matrix_fixed *psmat,
- const gs_font_type42 *pfont, const gs_matrix_fixed *pmat)
-{
- const byte *glyph = *pdata;
- uint flags;
- double factor = 1.0 / pfont->data.unitsPerEm;
- gs_matrix_fixed mat;
- gs_matrix scale_mat;
-
- flags = U16(glyph);
- glyph += 4;
- mat = *pmat;
- if (flags & cg_argsAreXYValues) {
- int arg1, arg2;
- gs_fixed_point pt;
-
- if (flags & cg_argsAreWords)
- arg1 = S16(glyph), arg2 = S16(glyph + 2), glyph += 4;
- else
- arg1 = S8(glyph), arg2 = S8(glyph + 1), glyph += 2;
- gs_point_transform2fixed(pmat, arg1 * factor,
- arg2 * factor, &pt);
- /****** HACK: WE KNOW ABOUT FIXED MATRICES ******/
- mat.tx = fixed2float(mat.tx_fixed = pt.x);
- mat.ty = fixed2float(mat.ty_fixed = pt.y);
- } else {
- /****** WE DON'T HANDLE POINT MATCHING YET ******/
- glyph += (flags & cg_argsAreWords ? 4 : 2);
- }
-#define S2_14(p) (S16(p) / 16384.0)
- if (flags & cg_haveScale) {
- scale_mat.xx = scale_mat.yy = S2_14(glyph);
- scale_mat.xy = scale_mat.yx = 0;
- glyph += 2;
- } else if (flags & cg_haveXYScale) {
- scale_mat.xx = S2_14(glyph);
- scale_mat.yy = S2_14(glyph + 2);
- scale_mat.xy = scale_mat.yx = 0;
- glyph += 4;
- } else if (flags & cg_have2x2) {
- scale_mat.xx = S2_14(glyph);
- scale_mat.xy = S2_14(glyph + 2);
- scale_mat.yx = S2_14(glyph + 4);
- scale_mat.yy = S2_14(glyph + 6);
- glyph += 8;
- } else
- goto no_scale;
-#undef S2_14
- scale_mat.tx = 0;
- scale_mat.ty = 0;
- /* The scale doesn't affect mat.t{x,y}, so we don't */
- /* need to update the fixed components. */
- gs_matrix_multiply(&scale_mat, (const gs_matrix *)&mat,
- (gs_matrix *)&mat);
-no_scale:
- *pdata = glyph;
- *pflags = flags;
- *psmat = mat;
-}
-
/* Get the metrics of a simple glyph. */
private int
simple_glyph_metrics(gs_font_type42 * pfont, uint glyph_index,
@@ -318,10 +457,6 @@ gs_type42_get_metrics(gs_font_type42 * pfont, uint glyph_index,
#define gf_yPos 32 /* yShort */
#define gf_ySame 32 /* !yShort */
-/* Forward references */
-private int append_outline(P4(uint glyph_index, const gs_matrix_fixed * pmat,
- gx_path * ppath, gs_font_type42 * pfont));
-
/* Append a TrueType outline to a path. */
/* Note that this does not append the final moveto for the width. */
int
diff --git a/gs/src/gsutil.c b/gs/src/gsutil.c
index 6be16261e..1ca93d9e5 100644
--- a/gs/src/gsutil.c
+++ b/gs/src/gsutil.c
@@ -32,6 +32,7 @@
/* Generate a block of unique IDs. */
static ulong gs_next_id;
+init_proc(gs_gsutil_init); /* check prototype */
void
gs_gsutil_init(gs_memory_t *mem)
{
diff --git a/gs/src/gxacpath.c b/gs/src/gxacpath.c
index 8eeeb76e6..5830c4eb4 100644
--- a/gs/src/gxacpath.c
+++ b/gs/src/gxacpath.c
@@ -32,9 +32,6 @@
#include "gzcpath.h"
#include "gzacpath.h"
-/* Imported procedures */
-extern bool clip_list_validate(P1(const gx_clip_list *));
-
/* Device procedures */
private dev_proc_open_device(accum_open);
private dev_proc_close_device(accum_close);
@@ -185,6 +182,37 @@ gx_cpath_intersect_path_slow(gx_clip_path * pcpath, gx_path * ppath,
/* ------ Device implementation ------ */
+#ifdef DEBUG
+/* Validate a clipping path after accumulation. */
+private bool
+clip_list_validate(const gx_clip_list * clp)
+{
+ if (clp->count <= 1)
+ return (clp->head == 0 && clp->tail == 0 &&
+ clp->single.next == 0 && clp->single.prev == 0);
+ else {
+ const gx_clip_rect *prev = clp->head;
+ const gx_clip_rect *ptr;
+ bool ok = true;
+
+ while ((ptr = prev->next) != 0) {
+ if (ptr->ymin > ptr->ymax || ptr->xmin > ptr->xmax ||
+ !(ptr->ymin >= prev->ymax ||
+ (ptr->ymin == prev->ymin &&
+ ptr->ymax == prev->ymax &&
+ ptr->xmin >= prev->xmax)) ||
+ ptr->prev != prev
+ ) {
+ clip_rect_print('q', "WRONG:", ptr);
+ ok = false;
+ }
+ prev = ptr;
+ }
+ return ok && prev == clp->tail;
+ }
+}
+#endif /* DEBUG */
+
/* Initialize the accumulation device. */
private int
accum_open(register gx_device * dev)
diff --git a/gs/src/gxalloc.h b/gs/src/gxalloc.h
index 2b2fb2df7..9bcd8adb0 100644
--- a/gs/src/gxalloc.h
+++ b/gs/src/gxalloc.h
@@ -198,42 +198,28 @@ extern_st(st_chunk);
* Macros for scanning a chunk linearly, with the following schema:
* SCAN_CHUNK_OBJECTS(cp) << declares pre, size >>
* << code for all objects -- size not set yet >>
- * DO_LARGE
- * << code for large objects >>
- * DO_SMALL
- * << code for small objects >>
+ * DO_ALL
+ * << code for all objects -- size is set >>
* END_OBJECTS_SCAN
- * If large and small objects are treated alike, one can use DO_ALL instead
- * of DO_LARGE and DO_SMALL.
*/
#define SCAN_CHUNK_OBJECTS(cp)\
{ obj_header_t *pre = (obj_header_t *)((cp)->cbase);\
obj_header_t *end = (obj_header_t *)((cp)->cbot);\
- ulong size; /* long because of large objects */\
+ uint size;\
+\
for ( ; pre < end;\
pre = (obj_header_t *)((char *)pre + obj_size_round(size))\
)\
{
-#define DO_LARGE\
- if ( pre->o_large )\
- { size = pre_obj_large_size(pre);\
- {
-#define DO_SMALL\
- }\
- } else\
- { size = pre_obj_small_size(pre);\
- {
#define DO_ALL\
- { size = pre_obj_contents_size(pre);\
- {
+ size = pre_obj_contents_size(pre);\
+ {
#define END_OBJECTS_SCAN_INCOMPLETE\
- }\
}\
}\
}
#ifdef DEBUG
# define END_OBJECTS_SCAN\
- }\
}\
}\
if ( pre != end )\
@@ -341,8 +327,6 @@ struct gs_ref_memory_s {
uint large_size; /* min size to give large object */
/* its own chunk: must be */
/* 1 mod obj_align_mod */
- gs_ref_memory_t *global; /* global VM for this allocator */
- /* (may point to itself) */
uint space; /* a_local, a_global, a_system */
/* Callers can change the following dynamically */
/* (through a procedural interface). */
@@ -374,9 +358,12 @@ struct gs_ref_memory_s {
} lost;
/*
* The following are for the interpreter's convenience: the
- * library initializes them to 0 and then never touches them.
+ * library initializes them as indicated and then never touches them.
*/
- stream *streams;
+ int save_level; /* # of saves with non-zero id */
+ uint new_mask; /* l_new or 0 (default) */
+ uint test_mask; /* l_new or ~0 (default) */
+ stream *streams; /* streams allocated at current level */
/* Garbage collector information */
gs_gc_root_t *roots; /* roots for GC */
/* Sharing / saved state information */
diff --git a/gs/src/gxccache.c b/gs/src/gxccache.c
index 960f45b8e..4cea852a0 100644
--- a/gs/src/gxccache.c
+++ b/gs/src/gxccache.c
@@ -257,7 +257,7 @@ gx_image_cached_char(register gs_show_enum * penum, register cached_char * cc)
code = gx_effective_clip_path(pgs, &pcpath);
if (code < 0)
return code;
- gx_make_clip_device(&cdev, &cdev, gx_cpath_list(pcpath));
+ gx_make_clip_device(&cdev, gx_cpath_list(pcpath));
cdev.target = dev;
dev = (gx_device *) & cdev;
(*dev_proc(dev, open_device)) (dev);
diff --git a/gs/src/gxchar.c b/gs/src/gxchar.c
new file mode 100644
index 000000000..048d8de52
--- /dev/null
+++ b/gs/src/gxchar.c
@@ -0,0 +1,1305 @@
+/* Copyright (C) 1989, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
+
+ This file is part of Aladdin Ghostscript.
+
+ Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
+ or distributor accepts any responsibility for the consequences of using it,
+ or for whether it serves any particular purpose or works at all, unless he
+ or she says so in writing. Refer to the Aladdin Ghostscript Free Public
+ License (the "License") for full details.
+
+ Every copy of Aladdin Ghostscript must include a copy of the License,
+ normally in a plain ASCII text file named PUBLIC. The License grants you
+ the right to copy, modify and redistribute Aladdin Ghostscript, but only
+ under certain conditions described in the License. Among other things, the
+ License requires that the copyright notice and this notice be preserved on
+ all copies.
+ */
+
+
+/* Default implementation of text writing */
+#include "gx.h"
+#include "memory_.h"
+#include "string_.h"
+#include "gserrors.h"
+#include "gsstruct.h"
+#include "gxfixed.h" /* ditto */
+#include "gxarith.h"
+#include "gxmatrix.h"
+#include "gzstate.h"
+#include "gxcoord.h"
+#include "gxdevice.h"
+#include "gxdevmem.h"
+#include "gxchar.h"
+#include "gxfont.h"
+#include "gxfont0.h"
+#include "gxfcache.h"
+#include "gspath.h"
+#include "gzpath.h"
+
+/* Define whether or not to cache characters rotated by angles other than */
+/* multiples of 90 degrees. */
+private bool CACHE_ROTATED_CHARS = true;
+
+/* Define whether or not to oversample characters at small sizes. */
+private bool OVERSAMPLE = true;
+
+/* Define the maximum size of a full temporary bitmap when rasterizing, */
+/* in bits (not bytes). */
+private uint MAX_TEMP_BITMAP_BITS = 80000;
+
+/* Define whether the show operation uses the character outline data, */
+/* as opposed to just needing the width (or nothing). */
+#define SHOW_USES_OUTLINE(penum)\
+ !SHOW_IS(penum, TEXT_DO_NONE | TEXT_DO_CHARWIDTH)
+
+/* Structure descriptors */
+public_st_gs_show_enum();
+extern_st(st_gs_text_enum);
+extern_st(st_gs_state); /* only for testing */
+private
+ENUM_PTRS_BEGIN(show_enum_enum_ptrs)
+ return ENUM_USING(st_gs_text_enum, vptr, size, index);
+ENUM_PTR(0, gs_show_enum, pgs);
+ENUM_PTR(1, gs_show_enum, show_gstate);
+ENUM_PTR3(2, gs_show_enum, dev_cache, dev_cache2, dev_null);
+ENUM_PTRS_END
+private RELOC_PTRS_WITH(show_enum_reloc_ptrs, gs_show_enum *eptr)
+{
+ RELOC_USING(st_gs_text_enum, vptr, size); /* superclass */
+ RELOC_VAR(eptr->pgs);
+ RELOC_VAR(eptr->show_gstate);
+ RELOC_PTR3(gs_show_enum, dev_cache, dev_cache2, dev_null);
+}
+RELOC_PTRS_END
+
+/* Forward declarations */
+private int continue_kshow(P1(gs_show_enum *));
+private int continue_show(P1(gs_show_enum *));
+private int continue_show_update(P1(gs_show_enum *));
+private void show_set_scale(P1(gs_show_enum *));
+private int show_cache_setup(P1(gs_show_enum *));
+private int show_state_setup(P1(gs_show_enum *));
+private int show_origin_setup(P4(gs_state *, fixed, fixed, gs_char_path_mode));
+
+/* Accessors for current_char and current_glyph. */
+#define CURRENT_CHAR(penum) ((penum)->returned.current_char)
+#define SET_CURRENT_CHAR(penum, chr)\
+ ((penum)->returned.current_char = (chr))
+#define CURRENT_GLYPH(penum) ((penum)->returned.current_glyph)
+#define SET_CURRENT_GLYPH(penum, glyph)\
+ ((penum)->returned.current_glyph = (glyph))
+
+/* Allocate a show enumerator. */
+gs_show_enum *
+gs_show_enum_alloc(gs_memory_t * mem, gs_state * pgs, client_name_t cname)
+{
+ gs_show_enum *penum;
+
+ rc_alloc_struct_1(penum, gs_show_enum, &st_gs_show_enum, mem,
+ return 0, cname);
+ penum->rc.free = rc_free_text_enum;
+ penum->auto_release = true; /* old API */
+ /* Initialize pointers for GC */
+ penum->text.operation = 0; /* no pointers relevant */
+ penum->dev = 0;
+ penum->pgs = pgs;
+ penum->show_gstate = 0;
+ penum->dev_cache = 0;
+ penum->dev_cache2 = 0;
+ penum->dev_null = 0;
+ penum->fstack.depth = -1;
+ return penum;
+}
+
+/* ------ Driver procedure ------ */
+
+private text_enum_proc_resync(gx_show_text_resync);
+private text_enum_proc_process(gx_show_text_process);
+private text_enum_proc_is_width_only(gx_show_text_is_width_only);
+private text_enum_proc_current_width(gx_show_text_current_width);
+private text_enum_proc_set_cache(gx_show_text_set_cache);
+private text_enum_proc_retry(gx_show_text_retry);
+private text_enum_proc_release(gx_show_text_release); /* not default */
+
+private const gs_text_enum_procs_t default_text_procs = {
+ gx_show_text_resync, gx_show_text_process,
+ gx_show_text_is_width_only, gx_show_text_current_width,
+ gx_show_text_set_cache, gx_show_text_retry,
+ gx_show_text_release
+};
+
+int
+gx_default_text_begin(gx_device * dev, gs_imager_state * pis,
+ const gs_text_params_t * text, gs_font * font,
+ gx_path * path, const gx_device_color * pdcolor,
+ const gx_clip_path * pcpath,
+ gs_memory_t * mem, gs_text_enum_t ** ppte)
+{
+ uint operation = text->operation;
+ bool propagate_charpath = (operation & TEXT_DO_DRAW) != 0;
+ int code;
+ gs_state *pgs = (gs_state *)pis;
+ gs_show_enum *penum;
+
+ /*
+ * For the moment, require pis to be a gs_state *, since all the
+ * procedures for character rendering expect it.
+ */
+ if (gs_object_type(mem, pis) != &st_gs_state)
+ return_error(gs_error_Fatal);
+ penum = gs_show_enum_alloc(mem, pgs, "gx_default_text_begin");
+ if (!penum)
+ return_error(gs_error_VMerror);
+ code = gs_text_enum_init((gs_text_enum_t *)penum, &default_text_procs,
+ dev, pis, text, font, path, pdcolor, pcpath, mem);
+ if (code < 0) {
+ gs_free_object(mem, penum, "gx_default_text_begin");
+ return code;
+ }
+ penum->auto_release = false; /* new API */
+ penum->level = pgs->level;
+ if (operation & TEXT_DO_ANY_CHARPATH)
+ penum->charpath_flag =
+ (operation & TEXT_DO_FALSE_CHARPATH ? cpm_false_charpath :
+ operation & TEXT_DO_TRUE_CHARPATH ? cpm_true_charpath :
+ operation & TEXT_DO_FALSE_CHARBOXPATH ? cpm_false_charboxpath :
+ operation & TEXT_DO_TRUE_CHARBOXPATH ? cpm_true_charboxpath :
+ operation & TEXT_DO_CHARWIDTH ? cpm_charwidth :
+ cpm_show /* can't happen */ );
+ else
+ penum->charpath_flag =
+ (propagate_charpath ? pgs->in_charpath : cpm_show);
+ penum->cc = 0;
+ penum->continue_proc = continue_show;
+ /* Note: show_state_setup may reset can_cache. */
+ switch (penum->charpath_flag) {
+ case cpm_false_charpath: case cpm_true_charpath:
+ penum->can_cache = -1; break;
+ case cpm_false_charboxpath: case cpm_true_charboxpath:
+ penum->can_cache = 0; break;
+ case cpm_charwidth:
+ default: /* cpm_show */
+ penum->can_cache = 1; break;
+ }
+ code = show_state_setup(penum);
+ if (code < 0)
+ return code;
+ penum->show_gstate =
+ (propagate_charpath && (pgs->in_charpath != 0) ?
+ pgs->show_gstate : pgs);
+ if (!(~operation & (TEXT_DO_NONE | TEXT_RETURN_WIDTH))) {
+ /* This is stringwidth. */
+ gx_device_null *dev_null =
+ gs_alloc_struct(mem, gx_device_null, &st_device_null,
+ "stringwidth(dev_null)");
+
+ if (dev_null == 0)
+ return_error(gs_error_VMerror);
+ /* Do an extra gsave and suppress output */
+ if ((code = gs_gsave(pgs)) < 0)
+ return code;
+ penum->level = pgs->level; /* for level check in show_update */
+ /* Set up a null device that forwards xfont requests properly. */
+ gs_make_null_device(dev_null, gs_currentdevice_inline(pgs), mem);
+ pgs->ctm_default_set = false;
+ penum->dev_null = dev_null;
+ /* Retain this device, since it is referenced from the enumerator. */
+ gx_device_retain((gx_device *)dev_null, true);
+ gs_setdevice_no_init(pgs, (gx_device *) dev_null);
+ /* Establish an arbitrary translation and current point. */
+ gs_newpath(pgs);
+ gx_translate_to_fixed(pgs, fixed_0, fixed_0);
+ code = gx_path_add_point(pgs->path, fixed_0, fixed_0);
+ if (code < 0)
+ return code;
+ }
+ *ppte = (gs_text_enum_t *)penum;
+ return 0;
+}
+
+/* ------ Width/cache setting ------ */
+
+private int
+ set_char_width(P4(gs_show_enum *penum, gs_state *pgs,
+ floatp wx, floatp wy)),
+ set_cache_device(P6(gs_show_enum *penum, gs_state *pgs,
+ floatp llx, floatp lly, floatp urx, floatp ury));
+
+/* This is the default implementation of text enumerator set_cache. */
+private int
+gx_show_text_set_cache(gs_text_enum_t *pte, const double *pw,
+ gs_text_cache_control_t control)
+{
+ gs_show_enum *const penum = (gs_show_enum *)pte;
+ gs_state *pgs = penum->pgs;
+
+ switch (control) {
+ case TEXT_SET_CHAR_WIDTH:
+ return set_char_width(penum, pgs, pw[0], pw[1]);
+ case TEXT_SET_CACHE_DEVICE: {
+ int code = set_char_width(penum, pgs, pw[0], pw[1]); /* default is don't cache */
+
+ if (code < 0)
+ return code;
+ return set_cache_device(penum, pgs, pw[2], pw[3], pw[4], pw[5]);
+ }
+ case TEXT_SET_CACHE_DEVICE2: {
+ int code;
+
+ if (gs_rootfont(pgs)->WMode) {
+ float vx = pw[8], vy = pw[9];
+ gs_fixed_point pvxy, dvxy;
+ cached_char *cc;
+
+ if ((code = gs_point_transform2fixed(&pgs->ctm, -vx, -vy, &pvxy)) < 0 ||
+ (code = gs_distance_transform2fixed(&pgs->ctm, vx, vy, &dvxy)) < 0
+ )
+ return 0; /* don't cache */
+ if ((code = set_char_width(penum, pgs, pw[6], pw[7])) < 0)
+ return code;
+ /* Adjust the origin by (vx, vy). */
+ gx_translate_to_fixed(pgs, pvxy.x, pvxy.y);
+ code = set_cache_device(penum, pgs, pw[2], pw[3], pw[4], pw[5]);
+ if (code != 1)
+ return code;
+ /* Adjust the character origin too. */
+ cc = penum->cc;
+ cc->offset.x += dvxy.x;
+ cc->offset.y += dvxy.y;
+ } else {
+ code = set_char_width(penum, pgs, pw[0], pw[1]);
+ if (code < 0)
+ return code;
+ code = set_cache_device(penum, pgs, pw[2], pw[3], pw[4], pw[5]);
+ }
+ return code;
+ }
+ default:
+ return_error(gs_error_rangecheck);
+ }
+}
+
+/* Set the character width. */
+/* Note that this returns 1 if the current show operation is */
+/* non-displaying (stringwidth or cshow). */
+private int
+set_char_width(gs_show_enum *penum, gs_state *pgs, floatp wx, floatp wy)
+{
+ int code;
+
+ if (penum->width_status != sws_none)
+ return_error(gs_error_undefined);
+ if ((code = gs_distance_transform2fixed(&pgs->ctm, wx, wy, &penum->wxy)) < 0)
+ return code;
+ /* Check whether we're setting the scalable width */
+ /* for a cached xfont character. */
+ if (penum->cc != 0) {
+ penum->cc->wxy = penum->wxy;
+ penum->width_status = sws_cache_width_only;
+ } else {
+ penum->width_status = sws_no_cache;
+ }
+ return !SHOW_IS_DRAWING(penum);
+}
+
+/* Set up the cache device if relevant. */
+/* Return 1 if we just set up a cache device. */
+/* Used by setcachedevice and setcachedevice2. */
+private int
+set_cache_device(gs_show_enum * penum, gs_state * pgs, floatp llx, floatp lly,
+ floatp urx, floatp ury)
+{
+ gs_glyph glyph;
+
+ /* See if we want to cache this character. */
+ if (pgs->in_cachedevice) /* no recursion! */
+ return 0;
+ pgs->in_cachedevice = CACHE_DEVICE_NOT_CACHING; /* disable color/gray/image operators */
+ /* We can only use the cache if we know the glyph. */
+ glyph = CURRENT_GLYPH(penum);
+ if (glyph == gs_no_glyph)
+ return 0;
+ /* We can only use the cache if ctm is unchanged */
+ /* (aside from a possible translation). */
+ if (penum->can_cache <= 0 || !pgs->char_tm_valid) {
+ if_debug2('k', "[k]no cache: can_cache=%d, char_tm_valid=%d\n",
+ penum->can_cache, (int)pgs->char_tm_valid);
+ return 0;
+ } {
+ const gs_font *pfont = pgs->font;
+ gs_font_dir *dir = pfont->dir;
+ gx_device *dev = gs_currentdevice_inline(pgs);
+ int alpha_bits =
+ (*dev_proc(dev, get_alpha_bits)) (dev, go_text);
+ gs_log2_scale_point log2_scale;
+ static const fixed max_cdim[3] =
+ {
+#define max_cd(n)\
+ (fixed_1 << (arch_sizeof_short * 8 - n)) - (fixed_1 >> n) * 3
+ max_cd(0), max_cd(1), max_cd(2)
+#undef max_cd
+ };
+ ushort iwidth, iheight;
+ cached_char *cc;
+ gs_fixed_rect clip_box;
+ int code;
+
+ /* Compute the bounding box of the transformed character. */
+ /* Since we accept arbitrary transformations, the extrema */
+ /* may occur in any order; however, we can save some work */
+ /* by observing that opposite corners before transforming */
+ /* are still opposite afterwards. */
+ gs_fixed_point cll, clr, cul, cur, cdim;
+
+ if ((code = gs_distance_transform2fixed(&pgs->ctm, llx, lly, &cll)) < 0 ||
+ (code = gs_distance_transform2fixed(&pgs->ctm, llx, ury, &clr)) < 0 ||
+ (code = gs_distance_transform2fixed(&pgs->ctm, urx, lly, &cul)) < 0 ||
+ (code = gs_distance_transform2fixed(&pgs->ctm, urx, ury, &cur)) < 0
+ )
+ return 0; /* don't cache */
+ {
+ fixed ctemp;
+
+#define swap(a, b) ctemp = a, a = b, b = ctemp
+#define make_min(a, b) if ( (a) > (b) ) swap(a, b)
+
+ make_min(cll.x, cur.x);
+ make_min(cll.y, cur.y);
+ make_min(clr.x, cul.x);
+ make_min(clr.y, cul.y);
+#undef make_min
+#undef swap
+ }
+ /* Now take advantage of symmetry. */
+ if (clr.x < cll.x)
+ cll.x = clr.x, cur.x = cul.x;
+ if (clr.y < cll.y)
+ cll.y = clr.y, cur.y = cul.y;
+ /* Now cll and cur are the extrema of the box. */
+ cdim.x = cur.x - cll.x;
+ cdim.y = cur.y - cll.y;
+ show_set_scale(penum);
+ log2_scale.x = penum->log2_suggested_scale.x;
+ log2_scale.y = penum->log2_suggested_scale.y;
+#ifdef DEBUG
+ if (gs_debug_c('k')) {
+ dlprintf6("[k]cbox=[%g %g %g %g] scale=%dx%d\n",
+ fixed2float(cll.x), fixed2float(cll.y),
+ fixed2float(cur.x), fixed2float(cur.y),
+ 1 << log2_scale.x, 1 << log2_scale.y);
+ dlprintf6("[p] ctm=[%g %g %g %g %g %g]\n",
+ pgs->ctm.xx, pgs->ctm.xy, pgs->ctm.yx, pgs->ctm.yy,
+ pgs->ctm.tx, pgs->ctm.ty);
+ }
+#endif
+ /*
+ * If the device wants anti-aliased text,
+ * increase the sampling scale to ensure that
+ * if we want N bits of alpha, we generate
+ * at least 2^N sampled bits per pixel.
+ */
+ if (alpha_bits > 1) {
+ int more_bits =
+ alpha_bits - (log2_scale.x + log2_scale.y);
+
+ if (more_bits > 0) {
+ if (log2_scale.x <= log2_scale.y) {
+ log2_scale.x += (more_bits + 1) >> 1;
+ log2_scale.y += more_bits >> 1;
+ } else {
+ log2_scale.x += more_bits >> 1;
+ log2_scale.y += (more_bits + 1) >> 1;
+ }
+ }
+ } else if (!OVERSAMPLE || pfont->PaintType != 0) {
+ /* Don't oversample artificially stroked fonts. */
+ log2_scale.x = log2_scale.y = 0;
+ }
+ if (cdim.x > max_cdim[log2_scale.x] ||
+ cdim.y > max_cdim[log2_scale.y]
+ )
+ return 0; /* much too big */
+ iwidth = ((ushort) fixed2int_var(cdim.x) + 2) << log2_scale.x;
+ iheight = ((ushort) fixed2int_var(cdim.y) + 2) << log2_scale.y;
+ if_debug3('k', "[k]iwidth=%u iheight=%u dev_cache %s\n",
+ (uint) iwidth, (uint) iheight,
+ (penum->dev_cache == 0 ? "not set" : "set"));
+ if (penum->dev_cache == 0) {
+ code = show_cache_setup(penum);
+ if (code < 0)
+ return code;
+ }
+ /*
+ * If we're oversampling (i.e., the temporary bitmap is
+ * larger than the final monobit or alpha array) and the
+ * temporary bitmap is large, use incremental conversion
+ * from oversampled bitmap strips to alpha values instead of
+ * full oversampling with compression at the end.
+ */
+ cc = gx_alloc_char_bits(dir, penum->dev_cache,
+ (iwidth > MAX_TEMP_BITMAP_BITS / iheight &&
+ log2_scale.x + log2_scale.y > alpha_bits ?
+ penum->dev_cache2 : NULL),
+ iwidth, iheight, &log2_scale, alpha_bits);
+ if (cc == 0)
+ return 0; /* too big for cache */
+ /* The mins handle transposed coordinate systems.... */
+ /* Truncate the offsets to avoid artifacts later. */
+ cc->offset.x = fixed_ceiling(-cll.x);
+ cc->offset.y = fixed_ceiling(-cll.y);
+ if_debug4('k', "[k]width=%u, height=%u, offset=[%g %g]\n",
+ (uint) iwidth, (uint) iheight,
+ fixed2float(cc->offset.x),
+ fixed2float(cc->offset.y));
+ if ((code = gs_gsave(pgs)) < 0) {
+ gx_free_cached_char(dir, cc);
+ return code;
+ }
+ /* Nothing can go wrong now.... */
+ penum->cc = cc;
+ cc->code = glyph;
+ cc->wmode = gs_rootfont(pgs)->WMode;
+ cc->wxy = penum->wxy;
+ /* Install the device */
+ gx_set_device_only(pgs, (gx_device *) penum->dev_cache);
+ pgs->ctm_default_set = false;
+ /* Adjust the transformation in the graphics context */
+ /* so that the character lines up with the cache. */
+ gx_translate_to_fixed(pgs,
+ cc->offset.x << log2_scale.x,
+ cc->offset.y << log2_scale.y);
+ if ((log2_scale.x | log2_scale.y) != 0)
+ gx_scale_char_matrix(pgs, 1 << log2_scale.x,
+ 1 << log2_scale.y);
+ /* Set the initial matrix for the cache device. */
+ penum->dev_cache->initial_matrix = ctm_only(pgs);
+ /* Set the oversampling factor. */
+ penum->log2_scale.x = log2_scale.x;
+ penum->log2_scale.y = log2_scale.y;
+ /* Reset the clipping path to match the metrics. */
+ clip_box.p.x = clip_box.p.y = 0;
+ clip_box.q.x = int2fixed(iwidth);
+ clip_box.q.y = int2fixed(iheight);
+ if ((code = gx_clip_to_rectangle(pgs, &clip_box)) < 0)
+ return code;
+ gx_set_device_color_1(pgs); /* write 1's */
+ pgs->in_cachedevice = CACHE_DEVICE_CACHING;
+ }
+ penum->width_status = sws_cache;
+ return 1;
+}
+
+/* Return the cache device status. */
+gs_in_cache_device_t
+gs_incachedevice(const gs_state *pgs)
+{
+ return pgs->in_cachedevice;
+}
+
+/* ------ Enumerator ------ */
+
+/*
+ * Set the encode_char procedure in an enumerator.
+ */
+private void
+show_set_encode_char(gs_show_enum * penum)
+{
+ penum->encode_char =
+ (SHOW_IS(penum, TEXT_FROM_GLYPHS | TEXT_FROM_SINGLE_GLYPH) ?
+ gs_no_encode_char :
+ gs_show_current_font(penum)->procs.encode_char);
+}
+
+/*
+ * Resync a text operation with a different set of parameters.
+ * Currently this is implemented only for changing the data source.
+ */
+private int
+gx_show_text_resync(gs_text_enum_t *pte, const gs_text_enum_t *pfrom)
+{
+ gs_show_enum *const penum = (gs_show_enum *)pte;
+ int old_index = pte->index;
+
+ if ((pte->text.operation ^ pfrom->text.operation) & ~TEXT_FROM_ANY)
+ return_error(gs_error_rangecheck);
+ pte->text = pfrom->text;
+ if (pte->index == old_index) {
+ show_set_encode_char(penum);
+ return 0;
+ } else
+ return show_state_setup(penum);
+}
+
+/* Do the next step of a show (or stringwidth) operation */
+private int
+gx_show_text_process(gs_text_enum_t *pte)
+{
+ gs_show_enum *const penum = (gs_show_enum *)pte;
+
+ return (*penum->continue_proc)(penum);
+}
+
+/* Continuation procedures */
+private int show_update(P1(gs_show_enum * penum));
+private int show_move(P1(gs_show_enum * penum));
+private int show_proceed(P1(gs_show_enum * penum));
+private int show_finish(P1(gs_show_enum * penum));
+private int
+continue_show_update(gs_show_enum * penum)
+{
+ int code = show_update(penum);
+
+ if (code < 0)
+ return code;
+ code = show_move(penum);
+ if (code != 0)
+ return code;
+ return show_proceed(penum);
+}
+private int
+continue_show(gs_show_enum * penum)
+{
+ return show_proceed(penum);
+}
+/* For kshow, the CTM or font may have changed, so we have to reestablish */
+/* the cached values in the enumerator. */
+private int
+continue_kshow(gs_show_enum * penum)
+{
+ int code = show_state_setup(penum);
+
+ if (code < 0)
+ return code;
+ return show_proceed(penum);
+}
+
+/* Update position */
+private int
+show_update(gs_show_enum * penum)
+{
+ gs_state *pgs = penum->pgs;
+ cached_char *cc = penum->cc;
+ int code;
+
+ /* Update position for last character */
+ switch (penum->width_status) {
+ case sws_none:
+ /* Adobe interpreters assume a character width of 0, */
+ /* even though the documentation says this is an error.... */
+ penum->wxy.x = penum->wxy.y = 0;
+ break;
+ case sws_cache:
+ /* Finish installing the cache entry. */
+ /* If the BuildChar/BuildGlyph procedure did a save and a */
+ /* restore, it already undid the gsave in setcachedevice. */
+ /* We have to check for this by comparing levels. */
+ switch (pgs->level - penum->level) {
+ default:
+ return_error(gs_error_invalidfont); /* WRONG */
+ case 2:
+ code = gs_grestore(pgs);
+ if (code < 0)
+ return code;
+ case 1:
+ ;
+ }
+ gx_add_cached_char(pgs->font->dir, penum->dev_cache,
+ cc, gx_lookup_fm_pair(pgs->font, pgs),
+ &penum->log2_scale);
+ if (!SHOW_USES_OUTLINE(penum) ||
+ penum->charpath_flag != cpm_show
+ )
+ break;
+ /* falls through */
+ case sws_cache_width_only:
+ /* Copy the bits to the real output device. */
+ code = gs_grestore(pgs);
+ if (code < 0)
+ return code;
+ code = gs_state_color_load(pgs);
+ if (code < 0)
+ return code;
+ return gx_image_cached_char(penum, cc);
+ case sws_no_cache:
+ ;
+ }
+ if (penum->charpath_flag != cpm_show) {
+ /* Move back to the character origin, so that */
+ /* show_move will get us to the right place. */
+ code = gx_path_add_point(pgs->show_gstate->path,
+ penum->origin.x, penum->origin.y);
+ if (code < 0)
+ return code;
+ }
+ return gs_grestore(pgs);
+}
+
+/* Move to next character */
+private int
+show_fast_move(gs_state * pgs, gs_fixed_point * pwxy)
+{
+ int code = gx_path_add_rel_point_inline(pgs->path, pwxy->x, pwxy->y);
+
+ /* If the current position is out of range, don't try to move. */
+ if (code == gs_error_limitcheck && pgs->clamp_coordinates)
+ code = 0;
+ return code;
+}
+private int
+show_move(gs_show_enum * penum)
+{
+ gs_state *pgs = penum->pgs;
+
+ if (SHOW_IS(penum, TEXT_REPLACE_WIDTHS)) {
+ gs_point dpt;
+
+ gs_text_replaced_width(&penum->text, penum->xy_index - 1, &dpt);
+ gs_distance_transform2fixed(&pgs->ctm, dpt.x, dpt.y, &penum->wxy);
+ } else {
+ double dx = 0, dy = 0;
+
+ if (SHOW_IS_ADD_TO_SPACE(penum)) {
+ gs_char chr = CURRENT_CHAR(penum) & 0xff;
+ int fdepth = penum->fstack.depth;
+
+ if (fdepth > 0) {
+ /* Add in the shifted font number. */
+ uint fidx = penum->fstack.items[fdepth].index;
+
+ switch (((gs_font_type0 *) (penum->fstack.items[fdepth - 1].font))->data.FMapType) {
+ case fmap_1_7:
+ case fmap_9_7:
+ chr += fidx << 7;
+ break;
+ case fmap_CMap:
+ chr = CURRENT_CHAR(penum); /* the full character */
+ if (!penum->cmap_code)
+ break;
+ /* falls through */
+ default:
+ chr += fidx << 8;
+ }
+ }
+ if (chr == penum->text.space.s_char) {
+ dx = penum->text.delta_space.x;
+ dy = penum->text.delta_space.y;
+ }
+ }
+ if (SHOW_IS_ADD_TO_ALL(penum)) {
+ dx += penum->text.delta_all.x;
+ dy += penum->text.delta_all.y;
+ }
+ if (!is_fzero2(dx, dy)) {
+ gs_fixed_point dxy;
+
+ gs_distance_transform2fixed(&pgs->ctm, dx, dy, &dxy);
+ penum->wxy.x += dxy.x;
+ penum->wxy.y += dxy.y;
+ }
+ }
+ if (SHOW_IS_ALL_OF(penum, TEXT_DO_NONE | TEXT_INTERVENE)) {
+ /* HACK for cshow */
+ penum->continue_proc = continue_kshow;
+ return TEXT_PROCESS_INTERVENE;
+ }
+ /* wxy is in device coordinates */
+ {
+ int code = show_fast_move(pgs, &penum->wxy);
+
+ if (code < 0)
+ return code;
+ }
+ /* Check for kerning, but not on the last character. */
+ if (SHOW_IS_DO_KERN(penum) && penum->index < penum->text.size) {
+ penum->continue_proc = continue_kshow;
+ return TEXT_PROCESS_INTERVENE;
+ }
+ return 0;
+}
+/* Process next character */
+private int
+show_proceed(gs_show_enum * penum)
+{
+ gs_state *pgs = penum->pgs;
+ gs_font *pfont;
+ cached_fm_pair *pair = 0;
+ gs_font *rfont =
+ (penum->fstack.depth < 0 ? pgs->font : penum->fstack.items[0].font);
+ int wmode = rfont->WMode;
+ font_proc_next_char_glyph((*next_char_glyph)) =
+ rfont->procs.next_char_glyph;
+#define get_next_char_glyph(pte, pchr, pglyph)\
+ (++(penum->xy_index), next_char_glyph(pte, pchr, pglyph))
+ gs_char chr;
+ gs_glyph glyph;
+ int code;
+ cached_char *cc;
+ gx_device *dev = gs_currentdevice_inline(pgs);
+ int alpha_bits = (*dev_proc(dev, get_alpha_bits)) (dev, go_text);
+
+ if (penum->charpath_flag == cpm_show && SHOW_USES_OUTLINE(penum)) {
+ code = gs_state_color_load(pgs);
+ if (code < 0)
+ return code;
+ }
+ more: /* Proceed to next character */
+ pfont = (penum->fstack.depth < 0 ? pgs->font :
+ penum->fstack.items[penum->fstack.depth].font);
+ penum->current_font = pfont;
+ /* can_cache >= 0 allows us to use cached characters, */
+ /* even if we can't make new cache entries. */
+ if (penum->can_cache >= 0) {
+ /* Loop with cache */
+ for (;;) {
+ switch ((code = get_next_char_glyph((gs_text_enum_t *)penum,
+ &chr, &glyph))
+ ) {
+ default: /* error */
+ return code;
+ case 2: /* done */
+ return show_finish(penum);
+ case 1: /* font change */
+ pfont = penum->fstack.items[penum->fstack.depth].font;
+ penum->current_font = pfont;
+ pgs->char_tm_valid = false;
+ show_state_setup(penum);
+ pair = 0;
+ /* falls through */
+ case 0: /* plain char */
+ /*
+ * We don't need to set penum->current_char in the
+ * normal cases, but it's needed for widthshow,
+ * kshow, and one strange client, so we may as well
+ * do it here.
+ */
+ SET_CURRENT_CHAR(penum, chr);
+ if (glyph == gs_no_glyph) {
+ glyph = (*penum->encode_char)(pfont, chr,
+ GLYPH_SPACE_NAME);
+ if (glyph == gs_no_glyph) {
+ cc = 0;
+ goto no_cache;
+ }
+ }
+ if (pair == 0)
+ pair = gx_lookup_fm_pair(pfont, pgs);
+ cc = gx_lookup_cached_char(pfont, pair, glyph, wmode,
+ alpha_bits);
+ if (cc == 0) {
+ /* Character is not in cache. */
+ /* If possible, try for an xfont before */
+ /* rendering from the outline. */
+ if (pfont->ExactSize == fbit_use_outlines ||
+ pfont->PaintType == 2
+ )
+ goto no_cache;
+ if (pfont->BitmapWidths) {
+ cc = gx_lookup_xfont_char(pgs, pair, chr,
+ glyph, &pfont->procs.callbacks, wmode);
+ if (cc == 0)
+ goto no_cache;
+ } else {
+ if (!SHOW_USES_OUTLINE(penum) ||
+ (penum->charpath_flag != cpm_show &&
+ penum->charpath_flag != cpm_charwidth)
+ )
+ goto no_cache;
+ /* We might have an xfont, but we still */
+ /* want the scalable widths. */
+ cc = gx_lookup_xfont_char(pgs, pair, chr,
+ glyph, &pfont->procs.callbacks, wmode);
+ /* Render up to the point of */
+ /* setcharwidth or setcachedevice, */
+ /* just as for stringwidth. */
+ /* This is the only case in which we can */
+ /* to go no_cache with cc != 0. */
+ goto no_cache;
+ }
+ }
+ /* Character is in cache. */
+ /* We might be doing .charboxpath or stringwidth; */
+ /* check for these now. */
+ if (penum->charpath_flag == cpm_charwidth) {
+ /* This is charwidth. Just move by the width. */
+ DO_NOTHING;
+ } else if (penum->charpath_flag != cpm_show) {
+ /* This is .charboxpath. Get the bounding box */
+ /* and append it to a path. */
+ gx_path box_path;
+ gs_fixed_point pt;
+ fixed llx, lly, urx, ury;
+
+ code = gx_path_current_point(pgs->path, &pt);
+ if (code < 0)
+ return code;
+ llx = fixed_rounded(pt.x - cc->offset.x) +
+ int2fixed(penum->ftx);
+ lly = fixed_rounded(pt.y - cc->offset.y) +
+ int2fixed(penum->fty);
+ urx = llx + int2fixed(cc->width),
+ ury = lly + int2fixed(cc->height);
+ gx_path_init_local(&box_path, pgs->memory);
+ code =
+ gx_path_add_rectangle(&box_path, llx, lly,
+ urx, ury);
+ if (code >= 0)
+ code =
+ gx_path_add_char_path(pgs->show_gstate->path,
+ &box_path,
+ penum->charpath_flag);
+ if (code >= 0)
+ code = gx_path_add_point(pgs->path, pt.x, pt.y);
+ gx_path_free(&box_path, "show_proceed(box path)");
+ if (code < 0)
+ return code;
+ } else if (SHOW_IS_DRAWING(penum)) {
+ code = gx_image_cached_char(penum, cc);
+ if (code < 0)
+ return code;
+ else if (code > 0) {
+ cc = 0;
+ goto no_cache;
+ }
+ }
+ if (SHOW_IS_SLOW(penum)) {
+ /* Split up the assignment so that the */
+ /* Watcom compiler won't reserve esi/edi. */
+ penum->wxy.x = cc->wxy.x;
+ penum->wxy.y = cc->wxy.y;
+ code = show_move(penum);
+ } else
+ code = show_fast_move(pgs, &cc->wxy);
+ if (code) {
+ /* Might be kshow, so store the state. */
+ SET_CURRENT_GLYPH(penum, glyph);
+ return code;
+ }
+ }
+ }
+ } else {
+ /* Can't use cache */
+ switch ((code = get_next_char_glyph((gs_text_enum_t *)penum,
+ &chr, &glyph))
+ ) {
+ default:
+ return code;
+ case 2:
+ return show_finish(penum);
+ case 1:
+ pfont = penum->fstack.items[penum->fstack.depth].font;
+ penum->current_font = pfont;
+ show_state_setup(penum);
+ case 0:
+ ;
+ }
+ SET_CURRENT_CHAR(penum, chr);
+ if (glyph == gs_no_glyph) {
+ glyph = (*penum->encode_char)(pfont, chr, GLYPH_SPACE_NAME);
+ }
+ cc = 0;
+ }
+ no_cache:
+ /*
+ * We must call the client's rendering code. Normally,
+ * we only do this if the character is not cached (cc = 0);
+ * however, we also must do this if we have an xfont but
+ * are using scalable widths. In this case, and only this case,
+ * we get here with cc != 0. penum->current_char has already
+ * been set, but not penum->current_glyph.
+ */
+ SET_CURRENT_GLYPH(penum, glyph);
+ if ((code = gs_gsave(pgs)) < 0)
+ return code;
+ /* Set the font to the current descendant font. */
+ pgs->font = pfont;
+ /* Reset the in_cachedevice flag, so that a recursive show */
+ /* will use the cache properly. */
+ pgs->in_cachedevice = CACHE_DEVICE_NONE;
+ /* Reset the sampling scale. */
+ penum->log2_scale.x = penum->log2_scale.y = 0;
+ /* Set the charpath data in the graphics context if necessary, */
+ /* so that fill and stroke will add to the path */
+ /* rather than having their usual effect. */
+ pgs->in_charpath = penum->charpath_flag;
+ pgs->show_gstate =
+ (penum->show_gstate == pgs ? pgs->saved : penum->show_gstate);
+ pgs->stroke_adjust = false; /* per specification */
+ {
+ gs_fixed_point cpt;
+ gx_path *ppath = pgs->path;
+
+ if ((code = gx_path_current_point_inline(ppath, &cpt)) < 0) {
+ /* For cshow, having no current point is acceptable. */
+ if (!SHOW_IS(penum, TEXT_DO_NONE))
+ goto rret;
+ cpt.x = cpt.y = 0; /* arbitrary */
+ }
+ penum->origin.x = cpt.x;
+ penum->origin.y = cpt.y;
+ /* Normally, char_tm is valid because of show_state_setup, */
+ /* but if we're in a cshow, it may not be. */
+ gs_currentcharmatrix(pgs, NULL, true);
+#if 1 /*USE_FPU <= 0 */
+ if (pgs->ctm.txy_fixed_valid && pgs->char_tm.txy_fixed_valid) {
+ fixed tx = pgs->ctm.tx_fixed;
+ fixed ty = pgs->ctm.ty_fixed;
+
+ gs_settocharmatrix(pgs);
+ cpt.x += pgs->ctm.tx_fixed - tx;
+ cpt.y += pgs->ctm.ty_fixed - ty;
+ } else
+#endif
+ {
+ double tx = pgs->ctm.tx;
+ double ty = pgs->ctm.ty;
+ double fpx, fpy;
+
+ gs_settocharmatrix(pgs);
+ fpx = fixed2float(cpt.x) + (pgs->ctm.tx - tx);
+ fpy = fixed2float(cpt.y) + (pgs->ctm.ty - ty);
+#define f_fits_in_fixed(f) f_fits_in_bits(f, fixed_int_bits)
+ if (!(f_fits_in_fixed(fpx) && f_fits_in_fixed(fpy))) {
+ gs_note_error(code = gs_error_limitcheck);
+ goto rret;
+ }
+ cpt.x = float2fixed(fpx);
+ cpt.y = float2fixed(fpy);
+ }
+ gs_newpath(pgs);
+ code = show_origin_setup(pgs, cpt.x, cpt.y,
+ penum->charpath_flag);
+ if (code < 0)
+ goto rret;
+ }
+ penum->width_status = sws_none;
+ penum->continue_proc = continue_show_update;
+ /* Try using the build procedure in the font. */
+ /* < 0 means error, 0 means success, 1 means failure. */
+ penum->cc = cc; /* set this now for build procedure */
+ code = (*pfont->procs.build_char)((gs_text_enum_t *)penum, pgs, pfont,
+ chr, glyph);
+ if (code < 0) {
+ discard(gs_note_error(code));
+ goto rret;
+ }
+ if (code == 0) {
+ code = show_update(penum);
+ if (code < 0)
+ goto rret;
+ /* Note that show_update does a grestore.... */
+ code = show_move(penum);
+ if (code)
+ return code; /* ... so don't go to rret here. */
+ goto more;
+ }
+ /*
+ * Some BuildChar procedures do a save before the setcachedevice,
+ * and a restore at the end. If we waited to allocate the cache
+ * device until the setcachedevice, we would attempt to free it
+ * after the restore. Therefore, allocate it now.
+ */
+ if (penum->dev_cache == 0) {
+ code = show_cache_setup(penum);
+ if (code < 0)
+ goto rret;
+ }
+ return TEXT_PROCESS_RENDER;
+ /* If we get an error while setting up for BuildChar, */
+ /* we must undo the partial setup. */
+ rret:gs_grestore(pgs);
+ return code;
+#undef get_next_char_glyph
+}
+
+/*
+ * Prepare to retry rendering of the current character. (This is only used
+ * in one place in zchar1.c; a different approach may be better.)
+ */
+private int
+gx_show_text_retry(gs_text_enum_t *pte)
+{
+ gs_show_enum *const penum = (gs_show_enum *)pte;
+
+ if (penum->cc) {
+ gs_font *pfont = penum->current_font;
+
+ gx_free_cached_char(pfont->dir, penum->cc);
+ penum->cc = 0;
+ }
+ gs_grestore(penum->pgs);
+ penum->width_status = sws_none;
+ penum->log2_scale.x = penum->log2_scale.y = 0;
+ return 0;
+}
+
+/* Finish show or stringwidth */
+private int
+show_finish(gs_show_enum * penum)
+{
+ gs_state *pgs = penum->pgs;
+ int code, rcode;
+
+ if (penum->auto_release)
+ penum->procs->release((gs_text_enum_t *)penum, "show_finish");
+ if (!SHOW_IS_STRINGWIDTH(penum))
+ return 0;
+ /* Save the accumulated width before returning, */
+ /* and undo the extra gsave. */
+ code = gs_currentpoint(pgs, &penum->returned.total_width);
+ rcode = gs_grestore(pgs);
+ return (code < 0 ? code : rcode);
+}
+
+/* Release the structure. */
+private void
+gx_show_text_release(gs_text_enum_t *pte, client_name_t cname)
+{
+ gs_show_enum *const penum = (gs_show_enum *)pte;
+
+ penum->cc = 0;
+ if (penum->dev_cache2) {
+ gx_device_retain((gx_device *)penum->dev_cache2, false);
+ penum->dev_cache2 = 0;
+ }
+ if (penum->dev_cache) {
+ gx_device_retain((gx_device *)penum->dev_cache, false);
+ penum->dev_cache = 0;
+ }
+ if (penum->dev_null) {
+ gx_device_retain((gx_device *)penum->dev_null, false);
+ penum->dev_null = 0;
+ }
+ gx_default_text_release(pte, cname);
+}
+
+/* ------ Miscellaneous accessors ------ */
+
+/* Return the charpath mode. */
+gs_char_path_mode
+gs_show_in_charpath(const gs_show_enum * penum)
+{
+ return penum->charpath_flag;
+}
+
+/* Return true if we only need the width from the rasterizer */
+/* and can short-circuit the full rendering of the character, */
+/* false if we need the actual character bits. */
+/* This is only meaningful just before calling gs_setcharwidth or */
+/* gs_setcachedevice[2]. */
+/* Note that we can't do this if the procedure has done any extra [g]saves. */
+private bool
+gx_show_text_is_width_only(const gs_text_enum_t *pte)
+{
+ const gs_show_enum *const penum = (const gs_show_enum *)pte;
+
+ /* penum->cc will be non-zero iff we are calculating */
+ /* the scalable width for an xfont character. */
+ return ((!SHOW_USES_OUTLINE(penum) || penum->cc != 0) &&
+ penum->pgs->level == penum->level + 1);
+}
+
+/* Return the width of the just-enumerated character (for cshow). */
+private int
+gx_show_text_current_width(const gs_text_enum_t *pte, gs_point *pwidth)
+{
+ const gs_show_enum *const penum = (const gs_show_enum *)pte;
+
+ return gs_idtransform(penum->pgs,
+ fixed2float(penum->wxy.x),
+ fixed2float(penum->wxy.y), pwidth);
+}
+
+/* Return the current font for cshow. */
+gs_font *
+gs_show_current_font(const gs_show_enum * penum)
+{
+ return (penum->fstack.depth < 0 ? penum->pgs->font :
+ penum->fstack.items[penum->fstack.depth].font);
+}
+
+/* ------ Internal routines ------ */
+
+/* Initialize the gstate-derived parts of a show enumerator. */
+/* We do this both when starting the show operation, */
+/* and when returning from the kshow callout. */
+/* Uses only penum->pgs, penum->fstack. */
+private int
+show_state_setup(gs_show_enum * penum)
+{
+ gs_state *pgs = penum->pgs;
+ gx_clip_path *pcpath;
+ gs_font *pfont;
+
+ if (penum->fstack.depth <= 0) {
+ pfont = pgs->font;
+ gs_currentcharmatrix(pgs, NULL, 1); /* make char_tm valid */
+ } else {
+ /* We have to concatenate the parent's FontMatrix as well. */
+ gs_matrix mat;
+ const gx_font_stack_item_t *pfsi =
+ &penum->fstack.items[penum->fstack.depth];
+
+ pfont = pfsi->font;
+ gs_matrix_multiply(&pfont->FontMatrix,
+ &pfsi[-1].font->FontMatrix, &mat);
+ gs_setcharmatrix(pgs, &mat);
+ }
+ penum->current_font = pfont;
+ /* Skewing or non-rectangular rotation are not supported. */
+ if (!CACHE_ROTATED_CHARS &&
+ (is_fzero2(pgs->char_tm.xy, pgs->char_tm.yx) ||
+ is_fzero2(pgs->char_tm.xx, pgs->char_tm.yy))
+ )
+ penum->can_cache = 0;
+ if (penum->can_cache >= 0 &&
+ gx_effective_clip_path(pgs, &pcpath) >= 0
+ ) {
+ gs_fixed_rect cbox;
+
+ gx_cpath_inner_box(pcpath, &cbox);
+ /* Since characters occupy an integral number of pixels, */
+ /* we can (and should) round the inner clipping box */
+ /* outward rather than inward. */
+ penum->ibox.p.x = fixed2int_var(cbox.p.x);
+ penum->ibox.p.y = fixed2int_var(cbox.p.y);
+ penum->ibox.q.x = fixed2int_var_ceiling(cbox.q.x);
+ penum->ibox.q.y = fixed2int_var_ceiling(cbox.q.y);
+ gx_cpath_outer_box(pcpath, &cbox);
+ penum->obox.p.x = fixed2int_var(cbox.p.x);
+ penum->obox.p.y = fixed2int_var(cbox.p.y);
+ penum->obox.q.x = fixed2int_var_ceiling(cbox.q.x);
+ penum->obox.q.y = fixed2int_var_ceiling(cbox.q.y);
+#if 1 /*USE_FPU <= 0 */
+ if (pgs->ctm.txy_fixed_valid && pgs->char_tm.txy_fixed_valid) {
+ penum->ftx = (int)fixed2long(pgs->char_tm.tx_fixed -
+ pgs->ctm.tx_fixed);
+ penum->fty = (int)fixed2long(pgs->char_tm.ty_fixed -
+ pgs->ctm.ty_fixed);
+ } else {
+#endif
+ double fdx = pgs->char_tm.tx - pgs->ctm.tx;
+ double fdy = pgs->char_tm.ty - pgs->ctm.ty;
+
+#define int_bits (arch_sizeof_int * 8 - 1)
+ if (!(f_fits_in_bits(fdx, int_bits) &&
+ f_fits_in_bits(fdy, int_bits))
+ )
+ return_error(gs_error_limitcheck);
+#undef int_bits
+ penum->ftx = (int)fdx;
+ penum->fty = (int)fdy;
+ }
+ }
+ show_set_encode_char(penum);
+ return 0;
+}
+
+/* Set the suggested oversampling scale for character rendering. */
+private void
+show_set_scale(gs_show_enum * penum)
+{
+ /*
+ * Decide whether to oversample.
+ * We have to decide this each time setcachedevice is called.
+ */
+ const gs_state *pgs = penum->pgs;
+
+ if ((penum->charpath_flag == cpm_show ||
+ penum->charpath_flag == cpm_charwidth) &&
+ SHOW_USES_OUTLINE(penum) &&
+ gx_path_is_void_inline(pgs->path) &&
+ /* Oversampling rotated characters doesn't work well. */
+ (is_fzero2(pgs->char_tm.xy, pgs->char_tm.yx) ||
+ is_fzero2(pgs->char_tm.xx, pgs->char_tm.yy))
+ ) {
+ const gs_font_base *pfont = (gs_font_base *) pgs->font;
+ gs_fixed_point extent;
+ int code = gs_distance_transform2fixed(&pgs->char_tm,
+ pfont->FontBBox.q.x - pfont->FontBBox.p.x,
+ pfont->FontBBox.q.y - pfont->FontBBox.p.y,
+ &extent);
+
+ if (code >= 0) {
+ int sx =
+ (extent.x == 0 ? 0 :
+ any_abs(extent.x) < int2fixed(25) ? 2 :
+ any_abs(extent.x) < int2fixed(60) ? 1 :
+ 0);
+ int sy =
+ (extent.y == 0 ? 0 :
+ any_abs(extent.y) < int2fixed(25) ? 2 :
+ any_abs(extent.y) < int2fixed(60) ? 1 :
+ 0);
+
+ /* If we oversample at all, make sure we do it */
+ /* in both X and Y. */
+ if (sx == 0 && sy != 0)
+ sx = 1;
+ else if (sy == 0 && sx != 0)
+ sy = 1;
+ penum->log2_suggested_scale.x = sx;
+ penum->log2_suggested_scale.y = sy;
+ return;
+ }
+ }
+ /* By default, don't scale. */
+ penum->log2_suggested_scale.x =
+ penum->log2_suggested_scale.y = 0;
+}
+
+/* Set up the cache device and related information. */
+/* Note that we always allocate both cache devices, */
+/* even if we only use one of them. */
+private int
+show_cache_setup(gs_show_enum * penum)
+{
+ gs_state *pgs = penum->pgs;
+ gs_memory_t *mem = pgs->memory;
+ gx_device_memory *dev =
+ gs_alloc_struct(mem, gx_device_memory, &st_device_memory,
+ "show_cache_setup(dev_cache)");
+ gx_device_memory *dev2 =
+ gs_alloc_struct(mem, gx_device_memory, &st_device_memory,
+ "show_cache_setup(dev_cache2)");
+
+ if (dev == 0 || dev2 == 0) {
+ gs_free_object(mem, dev2, "show_cache_setup(dev_cache2)");
+ gs_free_object(mem, dev, "show_cache_setup(dev_cache)");
+ return_error(gs_error_VMerror);
+ }
+ /*
+ * We only initialize the devices for the sake of the GC,
+ * (since we have to re-initialize dev as either a mem_mono
+ * or a mem_abuf device before actually using it) and also
+ * to set its memory pointer.
+ */
+ gs_make_mem_mono_device(dev, mem, gs_currentdevice_inline(pgs));
+ penum->dev_cache = dev;
+ gs_make_mem_mono_device(dev2, mem, gs_currentdevice_inline(pgs));
+ penum->dev_cache2 = dev2;
+ /* Retain these devices, since they are referenced from the enumerator. */
+ gx_device_retain((gx_device *)dev, true);
+ gx_device_retain((gx_device *)dev2, true);
+ return 0;
+}
+
+/* Set the character origin as the origin of the coordinate system. */
+/* Used before rendering characters, and for moving the origin */
+/* in setcachedevice2 when WMode=1. */
+private int
+show_origin_setup(gs_state * pgs, fixed cpt_x, fixed cpt_y,
+ gs_char_path_mode charpath_flag)
+{
+ if (charpath_flag == cpm_show) {
+ /* Round the translation in the graphics state. */
+ /* This helps prevent rounding artifacts later. */
+ cpt_x = fixed_rounded(cpt_x);
+ cpt_y = fixed_rounded(cpt_y);
+ }
+ /*
+ * BuildChar procedures expect the current point to be undefined,
+ * so we omit the gx_path_add_point with ctm.t*_fixed.
+ */
+ return gx_translate_to_fixed(pgs, cpt_x, cpt_y);
+}
diff --git a/gs/src/gxchar.h b/gs/src/gxchar.h
index 8eef4d3e5..cd2fc15c6 100644
--- a/gs/src/gxchar.h
+++ b/gs/src/gxchar.h
@@ -30,59 +30,30 @@
#ifndef cached_char_DEFINED
# define cached_char_DEFINED
typedef struct cached_char_s cached_char;
-
#endif
/* The type of cached font/matrix pairs is opaque. */
#ifndef cached_fm_pair_DEFINED
# define cached_fm_pair_DEFINED
typedef struct cached_fm_pair_s cached_fm_pair;
-
#endif
/* The type of font objects is opaque. */
#ifndef gs_font_DEFINED
# define gs_font_DEFINED
typedef struct gs_font_s gs_font;
-
#endif
/* The types of memory and null devices may be opaque. */
#ifndef gx_device_memory_DEFINED
# define gx_device_memory_DEFINED
typedef struct gx_device_memory_s gx_device_memory;
-
#endif
#ifndef gx_device_null_DEFINED
# define gx_device_null_DEFINED
typedef struct gx_device_null_s gx_device_null;
-
#endif
-/*
- * Define the stack for composite fonts.
- * If the current font is not composite, depth = -1.
- * If the current font is composite, 0 <= depth <= max_font_depth.
- * items[0] through items[depth] are occupied.
- * items[0].font is the root font; items[0].index = 0.
- * The root font must be composite, but may be of any map type.
- * items[0..N-1] are modal composite fonts, for some N <= depth.
- * items[N..depth-1] are non-modal composite fonts.
- * items[depth] is a base (non-composite) font.
- * Note that if depth >= 0, the font member of the graphics state
- * for a base font BuildChar/Glyph is the same as items[depth].font.
- */
-#define max_font_depth 5
-typedef struct gx_font_stack_item_s {
- gs_font *font; /* font at this level */
- uint index; /* index of this font in parent's */
- /* Encoding */
-} gx_font_stack_item;
-typedef struct gx_font_stack_s {
- int depth;
- gx_font_stack_item items[1 + max_font_depth];
-} gx_font_stack;
-
/* An enumeration object for string display. */
typedef enum {
sws_none,
@@ -93,32 +64,8 @@ typedef enum {
struct gs_show_enum_s {
/* Put this first for subclassing. */
gs_text_enum_common; /* (procs, text, index) */
-
-#define SHOW_IS(penum, op_mask)\
- (((penum)->text.operation & (op_mask)) != 0)
-#define SHOW_IS_ALL_OF(penum, op_mask)\
- (((penum)->text.operation & (op_mask)) == (op_mask))
- /*
- * The comments next to the following macros indicate the
- * corresponding test in pre-5.24 filesets.
- */
-#define SHOW_IS_ADD_TO_ALL(penum) /* add */\
- SHOW_IS(penum, TEXT_ADD_TO_ALL_WIDTHS)
-#define SHOW_IS_ADD_TO_SPACE(penum) /* wchr != no_char */\
- SHOW_IS(penum, TEXT_ADD_TO_SPACE_WIDTH)
-#define SHOW_IS_DO_KERN(penum) /* do_kern */\
- SHOW_IS(penum, TEXT_INTERVENE)
-#define SHOW_IS_XYCSHOW(penum) /* do_kern < 0 */\
- (SHOW_IS_DO_KERN(penum) &&\
- SHOW_IS(penum, TEXT_REPLACE_X_WIDTHS | TEXT_REPLACE_Y_WIDTHS | TEXT_DO_NONE))
-#define SHOW_IS_SLOW(penum) /* slow_show */\
- SHOW_IS(penum, TEXT_ADD_TO_ALL_WIDTHS | TEXT_ADD_TO_SPACE_WIDTH | TEXT_INTERVENE)
-#define SHOW_IS_DRAWING(penum) /* !stringwidth_flag */\
- !SHOW_IS(penum, TEXT_DO_NONE)
-#define SHOW_IS_STRINGWIDTH(penum) /* stringwidth_flag > 0 */\
- SHOW_IS_ALL_OF(penum, TEXT_DO_NONE | TEXT_RETURN_WIDTH)
-
/* Following are set at creation time */
+ bool auto_release; /* true if old API, false if new */
gs_state *pgs;
int level; /* save the level of pgs */
gs_char_path_mode charpath_flag;
@@ -132,9 +79,7 @@ struct gs_show_enum_s {
gs_int_rect obox; /* int version of (outer) clip box */
int ftx, fty; /* transformed font translation */
/* Following are updated dynamically */
- gs_glyph(*encode_char) (P3(gs_show_enum *, gs_font *, gs_char *));
- /* copied from font, */
- /* except for glyphshow */
+ gs_glyph (*encode_char)(P3(gs_font *, gs_char, gs_glyph_space_t)); /* copied from font */
gs_log2_scale_point log2_suggested_scale; /* suggested scaling */
/* factors for oversampling, */
/* based on FontBBox and CTM */
@@ -143,26 +88,24 @@ struct gs_show_enum_s {
/* if dev_cache is an alpha buffer */
gx_device_null *dev_null; /* null device for stringwidth */
/*uint index; */ /* index within string */
- gs_char current_char; /* current char for render or move */
- gs_glyph current_glyph; /* current glyph ditto */
- int cmap_code; /* for FMapType 9 composite fonts, */
- /* the value returned by decode_next */
+ /*uint xy_index;*/ /* index within X/Y widths */
+ /*gs_char returned.current_char;*/ /* current char for render or move */
+ /*gs_glyph returned.current_glyph;*/ /* current glyph ditto */
gs_fixed_point wxy; /* width of current char */
/* in device coords */
gs_fixed_point origin; /* unrounded origin of current char */
/* in device coords, needed for */
/* charpath and WMode=1 */
cached_char *cc; /* being accumulated */
- gs_point width; /* total width of string, set at end */
+ /*gs_point returned.total_width;*/ /* total width of string, set at end */
show_width_status width_status;
- gs_log2_scale_point log2_current_scale;
- gx_font_stack fstack;
+ /*gs_log2_scale_point log2_scale;*/
int (*continue_proc) (P1(gs_show_enum *)); /* continuation procedure */
};
-
#define gs_show_enum_s_DEFINED
-#define private_st_gs_show_enum() /* in gschar.c */\
- gs_private_st_composite(st_gs_show_enum, gs_show_enum, "gs_show_enum",\
+/* The structure descriptor is public for gschar.c. */
+#define public_st_gs_show_enum() /* in gxchar.c */\
+ gs_public_st_composite(st_gs_show_enum, gs_show_enum, "gs_show_enum",\
show_enum_enum_ptrs, show_enum_reloc_ptrs)
/* Cached character procedures (in gxccache.c and gxccman.c) */
diff --git a/gs/src/gxcie.h b/gs/src/gxcie.h
new file mode 100644
index 000000000..df4adf53e
--- /dev/null
+++ b/gs/src/gxcie.h
@@ -0,0 +1,58 @@
+/* Copyright (C) 1999 Aladdin Enterprises. All rights reserved.
+
+ This file is part of Aladdin Ghostscript.
+
+ Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
+ or distributor accepts any responsibility for the consequences of using it,
+ or for whether it serves any particular purpose or works at all, unless he
+ or she says so in writing. Refer to the Aladdin Ghostscript Free Public
+ License (the "License") for full details.
+
+ Every copy of Aladdin Ghostscript must include a copy of the License,
+ normally in a plain ASCII text file named PUBLIC. The License grants you
+ the right to copy, modify and redistribute Aladdin Ghostscript, but only
+ under certain conditions described in the License. Among other things, the
+ License requires that the copyright notice and this notice be preserved on
+ all copies.
+ */
+
+
+/* Internal definitions for CIE color implementation */
+/* Requires gxcspace.h */
+
+#ifndef gxcie_INCLUDED
+# define gxcie_INCLUDED
+
+#include "gscie.h"
+
+/*
+ * These color space implementation procedures are defined in gscie.c or
+ * gsciemap.c, and referenced from the color space structures in gscscie.c.
+ */
+/*
+ * We use CIExxx rather than CIEBasedxxx in some places because
+ * gcc under VMS only retains 23 characters of procedure names,
+ * and DEC C truncates all identifiers at 31 characters.
+ */
+
+/* Defined in gscie.c */
+
+cs_proc_init_color(gx_init_CIE);
+cs_proc_restrict_color(gx_restrict_CIEDEFG);
+cs_proc_install_cspace(gx_install_CIEDEFG);
+cs_proc_restrict_color(gx_restrict_CIEDEF);
+cs_proc_install_cspace(gx_install_CIEDEF);
+cs_proc_restrict_color(gx_restrict_CIEABC);
+cs_proc_install_cspace(gx_install_CIEABC);
+cs_proc_restrict_color(gx_restrict_CIEA);
+cs_proc_install_cspace(gx_install_CIEA);
+
+/* Defined in gsciemap.c */
+
+cs_proc_concretize_color(gx_concretize_CIEDEFG);
+cs_proc_concretize_color(gx_concretize_CIEDEF);
+cs_proc_concretize_color(gx_concretize_CIEABC);
+cs_proc_remap_color(gx_remap_CIEABC);
+cs_proc_concretize_color(gx_concretize_CIEA);
+
+#endif /* gxcie_INCLUDED */
diff --git a/gs/src/gxcldev.h b/gs/src/gxcldev.h
index 630e454ad..ed3a91ab8 100644
--- a/gs/src/gxcldev.h
+++ b/gs/src/gxcldev.h
@@ -291,6 +291,24 @@ struct gx_clist_state_s {
/* primarily large copy_ operations. */
#define cbuf_size 800
+/* ---------------- Driver procedures ---------------- */
+
+/* In gxclrect.c */
+dev_proc_fill_rectangle(clist_fill_rectangle);
+dev_proc_copy_mono(clist_copy_mono);
+dev_proc_copy_color(clist_copy_color);
+dev_proc_copy_alpha(clist_copy_alpha);
+dev_proc_strip_tile_rectangle(clist_strip_tile_rectangle);
+dev_proc_strip_copy_rop(clist_strip_copy_rop);
+
+/* In gxclimag.c */
+dev_proc_fill_mask(clist_fill_mask);
+dev_proc_begin_typed_image(clist_begin_typed_image);
+dev_proc_create_compositor(clist_create_compositor);
+
+/* In gxclread.c */
+dev_proc_get_bits_rectangle(clist_get_bits_rectangle);
+
/* ---------------- Driver procedure support ---------------- */
/*
diff --git a/gs/src/gxclip.c b/gs/src/gxclip.c
index 1831c3a68..37ccf779e 100644
--- a/gs/src/gxclip.c
+++ b/gs/src/gxclip.c
@@ -95,11 +95,11 @@ private const gx_device_clip gs_clip_device =
/* Make a clipping device. */
void
-gx_make_clip_translate_device(gx_device_clip * dev, void *container,
- const gx_clip_list * list, int tx, int ty)
+gx_make_clip_translate_device(gx_device_clip * dev, const gx_clip_list * list,
+ int tx, int ty, gs_memory_t *mem)
{
gx_device_init((gx_device *)dev, (const gx_device *)&gs_clip_device,
- NULL, true);
+ mem, true);
dev->list = *list;
dev->translation.x = tx;
dev->translation.y = ty;
@@ -107,7 +107,7 @@ gx_make_clip_translate_device(gx_device_clip * dev, void *container,
void
gx_make_clip_path_device(gx_device_clip * dev, const gx_clip_path * pcpath)
{
- gx_make_clip_device(dev, NULL, gx_cpath_list(pcpath));
+ gx_make_clip_device(dev, gx_cpath_list(pcpath));
}
/* Define debugging statistics for the clipping loops. */
diff --git a/gs/src/gxclip2.c b/gs/src/gxclip2.c
index 6b4274a29..f07002951 100644
--- a/gs/src/gxclip2.c
+++ b/gs/src/gxclip2.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1995, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1993, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -88,12 +88,12 @@ private const gx_device_tile_clip gs_tile_clip_device =
/* Initialize a tile clipping device from a mask. */
int
tile_clip_initialize(gx_device_tile_clip * cdev, const gx_strip_bitmap * tiles,
- gx_device * tdev, int px, int py)
+ gx_device * tdev, int px, int py, gs_memory_t *mem)
{
int code =
gx_mask_clip_initialize(cdev, &gs_tile_clip_device,
(const gx_bitmap *)tiles,
- tdev, 0, 0); /* phase will be reset */
+ tdev, 0, 0, mem); /* phase will be reset */
if (code >= 0) {
cdev->tiles = *tiles;
diff --git a/gs/src/gxclip2.h b/gs/src/gxclip2.h
index 27c31a5ec..b3f762903 100644
--- a/gs/src/gxclip2.h
+++ b/gs/src/gxclip2.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1996, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1993, 1996, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -40,9 +40,10 @@ typedef gx_device_mask_clip gx_device_tile_clip;
* Initialize a tile clipping device from a mask.
* We supply an explicit phase.
*/
-int tile_clip_initialize(P5(gx_device_tile_clip * cdev,
+int tile_clip_initialize(P6(gx_device_tile_clip * cdev,
const gx_strip_bitmap * tiles,
- gx_device * tdev, int px, int py));
+ gx_device * tdev, int px, int py,
+ gs_memory_t *mem));
/*
* Set the phase of the tile -- used in the tiling loop when
diff --git a/gs/src/gxclist.c b/gs/src/gxclist.c
index 3fadbd3d3..0548c184a 100644
--- a/gs/src/gxclist.c
+++ b/gs/src/gxclist.c
@@ -33,7 +33,7 @@
/* GC information */
#define CLIST_IS_WRITER(cdev) ((cdev)->common.ymin < 0)
extern_st(st_imager_state);
-public
+private
ENUM_PTRS_WITH(device_clist_enum_ptrs, gx_device_clist *cdev)
if (index < st_device_forward_max_ptrs) {
gs_ptr_type_t ret = ENUM_USING_PREFIX(st_device_forward, 0);
@@ -51,7 +51,7 @@ ENUM_PTRS_WITH(device_clist_enum_ptrs, gx_device_clist *cdev)
sizeof(gs_imager_state), index - 1);
}
ENUM_PTRS_END
-public
+private
RELOC_PTRS_WITH(device_clist_reloc_ptrs, gx_device_clist *cdev)
{
RELOC_PREFIX(st_device_forward);
@@ -69,28 +69,7 @@ private dev_proc_open_device(clist_open);
private dev_proc_output_page(clist_output_page);
private dev_proc_close_device(clist_close);
private dev_proc_get_band(clist_get_band);
-
-/* In gxclrect.c */
-extern dev_proc_fill_rectangle(clist_fill_rectangle);
-extern dev_proc_copy_mono(clist_copy_mono);
-extern dev_proc_copy_color(clist_copy_color);
-extern dev_proc_copy_alpha(clist_copy_alpha);
-extern dev_proc_strip_tile_rectangle(clist_strip_tile_rectangle);
-extern dev_proc_strip_copy_rop(clist_strip_copy_rop);
-
-/* In gxclpath.c */
-extern dev_proc_fill_path(clist_fill_path);
-extern dev_proc_stroke_path(clist_stroke_path);
-extern dev_proc_fill_parallelogram(clist_fill_parallelogram);
-extern dev_proc_fill_triangle(clist_fill_triangle);
-
-/* In gxclimag.c */
-extern dev_proc_fill_mask(clist_fill_mask);
-extern dev_proc_begin_typed_image(clist_begin_typed_image);
-extern dev_proc_create_compositor(clist_create_compositor);
-
-/* In gxclread.c */
-extern dev_proc_get_bits_rectangle(clist_get_bits_rectangle);
+/* Driver procedures defined in other files are declared in gxcldev.h. */
/* Other forward declarations */
private int clist_put_current_params(P1(gx_device_clist_writer *cldev));
diff --git a/gs/src/gxclist.h b/gs/src/gxclist.h
index 9a1b39b68..49e51f4a1 100644
--- a/gs/src/gxclist.h
+++ b/gs/src/gxclist.h
@@ -211,9 +211,14 @@ typedef struct gx_device_clist_writer_s {
uint tile_max_count; /* max # of hash table entries */
gx_strip_bitmap tile_params; /* current tile parameters */
int tile_depth; /* current tile depth */
- int tile_known_min, tile_known_max;
- /* range of bands that knows the */
- /* current tile parameters */
+ int tile_known_min, tile_known_max; /* range of bands that knows the */
+ /* current tile parameters */
+ /*
+ * NOTE: we must not set the line_params.dash.pattern member of the
+ * imager state to point to the dash_pattern member of the writer
+ * state (except transiently), since this would confuse the
+ * garbage collector.
+ */
gs_imager_state imager_state; /* current values of imager params */
float dash_pattern[cmd_max_dash]; /* current dash pattern */
const gx_clip_path *clip_path; /* current clip path */
diff --git a/gs/src/gxclpath.c b/gs/src/gxclpath.c
index 4091d5c9f..af5eaf0bc 100644
--- a/gs/src/gxclpath.c
+++ b/gs/src/gxclpath.c
@@ -331,7 +331,8 @@ cmd_write_unknown(gx_device_clist_writer * cldev, gx_clist_state * pcls,
code = set_cmd_put_op(dp, cldev, pcls, cmd_opv_set_misc2, 2);
if (code < 0)
return code;
- dp[1] = cmd_set_misc2_ac_op_sa +
+ dp[1] = cmd_set_misc2_cj_ac_op_sa +
+ ((cldev->imager_state.line_params.curve_join + 1) << 3) +
(cldev->imager_state.accurate_curves ? 4 : 0) +
(cldev->imager_state.overprint ? 2 : 0) +
(cldev->imager_state.stroke_adjust ? 1 : 0);
@@ -353,8 +354,7 @@ cmd_write_unknown(gx_device_clist_writer * cldev, gx_clist_state * pcls,
sizeof(float));
if (n != 0)
memcpy(dp + 2 + sizeof(float) * 2,
- cldev->imager_state.line_params.dash.pattern,
- n * sizeof(float));
+ cldev->dash_pattern, n * sizeof(float));
pcls->known |= dash_known;
}
if (unknown & alpha_known) {
@@ -629,11 +629,9 @@ clist_stroke_path(gx_device * dev, const gs_imager_state * pis, gx_path * ppath,
y1 = y + height;
/* Check the dash pattern, since we bail out if */
/* the pattern is too large. */
- cdev->imager_state.line_params.dash.pattern = cdev->dash_pattern;
if (cdev->imager_state.line_params.dash.pattern_size != pattern_size ||
(pattern_size != 0 &&
- memcmp(cdev->imager_state.line_params.dash.pattern,
- pis->line_params.dash.pattern,
+ memcmp(cdev->dash_pattern, pis->line_params.dash.pattern,
pattern_size * sizeof(float))) ||
cdev->imager_state.line_params.dash.offset !=
pis->line_params.dash.offset ||
@@ -643,15 +641,22 @@ clist_stroke_path(gx_device * dev, const gs_imager_state * pis, gx_path * ppath,
pis->line_params.dot_length ||
cdev->imager_state.line_params.dot_length_absolute !=
pis->line_params.dot_length_absolute
- ) { /* Bail out if the dash pattern is too long. */
+ ) {
+ /* Bail out if the dash pattern is too long. */
if (pattern_size > cmd_max_dash)
return gx_default_stroke_path(dev, pis, ppath, params,
pdcolor, pcpath);
unknown |= dash_known;
+ /*
+ * Temporarily reset the dash pattern pointer for gx_set_dash,
+ * but don't leave it set, since that would confuse the GC.
+ */
+ cdev->imager_state.line_params.dash.pattern = cdev->dash_pattern;
gx_set_dash(&cdev->imager_state.line_params.dash,
pis->line_params.dash.pattern,
pis->line_params.dash.pattern_size,
pis->line_params.dash.offset, NULL);
+ cdev->imager_state.line_params.dash.pattern = 0;
gx_set_dash_adapt(&cdev->imager_state.line_params.dash,
pis->line_params.dash.adapt);
gx_set_dot_length(&cdev->imager_state.line_params,
@@ -689,10 +694,11 @@ clist_stroke_path(gx_device * dev, const gs_imager_state * pis, gx_path * ppath,
state_update(line_params.cap);
state_update(line_params.join);
}
- if (state_neq(accurate_curves) || state_neq(overprint) ||
- state_neq(stroke_adjust)
+ if (state_neq(line_params.curve_join) || state_neq(accurate_curves) ||
+ state_neq(overprint) || state_neq(stroke_adjust)
) {
unknown |= misc1_known;
+ state_update(line_params.curve_join);
state_update(accurate_curves);
state_update(overprint);
state_update(stroke_adjust);
@@ -999,11 +1005,13 @@ cmd_put_path(gx_device_clist_writer * cldev, gx_clist_state * pcls,
cmd_segment_writer writer;
/*
- * initial_op is logically const, so we declare it as such,
- * since some systems really dislike non-const statics.
- * This entails an otherwise pointless cast in set_first_point().
+ * initial_op is logically const. We would like to declare it as
+ * static const, since some systems really dislike non-const statics,
+ * but this would entail a cast in set_first_point() that provokes a
+ * warning message from gcc. Instead, we pay the (tiny) cost of an
+ * unnecessary dynamic initialization.
*/
- static const byte initial_op = cmd_opv_end_run;
+ byte initial_op = cmd_opv_end_run;
/*
* We define the 'side' of a point according to its Y value as
@@ -1068,7 +1076,7 @@ cmd_put_path(gx_device_clist_writer * cldev, gx_clist_state * pcls,
writer.cldev = cldev;
writer.pcls = pcls;
writer.notes = sn_none;
-#define set_first_point() (writer.dp = (byte *)&initial_op)
+#define set_first_point() (writer.dp = &initial_op)
#define first_point() (writer.dp == &initial_op)
set_first_point();
for (;;) {
diff --git a/gs/src/gxclpath.h b/gs/src/gxclpath.h
index 76f42b328..f65fce476 100644
--- a/gs/src/gxclpath.h
+++ b/gs/src/gxclpath.h
@@ -60,8 +60,8 @@ typedef enum {
/* [, hival#, table|map] */
cmd_opv_set_misc2 = 0xd5,
#define cmd_set_misc2_cap_join (0x00) /* 00: cap(3)join(3) */
-#define cmd_set_misc2_ac_op_sa (0x40) /* 01: 0(3)acc.curves(1)overprint(1) */
- /* stroke_adj(1) */
+#define cmd_set_misc2_cj_ac_op_sa (0x40) /* 01: curve_join+1(3)acc.curves(1) */
+ /* overprint(1)stroke_adj(1) */
#define cmd_set_misc2_notes (0x80) /* 10: seg.notes(6) */
#define cmd_set_misc2_value (0xc0) /* 11: (see below) */
#define cmd_set_misc2_flatness (0xc0+0) /* 11000000, flatness(float) */
@@ -162,6 +162,14 @@ typedef enum {
*/
#define is_bits(d, n) !(((d) + ((fixed)1 << ((n) - 1))) & (-(fixed)1 << (n)))
+/* ---------------- Driver procedures ---------------- */
+
+/* In gxclpath.c */
+dev_proc_fill_path(clist_fill_path);
+dev_proc_stroke_path(clist_stroke_path);
+dev_proc_fill_parallelogram(clist_fill_parallelogram);
+dev_proc_fill_triangle(clist_fill_triangle);
+
/* ---------------- Driver procedure support ---------------- */
/* The procedures and macros defined here are used when writing */
diff --git a/gs/src/gxclrast.c b/gs/src/gxclrast.c
index 1ed931b58..30cb75ae8 100644
--- a/gs/src/gxclrast.c
+++ b/gs/src/gxclrast.c
@@ -1946,12 +1946,14 @@ read_set_misc2(command_buf_t *pcb, gs_imager_state *pis, segment_notes *pnotes)
pis->line_params.cap, pis->line_params.join);
break;
- case cmd_set_misc2_ac_op_sa >> 6:
+ case cmd_set_misc2_cj_ac_op_sa >> 6:
+ pis->line_params.curve_join = ((cb >> 3) & 7) - 1;
pis->accurate_curves = (cb & 4) != 0;
pis->overprint = (cb & 2) != 0;
pis->stroke_adjust = cb & 1;
- if_debug3('L', " AC=%d OP=%d SA=%d\n",
- pis->accurate_curves, pis->overprint, pis->stroke_adjust);
+ if_debug4('L', " CJ=%d AC=%d OP=%d SA=%d\n",
+ pis->line_params.curve_join, pis->accurate_curves,
+ pis->overprint, pis->stroke_adjust);
break;
case cmd_set_misc2_notes >> 6:
diff --git a/gs/src/gxcmap.c b/gs/src/gxcmap.c
index ecec4f298..a22a08555 100644
--- a/gs/src/gxcmap.c
+++ b/gs/src/gxcmap.c
@@ -34,19 +34,17 @@
/* Structure descriptor */
public_st_device_color();
-#define cptr ((gx_device_color *)vptr)
private
-ENUM_PTRS_BEGIN(device_color_enum_ptrs)
+ENUM_PTRS_WITH(device_color_enum_ptrs, gx_device_color *cptr)
{
return ENUM_USING(*cptr->type->stype, vptr, size, index);
}
ENUM_PTRS_END
-private RELOC_PTRS_BEGIN(device_color_reloc_ptrs)
+private RELOC_PTRS_WITH(device_color_reloc_ptrs, gx_device_color *cptr)
{
RELOC_USING(*cptr->type->stype, vptr, size);
}
RELOC_PTRS_END
-#undef cptr
/* ------ Trace device mapping procedures ------ */
diff --git a/gs/src/gxcmap.h b/gs/src/gxcmap.h
index ce1380a75..cd66c2cf4 100644
--- a/gs/src/gxcmap.h
+++ b/gs/src/gxcmap.h
@@ -88,8 +88,6 @@ void gx_set_cmap_procs(P2(gs_imager_state *, const gx_device *));
((pis)->cmap_procs->map_rgb_alpha)(cr, cg, cb, ca, pdc, pis, dev, select)
/* Map a color, with optional tracing if we are debugging. */
-#ifdef DEBUG
-/* Use procedures in gxcmap.c */
#include "gxcindex.h"
#include "gxcvalue.h"
gx_color_index gx_proc_map_rgb_color(P4(gx_device *,
@@ -98,7 +96,8 @@ gx_color_index gx_proc_map_rgb_alpha_color(P5(gx_device *,
gx_color_value, gx_color_value, gx_color_value, gx_color_value));
gx_color_index gx_proc_map_cmyk_color(P5(gx_device *,
gx_color_value, gx_color_value, gx_color_value, gx_color_value));
-
+#ifdef DEBUG
+/* Use procedures in gxcmap.c */
# define gx_map_rgb_color(dev, vr, vg, vb)\
gx_proc_map_rgb_color(dev, vr, vg, vb)
# define gx_map_rgb_alpha_color(dev, vr, vg, vb, va)\
diff --git a/gs/src/gxcpath.c b/gs/src/gxcpath.c
index 5202ddd89..591099631 100644
--- a/gs/src/gxcpath.c
+++ b/gs/src/gxcpath.c
@@ -90,45 +90,11 @@ RELOC_PTRS_WITH(device_clip_reloc_ptrs, gx_device_clip *cptr)
RELOC_PTRS_END
/* Define an empty clip list. */
-private const gx_clip_list clip_list_empty =
-{
+private const gx_clip_list clip_list_empty = {
{0, 0, min_int, max_int, 0, 0},
0, 0, 0, 0, 0
};
-/* Debugging */
-
-#ifdef DEBUG
-/* Validate a clipping path. */
-bool /* only exported for gxacpath.c */
-clip_list_validate(const gx_clip_list * clp)
-{
- if (clp->count <= 1)
- return (clp->head == 0 && clp->tail == 0 &&
- clp->single.next == 0 && clp->single.prev == 0);
- else {
- const gx_clip_rect *prev = clp->head;
- const gx_clip_rect *ptr;
- bool ok = true;
-
- while ((ptr = prev->next) != 0) {
- if (ptr->ymin > ptr->ymax || ptr->xmin > ptr->xmax ||
- !(ptr->ymin >= prev->ymax ||
- (ptr->ymin == prev->ymin &&
- ptr->ymax == prev->ymax &&
- ptr->xmin >= prev->xmax)) ||
- ptr->prev != prev
- ) {
- clip_rect_print('q', "WRONG:", ptr);
- ok = false;
- }
- prev = ptr;
- }
- return ok && prev == clp->tail;
- }
-}
-#endif
-
/* ------ Clipping path memory management ------ */
private rc_free_proc(rc_free_cpath_list);
diff --git a/gs/src/gxcpath.h b/gs/src/gxcpath.h
index 802656037..c18059bc4 100644
--- a/gs/src/gxcpath.h
+++ b/gs/src/gxcpath.h
@@ -112,11 +112,12 @@ extern_st(st_device_clip);
gs_public_st_composite_use_final(st_device_clip, gx_device_clip,\
"gx_device_clip", device_clip_enum_ptrs, device_clip_reloc_ptrs,\
gx_device_finalize)
-void gx_make_clip_translate_device(P5(gx_device_clip * dev, void *container,
- const gx_clip_list * list, int tx, int ty));
+void gx_make_clip_translate_device(P5(gx_device_clip * dev,
+ const gx_clip_list * list,
+ int tx, int ty, gs_memory_t *mem));
-#define gx_make_clip_device(dev, container, list)\
- gx_make_clip_translate_device(dev, container, list, 0, 0)
+#define gx_make_clip_device(dev, list)\
+ gx_make_clip_translate_device(dev, list, 0, 0, NULL)
void gx_make_clip_path_device(P2(gx_device_clip *, const gx_clip_path *));
#define clip_rect_print(ch, str, ar)\
diff --git a/gs/src/gxcspace.h b/gs/src/gxcspace.h
index 05dff50f4..c261466d2 100644
--- a/gs/src/gxcspace.h
+++ b/gs/src/gxcspace.h
@@ -208,6 +208,20 @@ cs_proc_install_cspace(gx_no_install_cspace);
cs_proc_adjust_cspace_count(gx_no_adjust_cspace_count);
cs_proc_adjust_color_count(gx_no_adjust_color_count);
+/*
+ * Define the implementation procedures for the standard device color
+ * spaces. These are implemented in gxcmap.c.
+ */
+cs_proc_remap_color(gx_remap_DeviceGray);
+cs_proc_concretize_color(gx_concretize_DeviceGray);
+cs_proc_remap_concrete_color(gx_remap_concrete_DGray);
+cs_proc_remap_color(gx_remap_DeviceRGB);
+cs_proc_concretize_color(gx_concretize_DeviceRGB);
+cs_proc_remap_concrete_color(gx_remap_concrete_DRGB);
+cs_proc_remap_color(gx_remap_DeviceCMYK);
+cs_proc_concretize_color(gx_concretize_DeviceCMYK);
+cs_proc_remap_concrete_color(gx_remap_concrete_DCMYK);
+
/* Define the allocator type for color spaces. */
extern_st(st_color_space);
diff --git a/gs/src/gxdevice.h b/gs/src/gxdevice.h
index b3f82129b..013a9be49 100644
--- a/gs/src/gxdevice.h
+++ b/gs/src/gxdevice.h
@@ -24,6 +24,7 @@
#include "stdio_.h" /* for FILE */
#include "gxdevcli.h"
+#include "gsfname.h"
#include "gsparam.h"
/*
* Many drivers still use gs_malloc and gs_free, so include the interface
@@ -360,11 +361,29 @@ void gx_device_copy_color_params(P2(gx_device *dev, const gx_device *target));
*/
void gx_device_copy_params(P2(gx_device *dev, const gx_device *target));
-/* Open the output file for a device. */
-int gx_device_open_output_file(P5(const gx_device * dev, const char *fname,
+/*
+ * Parse the output file name for a device, recognizing "-" and "|command",
+ * and also detecting and validating any %nnd format for inserting the
+ * page count. If a format is present, store a pointer to its last
+ * character in *pfmt, otherwise store 0 there. Note that an empty name
+ * is currently allowed.
+ */
+int gx_parse_output_file_name(P4(gs_parsed_file_name_t *pfn,
+ const char **pfmt, const char *fname,
+ uint len));
+
+/*
+ * Open the output file for a device. Note that if the file name is empty,
+ * it may be replaced with the name of a scratch file.
+ */
+int gx_device_open_output_file(P5(const gx_device * dev, char *fname,
bool binary, bool positionable,
FILE ** pfile));
+/* Close the output file for a device. */
+int gx_device_close_output_file(P3(const gx_device * dev, const char *fname,
+ FILE *file));
+
/*
* Determine whether a given device needs to halftone. Eventually this
* should take an imager state as an additional argument.
diff --git a/gs/src/gxfarith.h b/gs/src/gxfarith.h
index 86a6771f3..1c7edeaf8 100644
--- a/gs/src/gxfarith.h
+++ b/gs/src/gxfarith.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1995, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1993, 1995, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -45,8 +45,8 @@ typedef long _f_int_t;
typedef ulong _f_uint_t;
# endif
-# define _f_as_int(f) *(_f_int_t *)(&(f))
-# define _f_as_uint(f) *(_f_uint_t *)(&(f))
+# define _f_as_int(f) *(const _f_int_t *)(&(f))
+# define _f_as_uint(f) *(const _f_uint_t *)(&(f))
# if arch_sizeof_double == arch_sizeof_int
# define _d_int_t int
@@ -56,8 +56,8 @@ typedef ulong _f_uint_t;
# endif
# endif
# define _d_uint_t unsigned _d_int_t
-# define _d_as_int(f) *(_d_int_t *)(&(d))
-# define _d_as_uint(f) *(_d_uint_t *)(&(d))
+# define _d_as_int(f) *(const _d_int_t *)(&(d))
+# define _d_as_uint(f) *(const _d_uint_t *)(&(d))
# define _ftest(v,f,n)\
(sizeof(v)==sizeof(float)?(f):(n))
@@ -82,9 +82,9 @@ typedef ulong _f_uint_t;
# undef is_fneg
# if arch_is_big_endian
-# define _is_fnegb(f) (*(byte *)&(f) >= 0x80)
+# define _is_fnegb(f) (*(const byte *)&(f) >= 0x80)
# else
-# define _is_fnegb(f) (((byte *)&(f))[sizeof(f) - 1] >= 0x80)
+# define _is_fnegb(f) (((const byte *)&(f))[sizeof(f) - 1] >= 0x80)
# endif
# if arch_sizeof_float == arch_sizeof_int
# define is_fneg(f)\
diff --git a/gs/src/gxfcache.h b/gs/src/gxfcache.h
index dc54a4e1a..bd0517f33 100644
--- a/gs/src/gxfcache.h
+++ b/gs/src/gxfcache.h
@@ -215,6 +215,10 @@ typedef struct char_cache_s {
/* ------ Font/character cache ------ */
/* A font "directory" (font/character cache manager). */
+#ifndef gs_font_dir_DEFINED
+# define gs_font_dir_DEFINED
+typedef struct gs_font_dir_s gs_font_dir;
+#endif
struct gs_font_dir_s {
/* Original (unscaled) fonts */
diff --git a/gs/src/gxfill.c b/gs/src/gxfill.c
index c22949738..09f8aff43 100644
--- a/gs/src/gxfill.c
+++ b/gs/src/gxfill.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1989, 1995, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1989, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -319,7 +319,7 @@ gx_default_fill_path(gx_device * pdev, const gs_imager_state * pis,
*/
if (pcpath) {
dev = (gx_device *) & cdev;
- gx_make_clip_device(&cdev, &cdev, gx_cpath_list(pcpath));
+ gx_make_clip_device(&cdev, gx_cpath_list(pcpath));
cdev.target = save_dev;
cdev.max_fill_band = save_dev->max_fill_band;
(*dev_proc(dev, open_device)) (dev);
diff --git a/gs/src/gxfixed.h b/gs/src/gxfixed.h
index 44d4b464f..9d094a11e 100644
--- a/gs/src/gxfixed.h
+++ b/gs/src/gxfixed.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1989, 1995, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1989, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -83,8 +83,8 @@ typedef ulong ufixed; /* only used in a very few places */
#define fixed_is_int(x) !((x)&_fixed_fraction_v)
#if arch_ints_are_short & !arch_is_big_endian
/* Do some of the shifting and extraction ourselves. */
-# define _fixed_hi(x) *((uint *)&(x)+1)
-# define _fixed_lo(x) *((uint *)&(x))
+# define _fixed_hi(x) *((const uint *)&(x)+1)
+# define _fixed_lo(x) *((const uint *)&(x))
# define fixed2int_var(x)\
((int)((_fixed_hi(x) << (16-_fixed_shift)) +\
(_fixed_lo(x) >> _fixed_shift)))
@@ -171,26 +171,26 @@ fixed fixed_mult_quo(P3(fixed A, fixed B, fixed C));
* FINISH_DFMUL2FIXED_VARS(R, dtemp);
*/
#if USE_FPU_FIXED && arch_sizeof_short == 2
-
+#define NEED_SET_FMUL2FIXED
int set_fmul2fixed_(P3(fixed *, long, long));
#define CHECK_FMUL2FIXED_VARS(vr, vfa, vfb, dtemp)\
- set_fmul2fixed_(&vr, *(long *)&vfa, *(long *)&vfb)
+ set_fmul2fixed_(&vr, *(const long *)&vfa, *(const long *)&vfb)
#define FINISH_FMUL2FIXED_VARS(vr, dtemp)\
DO_NOTHING
-
int set_dfmul2fixed_(P4(fixed *, ulong, long, long));
# if arch_is_big_endian
# define CHECK_DFMUL2FIXED_VARS(vr, vda, vfb, dtemp)\
- set_dfmul2fixed_(&vr, ((ulong *)&vda)[1], *(long *)&vfb, *(long *)&vda)
+ set_dfmul2fixed_(&vr, ((const ulong *)&vda)[1], *(const long *)&vfb, *(const long *)&vda)
# else
# define CHECK_DFMUL2FIXED_VARS(vr, vda, vfb, dtemp)\
- set_dfmul2fixed_(&vr, *(ulong *)&vda, *(long *)&vfb, ((long *)&vda)[1])
+ set_dfmul2fixed_(&vr, *(const ulong *)&vda, *(const long *)&vfb, ((const long *)&vda)[1])
# endif
#define FINISH_DFMUL2FIXED_VARS(vr, dtemp)\
DO_NOTHING
#else /* don't bother */
+#undef NEED_SET_FMUL2FIXED
#define CHECK_FMUL2FIXED_VARS(vr, vfa, vfb, dtemp)\
(dtemp = (vfa) * (vfb),\
(f_fits_in_bits(dtemp, fixed_int_bits) ? 0 :\
@@ -219,17 +219,21 @@ int set_double2fixed_(P4(fixed *, ulong, long, int));
# define set_float2fixed_vars(vr,vf)\
(sizeof(vf) == sizeof(float) ?\
- set_float2fixed_(&vr, *(long *)&vf, fixed_fraction_bits) :\
- set_double2fixed_(&vr, ((ulong *)&vf)[arch_is_big_endian],\
- ((long *)&vf)[1 - arch_is_big_endian],\
+ set_float2fixed_(&vr, *(const long *)&vf, fixed_fraction_bits) :\
+ set_double2fixed_(&vr, ((const ulong *)&vf)[arch_is_big_endian],\
+ ((const long *)&vf)[1 - arch_is_big_endian],\
fixed_fraction_bits))
long fixed2float_(P2(fixed, int));
void set_fixed2double_(P3(double *, fixed, int));
+/*
+ * We need the (double *)&vf cast to prevent compile-time error messages,
+ * even though the call will only be executed if vf has the correct type.
+ */
# define set_fixed2float_var(vf,x)\
(sizeof(vf) == sizeof(float) ?\
(*(long *)&vf = fixed2float_(x, fixed_fraction_bits), 0) :\
- (set_fixed2double_(&vf, x, fixed_fraction_bits), 0))
+ (set_fixed2double_((double *)&vf, x, fixed_fraction_bits), 0))
#define set_ldexp_fixed2double(vd, x, exp)\
set_fixed2double_(&vd, x, -(exp))
#else
diff --git a/gs/src/gxfont.h b/gs/src/gxfont.h
index f360b0e56..4f7349da0 100644
--- a/gs/src/gxfont.h
+++ b/gs/src/gxfont.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1989, 1995, 1996, 1997 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1989, 1995, 1996, 1997, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -24,6 +24,7 @@
#include "gsccode.h"
#include "gsfont.h"
+#include "gsnotify.h"
#include "gsuid.h"
#include "gsstype.h" /* for extern_st */
#include "gxftype.h"
@@ -31,110 +32,239 @@
/* A font object as seen by clients. */
/* See the PostScript Language Reference Manual for details. */
-#ifndef gs_show_enum_DEFINED
-# define gs_show_enum_DEFINED
-typedef struct gs_show_enum_s gs_show_enum;
+#ifndef gs_text_enum_DEFINED
+# define gs_text_enum_DEFINED
+typedef struct gs_text_enum_s gs_text_enum_t;
+#endif
+#ifndef gx_path_DEFINED
+# define gx_path_DEFINED
+typedef struct gx_path_s gx_path;
#endif
/*
- * Fonts are "objects" to a limited extent, in that some of their
- * behavior is provided by a record of procedures in the font.
- * However, adding new types of fonts (subclasses) is not supported well.
+ * Define flags for font properties (Flags* members in the structure below.)
+ * Currently these must match the ones defined for PDF.
+ */
+#define FONT_IS_FIXED_WIDTH (1<<0)
+/*
+ * Define the structure used to return information about the font as a
+ * whole. Currently this structure almost exactly parallels the PDF
+ * FontDescriptor.
+ *
+ * Unless otherwise specified, values are in the font's native character
+ * space, scaled as requested by the call to the font_info procedure.
+ * Note that Type 1 fonts typically have 1000 units per em, while
+ * TrueType fonts typically have 1 unit per em.
+ */
+typedef struct gs_font_info_s {
+ int members;
+#define FONT_INFO_ASCENT 0x0001
+ int Ascent;
+#define FONT_INFO_AVG_WIDTH 0x0002
+ int AvgWidth;
+#define FONT_INFO_BBOX 0x0004
+ gs_int_rect BBox; /* computed from outlines, not FontBBox */
+#define FONT_INFO_CAP_HEIGHT 0x0008
+ int CapHeight;
+#define FONT_INFO_DESCENT 0x0010
+ int Descent;
+#define FONT_INFO_FLAGS 0x0020
+ uint Flags; /* a mask of FONT_IS_ bits */
+ uint Flags_requested; /* client must set this if FLAGS requested */
+ uint Flags_returned;
+#define FONT_INFO_ITALIC_ANGLE 0x0100
+ float ItalicAngle; /* degrees CCW from vertical */
+#define FONT_INFO_LEADING 0x0200
+ int Leading;
+#define FONT_INFO_MAX_WIDTH 0x0400
+ int MaxWidth;
+#define FONT_INFO_MISSING_WIDTH 0x0800
+ int MissingWidth;
+#define FONT_INFO_STEM_H 0x00010000
+ int StemH;
+#define FONT_INFO_STEM_V 0x00020000
+ int StemV;
+#define FONT_INFO_UNDERLINE_POSITION 0x00040000
+ int UnderlinePosition;
+#define FONT_INFO_UNDERLINE_THICKNESS 0x00080000
+ int UnderlineThickness;
+#define FONT_INFO_X_HEIGHT 0x00100000
+ int XHeight;
+} gs_font_info_t;
+
+/*
+ * Define the structure used to return information about a glyph.
*/
+typedef struct gs_glyph_info_s {
+ int members; /* mask of which members are valid */
+#define GLYPH_INFO_WIDTH0 1
+#define GLYPH_INFO_WIDTH GLYPH_INFO_WIDTH0
+#define GLYPH_INFO_WIDTH1 2 /* must be WIDTH0 << 1 */
+#define GLYPH_INFO_WIDTHS (GLYPH_INFO_WIDTH0 | GLYPH_INFO_WIDTH1)
+ gs_point width[2]; /* width for WMode 0/1 */
+#define GLYPH_INFO_BBOX 4
+ gs_rect bbox;
+#define GLYPH_INFO_NUM_PIECES 8
+ int num_pieces; /* # of pieces if composite, 0 if not */
+#define GLYPH_INFO_PIECES 16
+ gs_glyph *pieces; /* pieces are stored here: the caller must */
+ /* preset pieces if INFO_PIECES is set. */
+} gs_glyph_info_t;
+
+/* Define the "object" procedures of fonts. */
typedef struct gs_font_procs_s {
+ /* ------ Font-level procedures ------ */
+
/*
- * Define any needed procedure for initializing the composite
- * font stack in a show enumerator. This is a no-op for
- * all but composite fonts.
+ * Define any special handling of gs_definefont.
+ * We break this out so it can be different for composite fonts.
*/
-#define font_proc_init_fstack(proc)\
- int proc(P2(gs_show_enum *, gs_font *))
- font_proc_init_fstack((*init_fstack));
+#define font_proc_define_font(proc)\
+ int proc(P2(gs_font_dir *, gs_font *))
+ font_proc_define_font((*define_font));
/*
- * Define the font's algorithm for getting the next character from
- * a string being shown. This is trivial, except for composite fonts.
- * Returns 0 if the current (base) font didn't change,
- * 1 if it did change, 2 if there are no more characters,
- * or an error code.
- *
- * This procedure is OBSOLETE as of release 4.61, superseded by
- * next_glyph; however, we have to continue supporting it for
- * backward compatibility.
+ * Define any special handling of gs_makefont.
+ * We break this out so it can be different for composite fonts.
*/
-#define font_proc_next_char(proc)\
- int proc(P2(gs_show_enum *, gs_char *))
- font_proc_next_char((*next_char));
+#define font_proc_make_font(proc)\
+ int proc(P4(gs_font_dir *, const gs_font *, const gs_matrix *, gs_font **))
+ font_proc_make_font((*make_font));
+
+ /*
+ * Get information about the font, as specified by the members mask.
+ * Disregard the FontMatrix: scale the font as indicated by *pscale
+ * (pscale=NULL means no scaling). Set info->members to the members
+ * that are actually returned. Note that some member options require
+ * the caller to preset some of the elements of info. Note also that
+ * this procedure may return more information than was requested.
+ */
+
+#define font_proc_font_info(proc)\
+ int proc(P4(gs_font *font, const gs_point *pscale, int members,\
+ gs_font_info_t *info))
+ font_proc_font_info((*font_info));
- /* A client-supplied character encoding procedure. */
+ /* ------ Glyph-level procedures ------ */
+
+ /* Map a character code to a glyph. Some PostScript fonts use both
+ * names and indices to identify glyphs: for example, in PostScript Type
+ * 42 fonts, the Encoding array maps character codes to glyph names, and
+ * the CharStrings dictionary maps glyph names to glyph indices. In
+ * such fonts, the glyph_space argument determines which type of glyph
+ * is returned.
+ */
#define font_proc_encode_char(proc)\
- gs_glyph proc(P3(gs_show_enum *, gs_font *, gs_char *))
+ gs_glyph proc(P3(gs_font *, gs_char, gs_glyph_space_t))
font_proc_encode_char((*encode_char));
/*
- * A client-supplied BuildChar/BuildGlyph procedure.
- * The gs_char may be gs_no_char (for BuildGlyph), or the gs_glyph
- * may be gs_no_glyph (for BuildChar), but not both.
+ * Get the next glyph in an enumeration of all glyphs defined by the
+ * font. index = 0 means return the first one; a returned index of 0
+ * means the enumeration is finished. The glyphs are enumerated in
+ * an unpredictable order.
*/
-#define font_proc_build_char(proc)\
- int proc(P5(gs_show_enum *, gs_state *, gs_font *, gs_char, gs_glyph))
- font_proc_build_char((*build_char));
+#define font_proc_enumerate_glyph(proc)\
+ int proc(P4(gs_font *font, int *pindex, gs_glyph_space_t glyph_space,\
+ gs_glyph *pglyph))
+ font_proc_enumerate_glyph((*enumerate_glyph));
- /* Callback procedures for external font rasterizers */
- /* (see gsccode.h for details.) */
+ /*
+ * Get information about a glyph, as specified by the members mask.
+ * pmat = NULL means get the scalable values; non-NULL pmat means get
+ * the scaled values. Set info->members to the members that are
+ * actually returned. Return gs_error_undefined if the glyph doesn't
+ * exist in the font; calling glyph_info with members = 0 is an
+ * efficient way to find out whether a given glyph exists. Note that
+ * some member options require the caller to preset some of the elements
+ * of info. Note also that this procedure may return more information
+ * than was requested.
+ */
- gx_xfont_callbacks callbacks;
- /*gs_proc_glyph_name((*glyph_name)); */
+#define font_proc_glyph_info(proc)\
+ int proc(P5(gs_font *font, gs_glyph glyph, const gs_matrix *pmat,\
+ int members, gs_glyph_info_t *info))
+ font_proc_glyph_info((*glyph_info));
/*
- * Define any special handling of gs_definefont.
- * We break this out so it can be different for composite fonts.
+ * Append the outline for a glyph to a path, with the glyph origin
+ * at the current point. pmat is as for glyph_width. The outline
+ * does include a final moveto for the advance width.
*/
-#define font_proc_define_font(proc)\
- int proc(P2(gs_font_dir *, gs_font *))
- font_proc_define_font((*define_font));
+#define font_proc_glyph_outline(proc)\
+ int proc(P4(gs_font *font, gs_glyph glyph, const gs_matrix *pmat,\
+ gx_path *ppath))
+ font_proc_glyph_outline((*glyph_outline));
+
+ /* ------ Glyph rendering procedures ------ */
/*
- * Define any special handling of gs_makefont.
- * We break this out so it can be different for composite fonts.
+ * Define any needed procedure for initializing the composite
+ * font stack in a show enumerator. This is a no-op for
+ * all but composite fonts.
*/
-#define font_proc_make_font(proc)\
- int proc(P4(gs_font_dir *, const gs_font *, const gs_matrix *,\
- gs_font **))
- font_proc_make_font((*make_font));
+#define font_proc_init_fstack(proc)\
+ int proc(P2(gs_text_enum_t *, gs_font *))
+ font_proc_init_fstack((*init_fstack));
/*
- * Define the font's algorithm for getting the next character or
- * glyph from a string being shown. We only use this if the
- * next_char procedure is 0 (for backward compatibility).
+ * Define the font's algorithm for getting the next character or glyph
+ * from a string being shown. This is trivial, except for composite
+ * fonts. Returns 0 if the current (base) font didn't change, 1 if it
+ * did change, 2 if there are no more characters, or an error code.
+ *
+ * This procedure may set either *pchar to gs_no_char or *pglyph to
+ * gs_no_glyph, but not both.
+ */
+
+#define font_proc_next_char_glyph(proc)\
+ int proc(P3(gs_text_enum_t *pte, gs_char *pchar, gs_glyph *pglyph))
+ font_proc_next_char_glyph((*next_char_glyph));
+
+ /*
+ * A client-supplied BuildChar/BuildGlyph procedure.
+ * The gs_char may be gs_no_char (for BuildGlyph), or the gs_glyph
+ * may be gs_no_glyph (for BuildChar), but not both.
*/
-#define font_proc_next_glyph(proc)\
- int proc(P3(gs_show_enum *, gs_char *, gs_glyph *))
- font_proc_next_glyph((*next_glyph));
+#define font_proc_build_char(proc)\
+ int proc(P5(gs_text_enum_t *, gs_state *, gs_font *, gs_char, gs_glyph))
+ font_proc_build_char((*build_char));
+
+ /* Callback procedures for external font rasterizers */
+ /* (see gsccode.h for details.) */
+
+ gx_xfont_callbacks callbacks;
} gs_font_procs;
-/* Default font procedures */
-font_proc_init_fstack(gs_default_init_fstack);
-font_proc_next_char(gs_default_next_char);
-font_proc_encode_char(gs_no_encode_char);
-font_proc_build_char(gs_no_build_char);
+/* Default font-level font procedures in gsfont.c */
font_proc_define_font(gs_no_define_font);
font_proc_make_font(gs_no_make_font);
font_proc_make_font(gs_base_make_font);
-font_proc_next_glyph(gs_default_next_glyph);
+font_proc_font_info(gs_default_font_info);
+/* Default glyph-level font procedures in gsfont.c */
+font_proc_encode_char(gs_no_encode_char);
+font_proc_enumerate_glyph(gs_no_enumerate_glyph);
+font_proc_glyph_info(gs_default_glyph_info);
+font_proc_glyph_outline(gs_no_glyph_outline);
+/* Default glyph rendering procedures in gstext.c */
+font_proc_init_fstack(gs_default_init_fstack);
+font_proc_next_char_glyph(gs_default_next_char_glyph);
+font_proc_build_char(gs_no_build_char);
+/* Default procedure vector in gsfont.c */
+extern const gs_font_procs gs_font_procs_default;
-/* The font names are only needed for xfont lookup. */
+/* The font names are only needed for xfont lookup and high-level output. */
typedef struct gs_font_name_s {
#define gs_font_name_max 47 /* must be >= 40 */
/* The +1 is so we can null-terminate for debugging printout. */
@@ -155,6 +285,8 @@ typedef struct gs_font_name_s {
/* scaled font cache */\
gs_memory_t *memory; /* allocator for this font */\
gs_font_dir *dir; /* directory where registered */\
+ gs_notify_list_t notify_list; /* clients to notify when freeing */\
+ gs_id id; /* internal ID (no relation to UID) */\
gs_font *base; /* original (unscaled) base font */\
void *client_data; /* additional client data */\
gs_matrix FontMatrix;\
@@ -170,39 +302,56 @@ typedef struct gs_font_name_s {
/* We store both the FontDirectory key (key_name) and, */\
/* if present, the FontName (font_name). */\
gs_font_name key_name, font_name
- /*typedef struct gs_font_s gs_font; *//* in gsfont.h and other places */
+/*typedef struct gs_font_s gs_font; *//* in gsfont.h and other places */
struct gs_font_s {
gs_font_common;
};
extern_st(st_gs_font); /* (abstract) */
-struct_proc_finalize(gs_font_finalize); /* public for concrete subclasses */
+struct_proc_finalize(gs_font_finalize); /* public for concrete subclasses */
#define public_st_gs_font() /* in gsfont.c */\
gs_public_st_complex_only(st_gs_font, gs_font, "gs_font",\
0, font_enum_ptrs, font_reloc_ptrs, gs_font_finalize)
-#define st_gs_font_max_ptrs 5
+#define st_gs_font_max_ptrs (st_gs_notify_list_max_ptrs + 5)
+
#define private_st_gs_font_ptr() /* in gsfont.c */\
gs_private_st_ptr(st_gs_font_ptr, gs_font *, "gs_font *",\
font_ptr_enum_ptrs, font_ptr_reloc_ptrs)
#define st_gs_font_ptr_max_ptrs 1
+
extern_st(st_gs_font_ptr_element);
#define public_st_gs_font_ptr_element() /* in gsfont.c */\
gs_public_st_element(st_gs_font_ptr_element, gs_font *, "gs_font *[]",\
font_ptr_element_enum_ptrs, font_ptr_element_reloc_ptrs, st_gs_font_ptr)
+/* Allocate and minimally initialize a font. */
+/* Does not set: FontMatrix, FontType, key_name, font_name. */
+gs_font *
+ gs_font_alloc(P5(gs_memory_t *mem, gs_memory_type_ptr_t pstype,
+ const gs_font_procs *procs, gs_font_dir *dir,
+ client_name_t cname));
+
+/*
+ * Register/unregister a client for notification by a font. Currently
+ * the clients are only notified when a font is freed. Note that any
+ * such client must unregister itself when *it* is freed.
+ */
+int gs_font_notify_register(P3(gs_font *font, gs_notify_proc_t proc,
+ void *proc_data));
+int gs_font_notify_unregister(P3(gs_font *font, gs_notify_proc_t proc,
+ void *proc_data));
+
/* Define a base (not composite) font. */
#define gs_font_base_common\
gs_font_common;\
gs_rect FontBBox;\
gs_uid UID;\
- int encoding_index; /* 0=Std, 1=ISOLatin1, 2=Symbol, */\
- /* 3=Dingbats, -1=other */\
- int nearest_encoding_index /* (may be >= 0 even if */\
- /* encoding_index = -1) */
+ gs_encoding_index_t encoding_index;\
+ gs_encoding_index_t nearest_encoding_index /* (may be >= 0 even if */\
+ /* encoding_index = -1) */
#ifndef gs_font_base_DEFINED
# define gs_font_base_DEFINED
typedef struct gs_font_base_s gs_font_base;
-
#endif
struct gs_font_base_s {
gs_font_base_common;
@@ -215,4 +364,11 @@ extern_st(st_gs_font_base);
gs_font_finalize, st_gs_font, UID.xvalues)
#define st_gs_font_base_max_ptrs (st_gs_font_max_ptrs + 1)
+/* Allocate and minimally initialize a base font. */
+/* Does not set: same elements as gs_alloc_font. */
+gs_font_base *
+ gs_font_base_alloc(P5(gs_memory_t *mem, gs_memory_type_ptr_t pstype,
+ const gs_font_procs *procs, gs_font_dir *dir,
+ client_name_t cname));
+
#endif /* gxfont_INCLUDED */
diff --git a/gs/src/gxfont0.h b/gs/src/gxfont0.h
index d8e076655..501dcedde 100644
--- a/gs/src/gxfont0.h
+++ b/gs/src/gxfont0.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1994, 1996, 1997 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1994, 1996, 1997, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -45,7 +45,6 @@ typedef enum {
#ifndef gs_cmap_DEFINED
# define gs_cmap_DEFINED
typedef struct gs_cmap_s gs_cmap;
-
#endif
typedef struct gs_type0_data_s {
fmap_type FMapType;
@@ -72,4 +71,10 @@ extern_st(st_gs_font_type0);
gs_public_st_complex_only(st_gs_font_type0, gs_font_type0, "gs_font_type0",\
0, font_type0_enum_ptrs, font_type0_reloc_ptrs, gs_font_finalize)
+/* Define the Type 0 font procedures. */
+font_proc_define_font(gs_type0_define_font);
+font_proc_make_font(gs_type0_make_font);
+font_proc_init_fstack(gs_type0_init_fstack);
+font_proc_next_char_glyph(gs_type0_next_char_glyph);
+
#endif /* gxfont0_INCLUDED */
diff --git a/gs/src/gxfont1.h b/gs/src/gxfont1.h
index 62b983199..0382f6c91 100644
--- a/gs/src/gxfont1.h
+++ b/gs/src/gxfont1.h
@@ -72,14 +72,6 @@ typedef struct gs_type1_data_procs_s {
gs_const_string * pcdata));
/*
- * Get the next glyph in an enumeration. index = 0 means return the
- * first one; a returned index of 0 means the enumeration is finished.
- */
-
- int (*next_glyph)(P3(gs_font_type1 *pfont, int *pindex,
- gs_glyph * pglyph));
-
- /*
* Push (a) value(s) onto the client ('PostScript') stack during
* interpretation. Note that this procedure and the next one take a
* closure pointer, not the font pointer, as the first argument.
diff --git a/gs/src/gxfont42.h b/gs/src/gxfont42.h
index f04c5db6a..82878a4bf 100644
--- a/gs/src/gxfont42.h
+++ b/gs/src/gxfont42.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996, 1997, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1996, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -23,13 +23,10 @@
# define gxfont42_INCLUDED
/* This is the type-specific information for a Type 42 (TrueType) font. */
-
typedef struct gs_type42_data_s gs_type42_data;
-
#ifndef gs_font_type42_DEFINED
# define gs_font_type42_DEFINED
typedef struct gs_font_type42_s gs_font_type42;
-
#endif
struct gs_type42_data_s {
/* The following are set by the client. */
@@ -46,6 +43,7 @@ struct gs_type42_data_s {
ulong hmtx; /* offset to hmtx table */
uint hmtx_length; /* length of hmtx table */
ulong loca; /* offset to loca table */
+ uint numGlyphs; /* from size of loca */
};
struct gs_font_type42_s {
gs_font_base_common;
@@ -58,9 +56,26 @@ extern_st(st_gs_font_type42);
"gs_font_type42", font_type42_enum_ptrs, font_type42_reloc_ptrs,\
gs_font_finalize, st_gs_font_base, data.proc_data)
-/* Because a Type 42 font contains so many cached values, */
-/* we provide a procedure to initialize them from the font data. */
-/* Note that this initializes get_outline as well. */
+/*
+ * Because a Type 42 font contains so many cached values,
+ * we provide a procedure to initialize them from the font data.
+ * Note that this initializes get_outline and the font procedures as well.
+ */
int gs_type42_font_init(P1(gs_font_type42 *));
+/* Append the outline of a TrueType character to a path. */
+int gs_type42_append(P7(uint glyph_index, gs_imager_state * pis,
+ gx_path * ppath, const gs_log2_scale_point * pscale,
+ bool charpath_flag, int paint_type,
+ gs_font_type42 * pfont));
+
+/* Get the metrics of a TrueType character. */
+int gs_type42_get_metrics(P3(gs_font_type42 * pfont, uint glyph_index,
+ float psbw[4]));
+
+/* Export the font procedures so they can be called from the interpreter. */
+font_proc_enumerate_glyph(gs_type42_enumerate_glyph);
+font_proc_glyph_info(gs_type42_glyph_info);
+font_proc_glyph_outline(gs_type42_glyph_outline);
+
#endif /* gxfont42_INCLUDED */
diff --git a/gs/src/gxfunc.h b/gs/src/gxfunc.h
index 9a16cd16d..ed3c3c526 100644
--- a/gs/src/gxfunc.h
+++ b/gs/src/gxfunc.h
@@ -44,4 +44,8 @@ void fn_common_free(P3(gs_function_t * pfn, bool free_params, gs_memory_t * mem)
/* Check the values of m, n, Domain, and (if supplied) Range. */
int fn_check_mnDR(P3(const gs_function_params_t * params, int m, int n));
+/* Get the monotonicity of a function over its Domain. */
+int fn_domain_is_monotonic(P2(const gs_function_t *pfn,
+ gs_function_effort_t effort));
+
#endif /* gxfunc_INCLUDED */
diff --git a/gs/src/gxhint2.c b/gs/src/gxhint2.c
index 5665c9120..f27c4233d 100644
--- a/gs/src/gxhint2.c
+++ b/gs/src/gxhint2.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1990, 1995, 1997, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1990, 1995, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -30,7 +30,7 @@
/* Define the tolerance for testing whether a point is in a zone, */
/* in device pixels. (Maybe this should be variable?) */
-#define stem_tolerance float2fixed(0.05)
+#define STEM_TOLERANCE float2fixed(0.05)
/* Forward references */
@@ -94,14 +94,15 @@ update_stem_hints(gs_type1_state * pcis)
private void
store_stem_deltas(const stem_hint_table * psht, stem_hint * psh,
const pixel_scale * psp, fixed v, fixed dv, fixed adj_dv)
-{ /*
- * We want to align the stem so its edges fall on pixel boundaries
- * (possibly "big pixel" boundaries if we are oversampling),
- * but if hint replacement has occurred, we must shift edges in a
- * consistent way. This is a real nuisance, but I don't see how
- * to avoid it; if we don't do it, we get bizarre anomalies like
- * disappearing stems.
- */
+{
+ /*
+ * We want to align the stem so its edges fall on pixel boundaries
+ * (possibly "big pixel" boundaries if we are oversampling),
+ * but if hint replacement has occurred, we must shift edges in a
+ * consistent way. This is a real nuisance, but I don't see how
+ * to avoid it; if we don't do it, we get bizarre anomalies like
+ * disappearing stems.
+ */
const stem_hint *psh0 = 0;
const stem_hint *psh1 = 0;
int i;
@@ -150,6 +151,22 @@ store_stem_deltas(const stem_hint_table * psht, stem_hint * psh,
}
}
+/*
+ * The Type 1 font format uses negative stem widths to indicate edge hints.
+ * We need to convert these into zero-width stem hints.
+ */
+private void
+detect_edge_hint(fixed *xy, fixed *dxy)
+{
+ if (*dxy == -21) {
+ /* Bottom edge hint. */
+ *xy -= 21, *dxy = 0;
+ } else if (*dxy == -20) {
+ /* Top edge hint. */
+ *dxy = 0;
+ }
+}
+
/* Add a horizontal stem hint. */
void
type1_do_hstem(gs_type1_state * pcis, fixed y, fixed dy,
@@ -163,6 +180,7 @@ type1_do_hstem(gs_type1_state * pcis, fixed y, fixed dy,
if (!pcis->fh.use_y_hints || !pmat->txy_fixed_valid)
return;
+ detect_edge_hint(&y, &dy);
y += pcis->lsb.y + pcis->adxy.y;
if (pcis->fh.axes_swapped) {
psp = &pcis->scale.x;
@@ -240,6 +258,7 @@ type1_do_vstem(gs_type1_state * pcis, fixed x, fixed dx,
if (!pcis->fh.use_x_hints)
return;
+ detect_edge_hint(&x, &dx);
x += pcis->lsb.x + pcis->adxy.x;
if (pcis->fh.axes_swapped) {
psp = &pcis->scale.y;
@@ -322,8 +341,8 @@ type1_stem(const gs_type1_state * pcis, stem_hint_table * psht,
top--;
}
/* Add a little fuzz for insideness testing. */
- top->v0 = v0 - stem_tolerance;
- top->v1 = v0 + d + stem_tolerance;
+ top->v0 = v0 - STEM_TOLERANCE;
+ top->v1 = v0 + d + STEM_TOLERANCE;
top->index = pcis->hstem_hints.count + pcis->vstem_hints.count;
top->active = true;
psht->count++;
diff --git a/gs/src/gxht.c b/gs/src/gxht.c
index 8b458a501..a06ae3fbd 100644
--- a/gs/src/gxht.c
+++ b/gs/src/gxht.c
@@ -58,10 +58,8 @@ const gx_device_color_type_t *const gx_dc_type_ht_binary =
#define gx_dc_type_ht_binary (&gx_dc_type_data_ht_binary)
/* GC procedures */
-#define cptr ((gx_device_color *)vptr)
private
-ENUM_PTRS_BEGIN(dc_ht_binary_enum_ptrs) return 0;
-
+ENUM_PTRS_WITH(dc_ht_binary_enum_ptrs, gx_device_color *cptr) return 0;
ENUM_PTR(0, gx_device_color, colors.binary.b_ht);
case 1:
{
@@ -70,7 +68,7 @@ case 1:
ENUM_RETURN(tile - tile->index);
}
ENUM_PTRS_END
-private RELOC_PTRS_BEGIN(dc_ht_binary_reloc_ptrs)
+private RELOC_PTRS_WITH(dc_ht_binary_reloc_ptrs, gx_device_color *cptr)
{
uint index = cptr->colors.binary.b_tile->index;
diff --git a/gs/src/gxi12bit.c b/gs/src/gxi12bit.c
index 9388b6a8e..9420609a7 100644
--- a/gs/src/gxi12bit.c
+++ b/gs/src/gxi12bit.c
@@ -97,6 +97,9 @@ const sample_unpack_proc_t sample_unpack_12_proc = sample_unpack_12;
/* ------ Strategy procedure ------ */
+/* Check the prototype. */
+iclass_proc(gs_image_class_2_fracs);
+
/* Use special (slow) logic for 12-bit source values. */
private irender_proc(image_render_frac);
irender_proc_t
@@ -201,6 +204,8 @@ image_render_frac(gx_image_enum * penum, const byte * buffer, int data_x,
penum->y, w, fixed2float(xl), fixed2float(ytf));
memset(&run, 0, sizeof(run));
memset(&next, 0, sizeof(next));
+ /* Ensure that we don't get any false dev_color_eq hits. */
+ color_set_pure(&devc1, gx_no_color_index);
cs_full_init_color(&cc, pcs);
run.v[0] = ~psrc[0]; /* force remap */
diff --git a/gs/src/gxicolor.c b/gs/src/gxicolor.c
index 295051f98..a1ca0bb35 100644
--- a/gs/src/gxicolor.c
+++ b/gs/src/gxicolor.c
@@ -48,6 +48,9 @@ typedef union {
/* ------ Strategy procedure ------ */
+/* Check the prototype. */
+iclass_proc(gs_image_class_4_color);
+
private irender_proc(image_render_color);
irender_proc_t
gs_image_class_4_color(gx_image_enum * penum)
diff --git a/gs/src/gxifast.c b/gs/src/gxifast.c
index 3b04fc583..504b45a49 100644
--- a/gs/src/gxifast.c
+++ b/gs/src/gxifast.c
@@ -46,6 +46,9 @@
/* ------ Strategy procedure ------ */
+/* Check the prototype. */
+iclass_proc(gs_image_class_1_simple);
+
/* Use special fast logic for portrait or landscape black-and-white images. */
private irender_proc(image_render_skip);
private irender_proc(image_render_simple);
@@ -168,6 +171,9 @@ gs_image_class_1_simple(gx_image_enum * penum)
/* ------ Rendering procedures ------ */
+#define DC_IS_NULL(pdc)\
+ (gx_dc_is_pure(pdc) && (pdc)->colors.pure == gx_no_color_index)
+
/* Skip over a completely transparent image. */
private int
image_render_skip(gx_image_enum * penum, const byte * buffer, int data_x,
@@ -496,9 +502,6 @@ copy_portrait(gx_image_enum * penum, const byte * data, int dx, int raster,
const gx_device_color *pdc;
bool invert;
-#define DC_IS_NULL(pdc)\
- (gx_dc_is_pure(pdc) && (pdc)->colors.pure == gx_no_color_index)
-
if (DC_IS_NULL(pdc1)) {
pdc = pdc0;
invert = true;
@@ -513,9 +516,6 @@ copy_portrait(gx_image_enum * penum, const byte * data, int dx, int raster,
pdc = pdc1;
invert = false;
}
-
-#undef DC_IS_NULL
-
return (*pdc->type->fill_masked)
(pdc, data, dx, raster, gx_no_bitmap_id, x, y, w, h,
dev, lop_default, invert);
@@ -538,12 +538,19 @@ image_render_simple(gx_image_enum * penum, const byte * buffer, int data_x,
int ix = fixed2int_pixround(xcur);
int ixr;
const int iy = penum->yci, ih = penum->hci;
- const gx_device_color * const pdc0 = &penum->icolor0;
- const gx_device_color * const pdc1 = &penum->icolor1;
+ gx_device_color * const pdc0 = &penum->icolor0;
+ gx_device_color * const pdc1 = &penum->icolor1;
int dy;
+ int code;
if (h == 0)
return 0;
+ if ((!DC_IS_NULL(pdc0) &&
+ (code = gx_color_load(pdc0, penum->pis, dev)) < 0) ||
+ (!DC_IS_NULL(pdc1) &&
+ (code = gx_color_load(pdc1, penum->pis, dev)) < 0)
+ )
+ return code;
if (penum->line == 0) { /* A direct BitBlt is possible. */
line = buffer;
line_size = (w + 7) >> 3;
diff --git a/gs/src/gximage3.c b/gs/src/gximage3.c
index 93a5d7c14..b75a6ac91 100644
--- a/gs/src/gximage3.c
+++ b/gs/src/gximage3.c
@@ -88,9 +88,10 @@ typedef struct gx_image3_enum_s {
int pixel_y;
} gx_image3_enum_t;
-gs_private_st_ptrs6(st_image3_enum, gx_image3_enum_t, "gx_image3_enum_t",
- image3_enum_enum_ptrs, image3_enum_reloc_ptrs,
- mdev, pcdev, pixel_info, mask_info, pixel_data, mask_data);
+extern_st(st_gx_image_enum_common);
+gs_private_st_suffix_add6(st_image3_enum, gx_image3_enum_t, "gx_image3_enum_t",
+ image3_enum_enum_ptrs, image3_enum_reloc_ptrs, st_gx_image_enum_common,
+ mdev, pcdev, pixel_info, mask_info, pixel_data, mask_data);
/* Begin an ImageType 3 image. */
private bool check_image3_extent(P2(floatp mask_coeff, floatp data_coeff));
@@ -265,7 +266,7 @@ gx_begin_image3(gx_device * dev,
bits.id = gx_no_bitmap_id;
code = gx_mask_clip_initialize(pcdev, &gs_mask_clip_device,
(const gx_bitmap *)&bits, dev,
- origin.x, origin.y);
+ origin.x, origin.y, mem);
if (code < 0)
goto out4;
pcdev->tiles = bits;
@@ -351,6 +352,8 @@ gx_begin_image3(gx_device * dev,
(penum->num_planes - 1) * sizeof(penum->plane_depths[0]));
break;
}
+ gx_device_retain((gx_device *)mdev, true); /* will free explicitly */
+ gx_device_retain((gx_device *)pcdev, true); /* ditto */
*pinfo = (gx_image_enum_common_t *) penum;
return 0;
out6:gx_image_end(penum->mask_info, false);
diff --git a/gs/src/gximono.c b/gs/src/gximono.c
index 6ccae20bc..17b4b1c62 100644
--- a/gs/src/gximono.c
+++ b/gs/src/gximono.c
@@ -40,6 +40,9 @@
/* ------ Strategy procedure ------ */
+/* Check the prototype. */
+iclass_proc(gs_image_class_3_mono);
+
private irender_proc(image_render_mono);
irender_proc_t
gs_image_class_3_mono(gx_image_enum * penum)
diff --git a/gs/src/gxiodev.h b/gs/src/gxiodev.h
index bd5799c19..7ef1c606f 100644
--- a/gs/src/gxiodev.h
+++ b/gs/src/gxiodev.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1994, 1996, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1993, 1994, 1996, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -30,30 +30,30 @@
* Second Edition, for more information.
*/
-typedef struct gx_io_device_s gx_io_device; /* defined here */
-typedef struct gx_io_device_procs_s gx_io_device_procs; /* defined here */
+#ifndef gx_io_device_DEFINED
+# define gx_io_device_DEFINED
+typedef struct gx_io_device_s gx_io_device;
+#endif
+typedef struct gx_io_device_procs_s gx_io_device_procs; /* defined here */
-/* The IODevice table is defined in gconfig.c; its extern is in gscdefs.h. */
+/* The IODevice table is defined in gconf.c; its extern is in gscdefs.h. */
#ifndef file_enum_DEFINED /* also defined in gp.h */
# define file_enum_DEFINED
struct file_enum_s; /* opaque to client, defined by implementors */
typedef struct file_enum_s file_enum;
-
#endif
/* Define an opaque type for parameter lists. */
#ifndef gs_param_list_DEFINED
# define gs_param_list_DEFINED
typedef struct gs_param_list_s gs_param_list;
-
#endif
/* Define an opaque type for streams. */
#ifndef stream_DEFINED
# define stream_DEFINED
typedef struct stream_s stream;
-
#endif
/* Definition of IODevice procedures */
@@ -172,7 +172,7 @@ int gs_fopen_errno_to_code(P1(int));
/* Finally, the IODevice structure itself. */
struct gx_io_device_s {
const char *dname; /* the IODevice name */
- const char *dtype; /* the type returned by c'devparams */
+ const char *dtype; /* the type returned by currentdevparams */
gx_io_device_procs procs;
void *state; /* (if the IODevice has state) */
};
diff --git a/gs/src/gxipixel.c b/gs/src/gxipixel.c
index b9bad8ba0..cc9690d4c 100644
--- a/gs/src/gxipixel.c
+++ b/gs/src/gxipixel.c
@@ -53,9 +53,8 @@ private const gx_image_enum_procs_t image1_enum_procs = {
};
/* GC procedures */
-#define eptr ((gx_image_enum *)vptr)
private
-ENUM_PTRS_BEGIN(image_enum_enum_ptrs)
+ENUM_PTRS_WITH(image_enum_enum_ptrs, gx_image_enum *eptr)
{
int bps;
gs_ptr_type_t ret;
@@ -82,7 +81,7 @@ ENUM_PTRS_BEGIN(image_enum_enum_ptrs)
gx_image_enum_do_ptrs(e1)
#undef e1
ENUM_PTRS_END
-private RELOC_PTRS_BEGIN(image_enum_reloc_ptrs)
+private RELOC_PTRS_WITH(image_enum_reloc_ptrs, gx_image_enum *eptr)
{
int i;
@@ -102,7 +101,6 @@ private RELOC_PTRS_BEGIN(image_enum_reloc_ptrs)
}
}
RELOC_PTRS_END
-#undef eptr
/* Forward declarations */
private int color_draws_b_w(P2(gx_device * dev,
@@ -570,8 +568,8 @@ gx_image_enum_begin(gx_device * dev, const gs_imager_state * pis,
}
if (penum->clip_image && pcpath) { /* Set up the clipping device. */
gx_device_clip *cdev =
- gs_alloc_struct(mem, gx_device_clip,
- &st_device_clip, "image clipper");
+ gs_alloc_struct(mem, gx_device_clip,
+ &st_device_clip, "image clipper");
if (cdev == 0) {
gx_default_end_image(dev,
@@ -579,7 +577,8 @@ gx_image_enum_begin(gx_device * dev, const gs_imager_state * pis,
false);
return_error(gs_error_VMerror);
}
- gx_make_clip_device(cdev, cdev, gx_cpath_list(pcpath));
+ gx_make_clip_translate_device(cdev, gx_cpath_list(pcpath), 0, 0, mem);
+ gx_device_retain((gx_device *)cdev, true); /* will free explicitly */
gx_device_set_target((gx_device_forward *)cdev, dev);
(*dev_proc(cdev, open_device)) ((gx_device *) cdev);
penum->clip_dev = cdev;
diff --git a/gs/src/gxiscale.c b/gs/src/gxiscale.c
index 76be0041c..9311eacd5 100644
--- a/gs/src/gxiscale.c
+++ b/gs/src/gxiscale.c
@@ -48,6 +48,9 @@
/* ------ Strategy procedure ------ */
+/* Check the prototype. */
+iclass_proc(gs_image_class_0_interpolate);
+
/* If we're interpolating, use special logic. */
private irender_proc(image_render_interpolate);
irender_proc_t
@@ -62,6 +65,7 @@ gs_image_class_0_interpolate(gx_image_enum * penum)
const gs_color_space *pcs = penum->pcs;
const gs_color_space *pccs;
gs_point dst_xy;
+ uint in_size;
if (!penum->interpolate || penum->use_mask_color)
return 0;
@@ -80,7 +84,7 @@ gs_image_class_0_interpolate(gx_image_enum * penum)
* If we use Adobe's spatial interpolation approach, we don't need
* to do this.
*/
-#ifdef USE_MITCHELL_FILTER
+#ifdef USE_MITCHELL_FILTERX
if (penum->bps < 4 || penum->bps * penum->spp < 8 ||
(fabs(penum->matrix.xx) <= 5 && fabs(penum->matrix.yy <= 5))
) {
@@ -91,13 +95,6 @@ gs_image_class_0_interpolate(gx_image_enum * penum)
/* Non-ANSI compilers require the following casts: */
gs_distance_transform((float)penum->rect.w, (float)penum->rect.h,
&penum->matrix, &dst_xy);
- if (penum->bps <= 8 && penum->device_color) {
- iss.BitsPerComponentIn = 8;
- iss.MaxValueIn = 0xff;
- } else {
- iss.BitsPerComponentIn = sizeof(frac) * 8;
- iss.MaxValueIn = frac_1;
- }
iss.BitsPerComponentOut = sizeof(frac) * 8;
iss.MaxValueOut = frac_1;
iss.WidthOut = (int)ceil(fabs(dst_xy.x));
@@ -106,16 +103,24 @@ gs_image_class_0_interpolate(gx_image_enum * penum)
iss.HeightIn = penum->rect.h;
pccs = cs_concrete_space(pcs, pis);
iss.Colors = cs_num_components(pccs);
+ if (penum->bps <= 8 && penum->device_color) {
+ iss.BitsPerComponentIn = 8;
+ iss.MaxValueIn = 0xff;
+ in_size = 0;
+ } else {
+ iss.BitsPerComponentIn = sizeof(frac) * 8;
+ iss.MaxValueIn = frac_1;
+ in_size = round_up(iss.WidthIn * iss.Colors * sizeof(frac),
+ align_bitmap_mod);
+ }
/* Allocate a buffer for one source/destination line. */
{
- uint in_size =
- iss.WidthIn * iss.Colors * (iss.BitsPerComponentIn / 8);
uint out_size =
- iss.WidthOut * iss.Colors *
- max(iss.BitsPerComponentOut / 8, sizeof(gx_color_index));
+ iss.WidthOut * max(iss.Colors * (iss.BitsPerComponentOut / 8),
+ sizeof(gx_color_index));
- line = gs_alloc_bytes(mem, max(in_size, out_size),
- "image scale src line");
+ line = gs_alloc_bytes(mem, in_size + out_size,
+ "image scale src+dst line");
}
#ifdef USE_MITCHELL_FILTER
template = &s_IScale_template;
@@ -129,7 +134,7 @@ gs_image_class_0_interpolate(gx_image_enum * penum)
(*pss->template->init) ((stream_state *) pss) < 0)
) {
gs_free_object(mem, pss, "image scale state");
- gs_free_object(mem, line, "image scale src line");
+ gs_free_object(mem, line, "image scale src+dst line");
/* Try again without interpolation. */
penum->interpolate = false;
return 0;
@@ -163,6 +168,7 @@ image_render_interpolate(gx_image_enum * penum, const byte * buffer,
int c = pss->params.Colors;
stream_cursor_read r;
stream_cursor_write w;
+ byte *out = penum->line;
if (h != 0) {
/* Convert the unpacked data to concrete values in */
@@ -184,6 +190,7 @@ image_render_interpolate(gx_image_enum * penum, const byte * buffer,
int i;
r.ptr = (byte *) psrc - 1;
+ if_debug0('B', "[B]Concrete row:\n[B]");
for (i = 0; i < pss->params.WidthIn; i++, psrc += c) {
int j;
@@ -195,7 +202,18 @@ image_render_interpolate(gx_image_enum * penum, const byte * buffer,
decode_frac(*(const frac *)pdata, cc, j);
}
(*pcs->type->concretize_color) (&cc, pcs, psrc, pis);
+#ifdef DEBUG
+ if (gs_debug_c('B')) {
+ int ci;
+
+ for (ci = 0; ci < c; ++ci)
+ dprintf2("%c%04x", (ci == 0 ? ' ' : ','), psrc[ci]);
+ }
+#endif
}
+ out += round_up(pss->params.WidthIn * c * sizeof(frac),
+ align_bitmap_mod);
+ if_debug0('B', "\n");
}
r.limit = r.ptr + row_size;
} else /* h == 0 */
@@ -227,12 +245,11 @@ image_render_interpolate(gx_image_enum * penum, const byte * buffer,
gx_device_color devc;
int code;
- DECLARE_LINE_ACCUM_COPY(penum->line, bpp, xo);
+ DECLARE_LINE_ACCUM_COPY(out, bpp, xo);
- w.limit = penum->line + width * c *
- sizeof(gx_color_index) - 1;
- w.ptr = w.limit - width * c *
- (sizeof(gx_color_index) - sizeofPixelOut);
+ w.limit = out + width *
+ max(c * sizeofPixelOut, sizeof(gx_color_index)) - 1;
+ w.ptr = w.limit - width * c * sizeofPixelOut;
psrc = (const frac *)(w.ptr + 1);
code = (*pss->template->process)
((stream_state *) pss, &r, &w, h == 0);
@@ -241,7 +258,18 @@ image_render_interpolate(gx_image_enum * penum, const byte * buffer,
if (w.ptr == w.limit) {
int xe = xo + width;
+ if_debug1('B', "[B]Interpolated row %d:\n[B]",
+ penum->line_xy);
for (x = xo; x < xe;) {
+#ifdef DEBUG
+ if (gs_debug_c('B')) {
+ int ci;
+
+ for (ci = 0; ci < c; ++ci)
+ dprintf2("%c%04x", (ci == 0 ? ' ' : ','),
+ psrc[ci]);
+ }
+#endif
code = (*pconcs->type->remap_concrete_color)
(psrc, &devc, pis, dev, gs_color_select_source);
if (code < 0)
@@ -265,8 +293,7 @@ image_render_interpolate(gx_image_enum * penum, const byte * buffer,
} else {
int rcode;
- LINE_ACCUM_COPY(dev, penum->line, bpp,
- xo, x, raster, ry);
+ LINE_ACCUM_COPY(dev, out, bpp, xo, x, raster, ry);
rcode = gx_fill_rectangle_device_rop(x, ry,
1, 1, &devc, dev, lop);
if (rcode < 0)
@@ -276,9 +303,9 @@ image_render_interpolate(gx_image_enum * penum, const byte * buffer,
x++, psrc += c;
}
}
- LINE_ACCUM_COPY(dev, penum->line, bpp,
- xo, x, raster, ry);
+ LINE_ACCUM_COPY(dev, out, bpp, xo, x, raster, ry);
penum->line_xy++;
+ if_debug0('B', "\n");
}
if ((code == 0 && r.ptr == r.limit) || code == EOFC)
break;
diff --git a/gs/src/gxline.h b/gs/src/gxline.h
index e9c7aa678..03add165c 100644
--- a/gs/src/gxline.h
+++ b/gs/src/gxline.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995, 1996, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1995, 1996, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -45,10 +45,11 @@ typedef struct gx_line_params_s {
float half_width; /* one-half line width */
gs_line_cap cap;
gs_line_join join;
+ int curve_join; /* <0 means use join between segments of */
+ /* flattened curves, >=0 means use this join */
float miter_limit;
float miter_check; /* computed from miter limit, */
- /* see gx_set_miter_limit and */
- /* gs_stroke */
+ /* see gx_set_miter_limit and gs_stroke */
float dot_length;
bool dot_length_absolute; /* if true, dot_length is 1/72" units */
gs_matrix dot_orientation; /* dot length is aligned with (1,0); */
@@ -72,7 +73,8 @@ int gx_set_dot_length(P3(gx_line_params *, floatp, bool));
/* See gsline.c for the computation of miter_check. */
#define gx_line_params_initial\
- 0.0, gs_cap_butt, gs_join_miter, 10.0, 0.20305866, 0.0, 0/*false*/,\
+ 0.0, gs_cap_butt, gs_join_miter, gs_join_bevel /* for Adobe compatibility */,\
+ 10.0, 0.20305866, 0.0, 0/*false*/,\
{ identity_matrix_body }, { gx_dash_params_initial }
#endif /* gxline_INCLUDED */
diff --git a/gs/src/gxmatrix.h b/gs/src/gxmatrix.h
index 2df3c9931..a9df9fdca 100644
--- a/gs/src/gxmatrix.h
+++ b/gs/src/gxmatrix.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1989, 1995, 1996, 1997 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1989, 1995, 1996, 1997, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -37,6 +37,9 @@ typedef struct gs_matrix_fixed_s {
bool txy_fixed_valid;
} gs_matrix_fixed;
+/* Make a gs_matrix_fixed from a gs_matrix. */
+int gs_matrix_fixed_from_matrix(P2(gs_matrix_fixed *, const gs_matrix *));
+
/* Coordinate transformations to fixed point. */
int gs_point_transform2fixed(P4(const gs_matrix_fixed *, floatp, floatp,
gs_fixed_point *));
diff --git a/gs/src/gxmclip.c b/gs/src/gxmclip.c
index 8da49e98c..19db3ef48 100644
--- a/gs/src/gxmclip.c
+++ b/gs/src/gxmclip.c
@@ -27,9 +27,7 @@
public_st_device_mask_clip();
/* GC procedures */
-#define mcdev ((gx_device_mask_clip *)vptr)
-
-private ENUM_PTRS_BEGIN(device_mask_clip_enum_ptrs)
+private ENUM_PTRS_WITH(device_mask_clip_enum_ptrs, gx_device_mask_clip *mcdev)
{
if (index < st_gx_strip_bitmap_max_ptrs) {
return ENUM_USING(st_gx_strip_bitmap, &mcdev->tiles,
@@ -43,8 +41,7 @@ private ENUM_PTRS_BEGIN(device_mask_clip_enum_ptrs)
ENUM_PREFIX(st_device_forward, st_device_memory_max_ptrs);
}
ENUM_PTRS_END
-
-private RELOC_PTRS_BEGIN(device_mask_clip_reloc_ptrs)
+private RELOC_PTRS_WITH(device_mask_clip_reloc_ptrs, gx_device_mask_clip *mcdev)
{
RELOC_PREFIX(st_device_forward);
RELOC_USING(st_gx_strip_bitmap, &mcdev->tiles, sizeof(mcdev->tiles));
@@ -66,21 +63,19 @@ private RELOC_PTRS_BEGIN(device_mask_clip_reloc_ptrs)
}
RELOC_PTRS_END
-#undef mcdev
-
/* Initialize a mask clipping device. */
int
gx_mask_clip_initialize(gx_device_mask_clip * cdev,
const gx_device_mask_clip * proto,
const gx_bitmap * bits, gx_device * tdev,
- int tx, int ty)
+ int tx, int ty, gs_memory_t *mem)
{
int buffer_width = bits->size.x;
int buffer_height =
tile_clip_buffer_size / (bits->raster + sizeof(byte *));
gx_device_init((gx_device *)cdev, (const gx_device *)proto,
- NULL, true);
+ mem, true);
cdev->width = tdev->width;
cdev->height = tdev->height;
cdev->color_info = tdev->color_info;
diff --git a/gs/src/gxmclip.h b/gs/src/gxmclip.h
index 7959fb2c9..bec415002 100644
--- a/gs/src/gxmclip.h
+++ b/gs/src/gxmclip.h
@@ -64,10 +64,10 @@ extern_st(st_device_mask_clip);
* We supply an explicit device space origin or phase.
* Note that this procedure does not set cdev->tiles.
*/
-int gx_mask_clip_initialize(P6(gx_device_mask_clip * cdev,
+int gx_mask_clip_initialize(P7(gx_device_mask_clip * cdev,
const gx_device_mask_clip * proto,
const gx_bitmap * bits, gx_device * tdev,
- int tx, int ty));
+ int tx, int ty, gs_memory_t *mem));
/*
* Prepare colors for a copy_mono operation.
diff --git a/gs/src/gxobj.h b/gs/src/gxobj.h
index 9c1758d8d..cdffca6a2 100644
--- a/gs/src/gxobj.h
+++ b/gs/src/gxobj.h
@@ -27,19 +27,13 @@
/* ================ Objects ================ */
/*
- * Object headers come in a number of different varieties.
- * All arise from the same basic form, which is
- -l- -lmsize/mark/back-
- -size-
- -type/reloc-
- * l (large) is a single bit. The size of lmsize/mark/back, size, and type
- * varies according to the environment. On machines with N:16 segmented
- * addressing, 16-bit ints, and no alignment requirement more severe than
- * 2 bytes, we can fit an object header into 8 bytes by making the first
- * two fields only 16 bits wide. On all other machines, we let the
- * lmsize/mark/back field be 1 bit shorter than a uint, and round the header
- * size up to the next multiple of the most severe alignment restriction
- * (4 or 8 bytes). Miraculously, we can do all this without any case testing.
+ * Object headers have the form:
+ -l- -mark/back-
+ -size-
+ -type/reloc-
+ * l (aLone) is a single bit. Mark/back is 1 bit shorter than a uint. We
+ * round the header size up to the next multiple of the most severe
+ * alignment restriction (4 or 8 bytes).
*
* The mark/back field is used for the mark during the marking phase of
* garbage collection, and for a back pointer value during the compaction
@@ -51,12 +45,6 @@
* we use 1...10 in the mark field (o_untraced).
* Note that neither of these values is a possible real relocation value.
*
- * The lmsize field of large objects overlaps mark and back, so we must
- * handle these functions for large objects in some other way.
- * Since large objects cannot be moved or relocated, we don't need the
- * back field for them; we allocate 2 bits for the 3 mark values.
- */
-/*
* The back pointer's meaning depends on whether the object is
* free (unmarked) or in use (marked):
* - In free objects, the back pointer is an offset from the object
@@ -73,46 +61,26 @@
*/
#define obj_flag_bits 1
#define obj_mb_bits (arch_sizeof_int * 8 - obj_flag_bits)
-#define obj_ls_bits (obj_mb_bits - 2)
#define o_unmarked (((uint)1 << obj_mb_bits) - 1)
-#define o_l_unmarked (o_unmarked & 3)
-#define o_set_unmarked_large(pp) (pp)->o_lmark = o_l_unmarked
#define o_set_unmarked(pp)\
- BEGIN\
- if ((pp)->o_large) o_set_unmarked_large(pp);\
- else (pp)->o_smark = o_unmarked;\
- END
-#define o_is_unmarked_large(pp) ((pp)->o_lmark == o_l_unmarked)
+ ((pp)->o_smark = o_unmarked)
#define o_is_unmarked(pp)\
- ((pp)->o_large ? o_is_unmarked_large(pp) :\
- ((pp)->o_smark == o_unmarked))
+ ((pp)->o_smark == o_unmarked)
#define o_untraced (((uint)1 << obj_mb_bits) - 2)
-#define o_l_untraced (o_untraced & 3)
#define o_set_untraced(pp)\
- BEGIN\
- if ((pp)->o_large) (pp)->o_lmark = o_l_untraced;\
- else (pp)->o_smark = o_untraced;\
- END
+ ((pp)->o_smark = o_untraced)
#define o_is_untraced(pp)\
- ((pp)->o_large ? (pp)->o_lmark == o_l_untraced :\
- ((pp)->o_smark == o_untraced))
+ ((pp)->o_smark == o_untraced)
#define o_marked 0
-#define o_mark_large(pp) (pp)->o_lmark = o_marked
#define o_mark(pp)\
- BEGIN\
- if ((pp)->o_large) o_mark_large(pp);\
- else (pp)->o_smark = o_marked;\
- END
+ ((pp)->o_smark = o_marked)
#define obj_back_shift obj_flag_bits
#define obj_back_scale (1 << obj_back_shift)
typedef struct obj_header_data_s {
union _f {
struct _h {
- unsigned large:1;
+ unsigned alone:1;
} h;
- struct _l {
- unsigned _:1, lmark:2, lsize:obj_ls_bits;
- } l;
struct _m {
unsigned _:1, smark:obj_mb_bits;
} m;
@@ -165,9 +133,7 @@ struct obj_header_s { /* must be a struct because of forward reference */
};
/* Define some reasonable abbreviations for the fields. */
-#define o_large d.o.f.h.large
-#define o_lsize d.o.f.l.lsize
-#define o_lmark d.o.f.l.lmark
+#define o_alone d.o.f.h.alone
#define o_back d.o.f.b.back
#define o_smark d.o.f.m.smark
#define o_size d.o.size
@@ -178,34 +144,8 @@ struct obj_header_s { /* must be a struct because of forward reference */
* The macros for getting the sizes of objects all take pointers to
* the object header, for use when scanning storage linearly.
*/
-#define pre_obj_small_size(pp)\
- ((pp)->o_size)
-
-#if arch_sizeof_long > arch_sizeof_int
-
- /* Large objects need to use o_lsize. */
-
-#define pre_obj_large_size(pp)\
- (((ulong)(pp)->o_lsize << (arch_sizeof_int * 8)) + (pp)->o_size)
-#define pre_obj_set_large_size(pp, lsize)\
- ((pp)->o_lsize = (lsize) >> (arch_sizeof_int * 8),\
- (pp)->o_size = (uint)(lsize))
-#define pre_obj_contents_size(pp)\
- ((pp)->o_large ? pre_obj_large_size(pp) : pre_obj_small_size(pp))
-
-#else
-
- /* Large objects don't need to use o_lsize. */
-
-#define pre_obj_large_size(pp)\
- pre_obj_small_size(pp)
-#define pre_obj_set_large_size(pp, lsize)\
- ((pp)->o_lsize = 0,\
- (pp)->o_size = (lsize))
#define pre_obj_contents_size(pp)\
- pre_obj_small_size(pp)
-
-#endif
+ ((pp)->o_size)
#define pre_obj_rounded_size(pp)\
obj_size_round(pre_obj_contents_size(pp))
diff --git a/gs/src/gxp1fill.c b/gs/src/gxp1fill.c
index b417064f0..22a6bcc21 100644
--- a/gs/src/gxp1fill.c
+++ b/gs/src/gxp1fill.c
@@ -30,7 +30,7 @@
#include "gxdevmem.h"
#include "gxclip2.h"
#include "gxpcolor.h"
-#include "gxp1fill.h"
+#include "gxp1impl.h"
/* Define the state for tile filling. */
typedef struct tile_fill_state_s {
@@ -90,7 +90,7 @@ tile_fill_init(tile_fill_state_t * ptfs, const gx_device_color * pdevc,
m_tile->tmask.rep_height);
} else
px = py = 0;
- return tile_clip_initialize(&ptfs->cdev, ptfs->tmask, dev, px, py);
+ return tile_clip_initialize(&ptfs->cdev, ptfs->tmask, dev, px, py, NULL);
}
/*
diff --git a/gs/src/gxp1fill.h b/gs/src/gxp1impl.h
index e41a2bf65..8b664f068 100644
--- a/gs/src/gxp1fill.h
+++ b/gs/src/gxp1impl.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -17,12 +17,14 @@
*/
-/* PatternType 1 filling algorithm interface */
+/* PatternType 1 implementation interface */
+/* Requires gxpcolor.h */
-#ifndef gxp1fill_INCLUDED
-# define gxp1fill_INCLUDED
+#ifndef gxp1impl_INCLUDED
+# define gxp1impl_INCLUDED
/*
+ * Declare the filling algorithms implemented in gxp1fill.c.
* We use 'masked_fill_rect' instead of 'masked_fill_rectangle'
* in order to limit identifier lengths to 32 characters.
*/
@@ -31,4 +33,11 @@ dev_color_proc_fill_rectangle(gx_dc_pure_masked_fill_rect);
dev_color_proc_fill_rectangle(gx_dc_binary_masked_fill_rect);
dev_color_proc_fill_rectangle(gx_dc_colored_masked_fill_rect);
-#endif /* gxp1fill_INCLUDED */
+/*
+ * Declare the Pattern color mapping procedures exported by gxpcmap.c.
+ */
+int gx_pattern_load(P4(gx_device_color *, const gs_imager_state *,
+ gx_device *, gs_color_select_t));
+pattern_proc_remap_color(gs_pattern1_remap_color);
+
+#endif /* gxp1impl_INCLUDED */
diff --git a/gs/src/gxpaint.c b/gs/src/gxpaint.c
index b659778ae..a5a85873b 100644
--- a/gs/src/gxpaint.c
+++ b/gs/src/gxpaint.c
@@ -77,11 +77,11 @@ gx_stroke_add(gx_path * ppath, gx_path * to_path,
int
gx_imager_stroke_add(gx_path *ppath, gx_path *to_path,
- const gs_imager_state *pis)
+ gx_device *dev, const gs_imager_state *pis)
{
gx_stroke_params params;
params.flatness = pis->flatness;
- return gx_stroke_path_only(ppath, to_path, (gx_device *)0, pis,
+ return gx_stroke_path_only(ppath, to_path, dev, pis,
&params, NULL, NULL);
}
diff --git a/gs/src/gxpaint.h b/gs/src/gxpaint.h
index 47d5a6990..8cd467e99 100644
--- a/gs/src/gxpaint.h
+++ b/gs/src/gxpaint.h
@@ -53,8 +53,12 @@ int gx_fill_path(P6(gx_path * ppath, gx_device_color * pdevc, gs_state * pgs,
int rule, fixed adjust_x, fixed adjust_y));
int gx_stroke_fill(P2(gx_path * ppath, gs_state * pgs));
int gx_stroke_add(P3(gx_path *ppath, gx_path *to_path, const gs_state * pgs));
-int gx_imager_stroke_add(P3(gx_path *ppath, gx_path *to_path,
- const gs_imager_state *pis));
+/*
+ * gx_imager_stroke_add needs a device for the sake of absolute-length
+ * dots (and for no other reason).
+ */
+int gx_imager_stroke_add(P4(gx_path *ppath, gx_path *to_path,
+ gx_device *dev, const gs_imager_state *pis));
/* ------ Imager procedures ------ */
@@ -106,7 +110,6 @@ struct gx_fill_params_s {
#ifndef gx_stroke_params_DEFINED
# define gx_stroke_params_DEFINED
typedef struct gx_stroke_params_s gx_stroke_params;
-
#endif
struct gx_stroke_params_s {
float flatness;
diff --git a/gs/src/gxpath.c b/gs/src/gxpath.c
index 0ab418c99..b8b962277 100644
--- a/gs/src/gxpath.c
+++ b/gs/src/gxpath.c
@@ -657,6 +657,14 @@ gx_path_add_char_path(gx_path * to_path, gx_path * from_path,
default: /* shouldn't happen! */
gx_path_new(from_path);
return 0;
+ case cpm_charwidth: {
+ gs_fixed_point cpt;
+
+ code = gx_path_current_point(from_path, &cpt);
+ if (code < 0)
+ break;
+ return gx_path_add_point(to_path, cpt.x, cpt.y);
+ }
case cpm_true_charpath:
case cpm_false_charpath:
return gx_path_add_path(to_path, from_path);
diff --git a/gs/src/gxpath2.c b/gs/src/gxpath2.c
index 8c101be34..00283d9f6 100644
--- a/gs/src/gxpath2.c
+++ b/gs/src/gxpath2.c
@@ -21,6 +21,7 @@
#include "math_.h"
#include "gx.h"
#include "gserrors.h"
+#include "gspath.h" /* for gs_path_enum_alloc prototype */
#include "gsstruct.h"
#include "gxfixed.h"
#include "gxarith.h"
@@ -81,7 +82,8 @@ gx_path_bbox(gx_path * ppath, gs_fixed_rect * pbox)
}
/* The stored bounding box may not be up to date. */
/* Correct it now if necessary. */
- if (ppath->box_last == ppath->current_subpath->last) { /* Box is up to date */
+ if (ppath->box_last == ppath->current_subpath->last) {
+ /* Box is up to date */
*pbox = ppath->bbox;
} else {
fixed px, py, qx, qy;
@@ -306,9 +308,9 @@ gx_path_scale_exp2_shared(gx_path * ppath, int log2_scale_x, int log2_scale_y,
* Reverse a path. We know ppath != ppath_old.
* NOTE: in releases 5.01 and earlier, the implicit line added by closepath
* became the first segment of the reversed path. Starting in release
- * 5.02, the code follows the Adobe implementation, in which this line
- * becomes the *last* segment of the reversed path. This can produce some
- * quite counter-intuitive results.
+ * 5.02, the code follows the Adobe implementation (and LanguageLevel 3
+ * specification), in which this line becomes the *last* segment of the
+ * reversed path. This can produce some quite unintuitive results.
*/
int
gx_path_copy_reversed(const gx_path * ppath_old, gx_path * ppath)
@@ -323,8 +325,8 @@ gx_path_copy_reversed(const gx_path * ppath_old, gx_path * ppath)
const segment *pseg = psub->last;
const segment *prev;
segment_notes prev_notes =
- (pseg == (const segment *)psub ? sn_none :
- psub->next->notes);
+ (pseg == (const segment *)psub ? sn_none :
+ psub->next->notes);
segment_notes notes;
if (!psub->is_closed) {
@@ -385,9 +387,14 @@ gx_path_copy_reversed(const gx_path * ppath_old, gx_path * ppath)
/* not reached */
}
#undef sn_not_end
+ /*
+ * In the Adobe implementations, reversepath discards a trailing
+ * moveto unless the path consists only of a moveto. We reproduce
+ * this behavior here, even though we consider it a bug.
+ */
if (ppath_old->first_subpath == 0 &&
path_last_is_moveto(ppath_old)
- ) { /* The path consists only of a single moveto. */
+ ) {
int code = gx_path_add_point(ppath, ppath_old->position.x,
ppath_old->position.y);
diff --git a/gs/src/gxpcopy.c b/gs/src/gxpcopy.c
index b5bc2e82b..1cf40ef1f 100644
--- a/gs/src/gxpcopy.c
+++ b/gs/src/gxpcopy.c
@@ -113,11 +113,21 @@ gx_path_copy_reducing(const gx_path *ppath_old, gx_path *ppath,
SET_EXTENT(ex, x0, pc->p1.x, pc->p2.x, pc->pt.x);
SET_EXTENT(ey, y0, pc->p1.y, pc->p2.y, pc->pt.y);
#undef SET_EXTENT
- flat_x = fixed_mult_quo(fixed_flatness, ex,
- ex + expansion.x);
- flat_y = fixed_mult_quo(fixed_flatness, ey,
- ey + expansion.y);
- flat = min(flat_x, flat_y);
+ /*
+ * We check for the degenerate case specially
+ * to avoid a division by zero.
+ */
+ if (ex == 0 || ey == 0)
+ flat = 0;
+ else {
+ flat_x =
+ fixed_mult_quo(fixed_flatness, ex,
+ ex + expansion.x);
+ flat_y =
+ fixed_mult_quo(fixed_flatness, ey,
+ ey + expansion.y);
+ flat = min(flat_x, flat_y);
+ }
}
k = gx_curve_log2_samples(x0, y0, pc, flat);
if (options & pco_accurate) {
diff --git a/gs/src/gxshade1.c b/gs/src/gxshade1.c
index ade7f6f85..cde0f6c08 100644
--- a/gs/src/gxshade1.c
+++ b/gs/src/gxshade1.c
@@ -385,13 +385,17 @@ A_fill_region(A_fill_state_t * pfs)
for (;;) {
double t0 = fp->t0, t1 = fp->t1;
-
- if (!shade_colors2_converge(fp->cc,
- (const shading_fill_state_t *)pfs) &&
- /*
- * The colors don't converge. Is the stripe less than 1
- * pixel wide?
- */
+ float ft0, ft1;
+
+ if ((!(pfn->head.is_monotonic > 0 ||
+ (ft0 = (float)t0, ft1 = (float)t1,
+ gs_function_is_monotonic(pfn, &ft0, &ft1, EFFORT_MODERATE) > 0)) ||
+ !shade_colors2_converge(fp->cc,
+ (const shading_fill_state_t *)pfs)) &&
+ /*
+ * The function isn't monotonic, or the colors don't converge.
+ * Is the stripe less than 1 pixel wide?
+ */
pfs->length * (t1 - t0) > 1 &&
fp < &pfs->frames[countof(pfs->frames) - 1]
) {
@@ -537,26 +541,30 @@ R_fill_region(R_fill_state_t * pfs)
for (;;) {
double t0 = fp->t0, t1 = fp->t1;
+ float ft0, ft1;
- if (!shade_colors2_converge(fp->cc,
- (const shading_fill_state_t *)pfs) &&
+ if ((!(pfn->head.is_monotonic > 0 ||
+ (ft0 = (float)t0, ft1 = (float)t1,
+ gs_function_is_monotonic(pfn, &ft0, &ft1, EFFORT_MODERATE) > 0)) ||
+ !shade_colors2_converge(fp->cc,
+ (const shading_fill_state_t *)pfs)) &&
/*
- * The colors don't converge. Is the annulus less than 1 pixel
- * wide?
+ * The function isn't monotonic, or the colors don't converge.
+ * Is the annulus less than 1 pixel wide?
*/
pfs->width * (t1 - t0) > 1 &&
fp < &pfs->frames[countof(pfs->frames) - 1]
) {
- /* Subdivide the interval and recur. */
- float tm = (t0 + t1) * 0.5;
- float dm = tm * pfs->dd + psh->params.Domain[0];
-
- gs_function_evaluate(pfn, &dm, fp[1].cc[1].paint.values);
- fp[1].cc[0].paint = fp->cc[0].paint;
- fp[1].t0 = t0;
- fp[1].t1 = fp->t0 = tm;
- fp->cc[0].paint = fp[1].cc[1].paint;
- ++fp;
+ /* Subdivide the interval and recur. */
+ float tm = (t0 + t1) * 0.5;
+ float dm = tm * pfs->dd + psh->params.Domain[0];
+
+ gs_function_evaluate(pfn, &dm, fp[1].cc[1].paint.values);
+ fp[1].cc[0].paint = fp->cc[0].paint;
+ fp[1].t0 = t0;
+ fp[1].t1 = fp->t0 = tm;
+ fp->cc[0].paint = fp[1].cc[1].paint;
+ ++fp;
} else {
/* Fill the region with the color. */
int code = R_fill_annulus(pfs, &fp->cc[0], t0, t1,
diff --git a/gs/src/gxstroke.c b/gs/src/gxstroke.c
index 8746a89b6..fb30a5f0b 100644
--- a/gs/src/gxstroke.c
+++ b/gs/src/gxstroke.c
@@ -46,10 +46,10 @@
#define USE_FILL_ADJUSTMENT
#ifdef USE_FILL_ADJUSTMENT
-# define stroke_adjustment(thin, pis, xy)\
+# define STROKE_ADJUSTMENT(thin, pis, xy)\
(thin ? fixed_0 : (pis)->fill_adjust.xy)
#else
-# define stroke_adjustment(thin, pis, xy) fixed_0
+# define STROKE_ADJUSTMENT(thin, pis, xy) fixed_0
#endif
/*
@@ -86,6 +86,7 @@
* check and covers many common cases. Clients that care always have the
* option of using strokepath to get an exact result.
*/
+private float join_expansion_factor(P2(const gs_imager_state *, gs_line_join));
int
gx_stroke_path_expansion(const gs_imager_state * pis, const gx_path * ppath,
gs_fixed_point * ppt)
@@ -127,14 +128,20 @@ gx_stroke_path_expansion(const gs_imager_state * pis, const gx_path * ppath,
result = 0; /* exact result */
}
not_exact:
- if (result)
- expand *=
- (!gx_path_has_curves(ppath) && gx_path_subpath_count(ppath) <= 1 &&
- (psub == 0 || (pseg = psub->next) == 0 ||
- (pseg = pseg->next) == 0 || pseg->type == s_line_close) ? 1.0 :
- pis->line_params.join == gs_join_miter ?
- pis->line_params.miter_limit :
- pis->line_params.join == gs_join_triangle ? 2.0 : 1.0);
+ if (result) {
+ if (!gx_path_has_curves(ppath) && gx_path_subpath_count(ppath) <= 1 &&
+ (psub == 0 || (pseg = psub->next) == 0 ||
+ (pseg = pseg->next) == 0 || pseg->type == s_line_close))
+ DO_NOTHING;
+ else {
+ float factor = join_expansion_factor(pis, pis->line_params.join);
+
+ if (pis->line_params.curve_join >= 0)
+ factor = max(factor, join_expansion_factor(pis,
+ (gs_line_join)pis->line_params.curve_join));
+ expand *= factor;
+ }
+ }
/* Short-cut gs_bbox_transform. */
{
@@ -151,6 +158,15 @@ not_exact:
return result;
}
+private float
+join_expansion_factor(const gs_imager_state *pis, gs_line_join join)
+{
+ switch (join) {
+ case gs_join_miter: return pis->line_params.miter_limit;
+ case gs_join_triangle: return 2.0;
+ default: return 1.0;
+ }
+}
/*
* Structure for a partial line (passed to the drawing routine).
@@ -196,10 +212,10 @@ typedef partial_line *pl_ptr;
/* Other forward declarations */
private bool width_is_thin(P1(pl_ptr));
private void adjust_stroke(P3(pl_ptr, const gs_imager_state *, bool));
-private int line_join_points(P5(const gx_line_params * pgs_lp,
+private int line_join_points(P6(const gx_line_params * pgs_lp,
pl_ptr plp, pl_ptr nplp,
gs_fixed_point * join_points,
- const gs_matrix * pmat));
+ const gs_matrix * pmat, gs_line_join join));
private void compute_caps(P1(pl_ptr));
private int add_points(P4(gx_path *, const gs_fixed_point *,
int, bool));
@@ -221,10 +237,10 @@ gx_default_stroke_path(gx_device * dev, const gs_imager_state * pis,
/* Fill a partial stroked path. Free variables: */
/* to_path, stroke_path_body, fill_params, always_thin, pis, dev, pdevc, */
/* code, ppath, exit(label). */
-#define fill_stroke_path(thin)\
+#define FILL_STROKE_PATH(thin)\
if(to_path==&stroke_path_body && !gx_path_is_void(&stroke_path_body)) {\
- fill_params.adjust.x = stroke_adjustment(thin, pis, x);\
- fill_params.adjust.y = stroke_adjustment(thin, pis, y);\
+ fill_params.adjust.x = STROKE_ADJUSTMENT(thin, pis, x);\
+ fill_params.adjust.y = STROKE_ADJUSTMENT(thin, pis, y);\
code = gx_fill_path_only(to_path, dev, pis, &fill_params, pdevc, NULL);\
gx_path_free(&stroke_path_body, "fill_stroke_path");\
if ( code < 0 ) goto exit;\
@@ -239,9 +255,10 @@ gx_default_stroke_path(gx_device * dev, const gs_imager_state * pis,
* with an appropriate cap.
*/
#define stroke_line_proc(proc)\
- int proc(P10(gx_path *, int, pl_ptr, pl_ptr, const gx_device_color *,\
+ int proc(P11(gx_path *, int, pl_ptr, pl_ptr, const gx_device_color *,\
gx_device *, const gs_imager_state *,\
- const gx_stroke_params *, const gs_fixed_rect *, int))
+ const gx_stroke_params *, const gs_fixed_rect *, int,\
+ gs_line_join))
typedef stroke_line_proc((*stroke_line_proc_t));
private stroke_line_proc(stroke_add);
@@ -305,8 +322,22 @@ gx_stroke_path_only(gx_path * ppath, gx_path * to_path, gx_device * pdev,
(uniform = 0,
reflected = xy * yx > xx * yy,
orient_other));
+ /*
+ * Formerly, there was a hack here that only treated the joins of
+ * flattened curves specially if the dot length was non-zero.
+ * This was a surrogate to detect use of the library by PCL
+ * interpreters. We have replaced this hack with an explicit
+ * curve join parameter in the graphics state.
+ */
+#if 0
segment_notes not_first =
(!is_fzero(pis->line_params.dot_length) ? sn_not_first : sn_none);
+#else
+ const segment_notes not_first = sn_not_first;
+#endif
+ gs_line_join curve_join =
+ (pgs_lp->curve_join >= 0 ? (gs_line_join)pgs_lp->curve_join :
+ pgs_lp->join == gs_join_none ? gs_join_bevel : pgs_lp->join);
float line_width = pgs_lp->half_width; /* (*half* the line width) */
bool always_thin;
double line_width_and_scale, device_line_width_scale;
@@ -394,7 +425,7 @@ gx_stroke_path_only(gx_path * ppath, gx_path * to_path, gx_device * pdev,
* If there is a clipping path, set up a clipping device.
*/
if (pcpath) {
- gx_make_clip_device(&cdev, &cdev, gx_cpath_list(pcpath));
+ gx_make_clip_device(&cdev, gx_cpath_list(pcpath));
cdev.target = dev;
cdev.max_fill_band = dev->max_fill_band;
dev = (gx_device *) & cdev;
@@ -655,12 +686,12 @@ gx_stroke_path_only(gx_path * ppath, gx_path * to_path, gx_device * pdev,
}
}
if (index++) {
+ gs_line_join join =
+ (pseg->notes & not_first ? curve_join : pgs_lp->join);
int first;
pl_ptr lptr;
- if (pgs_lp->join == gs_join_none &&
- !(pseg->notes & not_first)
- ) {
+ if (join == gs_join_none) {
/* Fake the end of a subpath so we get */
/* caps instead of joins. */
first = 0;
@@ -672,10 +703,10 @@ gx_stroke_path_only(gx_path * ppath, gx_path * to_path, gx_device * pdev,
}
code = (*line_proc) (to_path, first, &pl_prev, lptr,
pdevc, dev, pis, params, &cbox,
- uniform);
+ uniform, join);
if (code < 0)
goto exit;
- fill_stroke_path(always_thin);
+ FILL_STROKE_PATH(always_thin);
} else
pl_first = pl;
pl_prev = pl;
@@ -683,20 +714,20 @@ gx_stroke_path_only(gx_path * ppath, gx_path * to_path, gx_device * pdev,
}
if (index) {
/* If closed, join back to start, else cap. */
+ gs_line_join join =
+ ((pseg == 0 ? (const segment *)spath->first_subpath :
+ pseg)->notes & not_first ? curve_join : pgs_lp->join);
/* For some reason, the Borland compiler requires the cast */
/* in the following statement. */
pl_ptr lptr =
- (!is_closed ||
- (pgs_lp->join == gs_join_none &&
- !((pseg == 0 ? (const segment *)spath->first_subpath :
- pseg)->notes & not_first)) ?
+ (!is_closed || join == gs_join_none ?
(pl_ptr) 0 : (pl_ptr) & pl_first);
- code = (*line_proc) (to_path, index - 1, &pl_prev, lptr,
- pdevc, dev, pis, params, &cbox, uniform);
+ code = (*line_proc) (to_path, index - 1, &pl_prev, lptr, pdevc,
+ dev, pis, params, &cbox, uniform, join);
if (code < 0)
goto exit;
- fill_stroke_path(always_thin);
+ FILL_STROKE_PATH(always_thin);
}
psub = (const subpath *)pseg;
}
@@ -772,11 +803,11 @@ adjust_stroke(pl_ptr plp, const gs_imager_state * pis, bool thin)
if (any_abs(plp->width.x) < any_abs(plp->width.y)) {
/* More horizontal stroke */
pw = &plp->width.y, pov = &plp->o.p.y, pev = &plp->e.p.y;
- adj2 = stroke_adjustment(thin, pis, y) << 1;
+ adj2 = STROKE_ADJUSTMENT(thin, pis, y) << 1;
} else {
/* More vertical stroke */
pw = &plp->width.x, pov = &plp->o.p.x, pev = &plp->e.p.x;
- adj2 = stroke_adjustment(thin, pis, x) << 1;
+ adj2 = STROKE_ADJUSTMENT(thin, pis, x) << 1;
}
/* Round the larger component of the width up or down, */
/* whichever way produces a result closer to the correct width. */
@@ -876,9 +907,9 @@ set_thin_widths(register pl_ptr plp)
/* Treat no join the same as a bevel join. */
private int
stroke_fill(gx_path * ppath, int first, register pl_ptr plp, pl_ptr nplp,
-const gx_device_color * pdevc, gx_device * dev, const gs_imager_state * pis,
- const gx_stroke_params * params, const gs_fixed_rect * pbbox,
- int uniform)
+ const gx_device_color * pdevc, gx_device * dev,
+ const gs_imager_state * pis, const gx_stroke_params * params,
+ const gs_fixed_rect * pbbox, int uniform, gs_line_join join)
{
const fixed lix = plp->o.p.x;
const fixed liy = plp->o.p.y;
@@ -918,7 +949,6 @@ const gx_device_color * pdevc, gx_device * dev, const gs_imager_state * pis,
{
const gx_line_params *pgs_lp = gs_currentlineparams_inline(pis);
gs_line_cap cap = pgs_lp->cap;
- gs_line_join join = pgs_lp->join;
if (!plp->thin && (nplp == 0 || !nplp->thin)
&& ((first != 0 && nplp != 0) || cap == gs_cap_butt
@@ -938,7 +968,7 @@ const gx_device_color * pdevc, gx_device * dev, const gs_imager_state * pis,
else
code = line_join_points(pgs_lp, plp, nplp, points + npoints,
(uniform ? (gs_matrix *) 0 :
- &ctm_only(pis)));
+ &ctm_only(pis)), join);
if (code < 0)
return code;
if (nplp != 0) {
@@ -985,15 +1015,15 @@ const gx_device_color * pdevc, gx_device * dev, const gs_imager_state * pis,
}
/* General case: construct a path for the fill algorithm. */
return stroke_add(ppath, first, plp, nplp, pdevc, dev, pis, params,
- pbbox, uniform);
+ pbbox, uniform, join);
}
/* Add a segment to the path. This handles all the complex cases. */
private int
stroke_add(gx_path * ppath, int first, pl_ptr plp, pl_ptr nplp,
-const gx_device_color * pdevc, gx_device * dev, const gs_imager_state * pis,
- const gx_stroke_params * params, const gs_fixed_rect * ignore_pbbox,
- int uniform)
+ const gx_device_color * pdevc, gx_device * dev,
+ const gs_imager_state * pis, const gx_stroke_params * params,
+ const gs_fixed_rect * ignore_pbbox, int uniform, gs_line_join join)
{
const gx_line_params *pgs_lp = gs_currentlineparams_inline(pis);
gs_fixed_point points[8];
@@ -1031,7 +1061,7 @@ const gx_device_color * pdevc, gx_device * dev, const gs_imager_state * pis,
goto done;
}
code = cap_points(pgs_lp->cap, &plp->e, points + npoints);
- } else if (pgs_lp->join == gs_join_round) {
+ } else if (join == gs_join_round) {
ASSIGN_POINT(&points[npoints], plp->e.co);
++npoints;
if ((code = add_points(ppath, points, npoints, moveto_first)) < 0)
@@ -1042,7 +1072,8 @@ const gx_device_color * pdevc, gx_device * dev, const gs_imager_state * pis,
code = cap_points(gs_cap_butt, &plp->e, points + npoints);
else /* non-round join */
code = line_join_points(pgs_lp, plp, nplp, points + npoints,
- (uniform ? (gs_matrix *) 0 : &ctm_only(pis)));
+ (uniform ? (gs_matrix *) 0 : &ctm_only(pis)),
+ join);
if (code < 0)
return code;
code = add_points(ppath, points, npoints + code, moveto_first);
@@ -1075,10 +1106,9 @@ add_points(gx_path * ppath, const gs_fixed_point * points, int npoints,
/* the miter check. */
private int
line_join_points(const gx_line_params * pgs_lp, pl_ptr plp, pl_ptr nplp,
- gs_fixed_point * join_points, const gs_matrix * pmat)
+ gs_fixed_point * join_points, const gs_matrix * pmat,
+ gs_line_join join)
{
- gs_line_join join = pgs_lp->join;
-
#define jp1 join_points[0]
#define np1 join_points[1]
#define np2 join_points[2]
@@ -1336,8 +1366,7 @@ add_round_cap(gx_path * ppath, const_ep_ptr endp)
/* Compute the points for a non-round cap. */
/* Return the number of points. */
private int
-cap_points(gs_line_cap type, const_ep_ptr endp,
- gs_fixed_point * pts /* [3] */ )
+cap_points(gs_line_cap type, const_ep_ptr endp, gs_fixed_point *pts /*[3]*/)
{
#define PUT_POINT(i, px, py)\
pts[i].x = (px), pts[i].y = (py)
diff --git a/gs/src/gxtext.h b/gs/src/gxtext.h
index 997dd317e..ba26578a9 100644
--- a/gs/src/gxtext.h
+++ b/gs/src/gxtext.h
@@ -23,6 +23,12 @@
# define gxtext_INCLUDED
#include "gstext.h"
+#include "gsrefct.h"
+
+/*
+ * WARNING: The APIs and structures in this file are UNSTABLE.
+ * Do not try to use them.
+ */
/* Define the abstract type for the object procedures. */
typedef struct gs_text_enum_procs_s gs_text_enum_procs_t;
@@ -33,15 +39,44 @@ typedef struct gs_text_enum_procs_s gs_text_enum_procs_t;
typedef struct gs_text_returned_s {
gs_char current_char; /* INTERVENE */
gs_glyph current_glyph; /* INTERVENE */
- gs_point current_width; /* INTERVENE & RETURN_WIDTH */
gs_point total_width; /* RETURN_WIDTH */
} gs_text_returned_t;
+
+/*
+ * Define the stack for composite fonts.
+ * If the current font is not composite, depth = -1.
+ * If the current font is composite, 0 <= depth <= MAX_FONT_STACK.
+ * items[0] through items[depth] are occupied.
+ * items[0].font is the root font; items[0].index = 0.
+ * The root font must be composite, but may be of any map type.
+ * items[0..N-1] are modal composite fonts, for some N <= depth.
+ * items[N..depth-1] are non-modal composite fonts.
+ * items[depth] is a base (non-composite) font.
+ * Note that if depth >= 0, the font member of the graphics state
+ * for a base font BuildChar/Glyph is the same as items[depth].font.
+ */
+#define MAX_FONT_STACK 5
+typedef struct gx_font_stack_item_s {
+ gs_font *font; /* font at this level */
+ uint index; /* index of this font in parent's Encoding */
+} gx_font_stack_item_t;
+typedef struct gx_font_stack_s {
+ int depth;
+ gx_font_stack_item_t items[1 + MAX_FONT_STACK];
+} gx_font_stack_t;
+
/*
* Define the common part of the structure that tracks the state of text
* processing. All implementations of text_begin must allocate one of these
* using rc_alloc_struct_1; implementations may subclass and extend it.
* Note that it includes a copy of the text parameters.
+ *
+ * The freeing procedure (rc.free) must call rc_free_text_enum, which
+ * calls the enumerator's release procedure. This is required in order to
+ * properly decrement the reference count(s) of the referenced structures
+ * (in the common part of the structure, only the device).
*/
+rc_free_proc(rc_free_text_enum);
#define gs_text_enum_common\
/*\
* The following copies of the arguments of text_begin are set at\
@@ -50,18 +85,23 @@ typedef struct gs_text_returned_s {
gs_text_params_t text; /* must be first for subclassing */\
gx_device *dev;\
gs_imager_state *pis;\
- const gs_font *orig_font;\
+ gs_font *orig_font;\
gx_path *path; /* unless DO_NONE & !RETURN_WIDTH */\
const gx_device_color *pdcolor; /* if DO_DRAW */\
const gx_clip_path *pcpath; /* if DO_DRAW */\
gs_memory_t *memory;\
/* The following additional members are set at initialization. */\
const gs_text_enum_procs_t *procs;\
- /* The following change dynamically. */\
+ /* The following change dynamically. NOTE: gs_text_enum_copy_dynamic */\
+ /* knows the entire list of dynamically changing elements. */\
rc_header rc;\
- const gs_font *current_font; /* changes for composite fonts */\
- gs_log2_scale_point scale; /* for oversampling */\
- uint index; /* index within string */\
+ gs_font *current_font; /* changes for composite fonts */\
+ gs_log2_scale_point log2_scale; /* for oversampling */\
+ uint index; /* index within string */\
+ uint xy_index; /* index within X/Y widths */\
+ gx_font_stack_t fstack;\
+ int cmap_code; /* hack for FMapType 9 composite fonts, */\
+ /* the value returned by decode_next */\
/* The following are used to return information to the client. */\
gs_text_returned_t returned
/* The typedef is in gstext.h. */
@@ -69,20 +109,62 @@ typedef struct gs_text_returned_s {
gs_text_enum_common;
} /*gs_text_enum_t*/;
-#define st_gs_text_enum_max_ptrs st_gs_text_params_max_ptrs
+#define st_gs_text_enum_max_ptrs (st_gs_text_params_max_ptrs + 7)
/*extern_st(st_gs_text_enum); */
#define public_st_gs_text_enum() /* in gstext.c */\
gs_public_st_composite(st_gs_text_enum, gs_text_enum_t, "gs_text_enum_t",\
text_enum_enum_ptrs, text_enum_reloc_ptrs)
+/*
+ * Initialize a newly created text enumerator. Implementations of
+ * text_begin must call this just after allocating the enumerator.
+ * Note that this procedure can return an error, e.g., if attempting
+ * a glyph-based operation with a composite font.
+ */
+int gs_text_enum_init(P10(gs_text_enum_t *pte,
+ const gs_text_enum_procs_t *procs,
+ gx_device *dev, gs_imager_state *pis,
+ const gs_text_params_t *text,
+ gs_font *font, gx_path *path,
+ const gx_device_color *pdcolor,
+ const gx_clip_path *pcpath,
+ gs_memory_t *mem));
+
/*
- * Define the control parameter for setting text metrics.
+ * Copy the dynamically changing elements from one enumerator to another.
+ * This is useful primarily for enumerators that sometimes pass the
+ * operation to a subsidiary enumerator. Note that `returned' is copied
+ * iff for_return is true.
*/
-typedef enum {
- TEXT_SET_CHAR_WIDTH,
- TEXT_SET_CACHE_DEVICE,
- TEXT_SET_CACHE_DEVICE2
-} gs_text_cache_control_t;
+void gs_text_enum_copy_dynamic(P3(gs_text_enum_t *pto,
+ const gs_text_enum_t *pfrom,
+ bool for_return));
+
+/*
+ * Define some convenience macros for testing aspects of a text
+ * enumerator.
+ */
+
+#define SHOW_IS(penum, op_mask)\
+ (((penum)->text.operation & (op_mask)) != 0)
+#define SHOW_IS_ALL_OF(penum, op_mask)\
+ (((penum)->text.operation & (op_mask)) == (op_mask))
+ /*
+ * The comments next to the following macros indicate the
+ * corresponding test on gs_show_enum structures in pre-5.24 filesets.
+ */
+#define SHOW_IS_ADD_TO_ALL(penum) /* add */\
+ SHOW_IS(penum, TEXT_ADD_TO_ALL_WIDTHS)
+#define SHOW_IS_ADD_TO_SPACE(penum) /* wchr != no_char */\
+ SHOW_IS(penum, TEXT_ADD_TO_SPACE_WIDTH)
+#define SHOW_IS_DO_KERN(penum) /* do_kern */\
+ SHOW_IS(penum, TEXT_INTERVENE)
+#define SHOW_IS_SLOW(penum) /* slow_show */\
+ SHOW_IS(penum, TEXT_REPLACE_WIDTHS | TEXT_ADD_TO_ALL_WIDTHS | TEXT_ADD_TO_SPACE_WIDTH | TEXT_INTERVENE)
+#define SHOW_IS_DRAWING(penum) /* !stringwidth_flag */\
+ !SHOW_IS(penum, TEXT_DO_NONE)
+#define SHOW_IS_STRINGWIDTH(penum) /* stringwidth_flag > 0 */\
+ SHOW_IS_ALL_OF(penum, TEXT_DO_NONE | TEXT_RETURN_WIDTH)
/*
* Define the procedures associated with text processing.
@@ -90,26 +172,84 @@ typedef enum {
struct gs_text_enum_procs_s {
/*
+ * Resync processing from an enumerator that may have different
+ * parameters and may be partway through processing the string. Note
+ * that this may only be implemented for certain kinds of changes, and
+ * will fail for other kinds. (We may reconsider this.) We require
+ * pfrom != pte.
+ */
+
+#define text_enum_proc_resync(proc)\
+ int proc(P2(gs_text_enum_t *pte, const gs_text_enum_t *pfrom))
+
+ text_enum_proc_resync((*resync));
+
+ /*
* Process the text. Then client should call this repeatedly until
- * it returns <= 0. (> 0 means the client must intervene.)
+ * it returns <= 0. (> 0 means the client must take action: see
+ * gstext.h.)
*/
#define text_enum_proc_process(proc)\
- int proc(P1(gs_text_enum_t *penum))
+ int proc(P1(gs_text_enum_t *pte))
text_enum_proc_process((*process));
/*
+ * After the implementation returned TEXT_PROCESS_RENDER, determine
+ * whether it needs the entire character description, or only the width
+ * (escapement).
+ */
+
+#define text_enum_proc_is_width_only(proc)\
+ int proc(P1(const gs_text_enum_t *pte))
+
+ text_enum_proc_is_width_only((*is_width_only));
+
+ /*
+ * Return the width of the current character (in user space coordinates).
+ */
+
+#define text_enum_proc_current_width(proc)\
+ int proc(P2(const gs_text_enum_t *pte, gs_point *pwidth))
+
+ text_enum_proc_current_width((*current_width));
+
+ /*
* Set the character width and optionally the bounding box,
* and optionally enable caching.
*/
#define text_enum_proc_set_cache(proc)\
- int proc(P3(gs_text_enum_t *penum, const double *values,\
+ int proc(P3(gs_text_enum_t *pte, const double *values,\
gs_text_cache_control_t control))
text_enum_proc_set_cache((*set_cache));
+ /*
+ * Prepare to retry processing the current character by uninstalling the
+ * cache device.
+ */
+
+#define text_enum_proc_retry(proc)\
+ int proc(P1(gs_text_enum_t *pte))
+
+ text_enum_proc_retry((*retry));
+
+ /*
+ * Release the contents of the structure at the end of processing,
+ * but don't free the structure itself. (gs_text_release also does
+ * the latter.)
+ */
+
+#define text_enum_proc_release(proc)\
+ void proc(P2(gs_text_enum_t *pte, client_name_t cname))
+
+ text_enum_proc_release((*release));
+
};
+/* Define the default release procedure. */
+text_enum_proc_release(gx_default_text_release);
+
#endif /* gxtext_INCLUDED */
diff --git a/gs/src/gxtype1.c b/gs/src/gxtype1.c
index 6c1d61ac9..1fe6de4fb 100644
--- a/gs/src/gxtype1.c
+++ b/gs/src/gxtype1.c
@@ -89,9 +89,8 @@ gs_type1_decrypt(byte * dest, const byte * src, uint len, crypt_state * pstate)
/* Define the structure type for a Type 1 interpreter state. */
public_st_gs_type1_state();
/* GC procedures */
-#define pcis ((gs_type1_state *)vptr)
private
-ENUM_PTRS_BEGIN(gs_type1_state_enum_ptrs)
+ENUM_PTRS_WITH(gs_type1_state_enum_ptrs, gs_type1_state *pcis)
{
if (index < pcis->ips_count + 4) {
ENUM_RETURN_CONST_STRING_PTR(gs_type1_state,
@@ -102,7 +101,7 @@ ENUM_PTRS_BEGIN(gs_type1_state_enum_ptrs)
ENUM_PTR3(0, gs_type1_state, pfont, pis, path);
ENUM_PTR(3, gs_type1_state, callback_data);
ENUM_PTRS_END
-private RELOC_PTRS_BEGIN(gs_type1_state_reloc_ptrs)
+private RELOC_PTRS_WITH(gs_type1_state_reloc_ptrs, gs_type1_state *pcis)
{
int i;
@@ -118,7 +117,6 @@ private RELOC_PTRS_BEGIN(gs_type1_state_reloc_ptrs)
ipsp->ip = ipsp->char_string.data + diff;
}
} RELOC_PTRS_END
-#undef pcis
/* ------ Interpreter services ------ */
@@ -421,8 +419,9 @@ gs_type1_endchar(gs_type1_state * pcis)
pcis->asb_diff = pcis->save_asb;
pcis->adxy = pcis->save_adxy;
/*
- * We're going to add in the lsb of the accented character when
- * we encounter its [h]sbw, so don't do it now.
+ * We're going to add in the lsb of the base character / accented
+ * character (*not* the lsb of the accent) when we encounter the
+ * [h]sbw of the accent, so ignore the lsb for now.
*/
accum_xy(pcis->adxy.x, pcis->adxy.y);
ppath->position.x = pcis->position.x = ptx;
diff --git a/gs/src/gxxfont.h b/gs/src/gxxfont.h
index 27f2e0f3f..cf6c80d60 100644
--- a/gs/src/gxxfont.h
+++ b/gs/src/gxxfont.h
@@ -99,11 +99,11 @@ struct gx_xfont_procs_s {
gs_memory_t *mem))
xfont_proc_lookup_font((*lookup_font));
- /* Convert a character name to an xglyph code. */
- /* encoding_index is 0 for StandardEncoding, */
- /* 1 for ISOLatin1Encoding, 2 for SymbolEncoding, */
- /* and -1 for any other encoding. Either chr or glyph */
- /* may be absent (gs_no_char/glyph), but not both. */
+ /*
+ * Convert a character name to an xglyph code. encoding_index is
+ * actually a gs_encoding_index_t. Either chr or glyph may be absent
+ * (gs_no_char/glyph), but not both.
+ */
/* OBSOLETE as of release 3.43, but still supported. */
#define xfont_proc_char_xglyph(proc)\
@@ -156,11 +156,11 @@ struct gx_xfont_procs_s {
* to its device:
*/
#define gs__st_dev_ptrs1(scope_st, stname, stype, sname, penum, preloc, de)\
- private ENUM_PTRS_BEGIN(penum) return 0;\
- case 0: ENUM_RETURN(gx_device_enum_ptr((gx_device *)(((stype *)vptr)->de)));\
+ private ENUM_PTRS_WITH(penum, stype *xfptr) return 0;\
+ case 0: ENUM_RETURN(gx_device_enum_ptr((gx_device *)(xfptr->de)));\
ENUM_PTRS_END\
- private RELOC_PTRS_BEGIN(preloc) ;\
- ((stype *)vptr)->de = (void *)gx_device_reloc_ptr((gx_device *)(((stype *)vptr)->de), gcst);\
+ private RELOC_PTRS_WITH(preloc, stype *xfptr) ;\
+ xfptr->de = (void *)gx_device_reloc_ptr((gx_device *)(xfptr->de), gcst);\
RELOC_PTRS_END\
gs__st_composite_only(scope_st, stname, stype, sname, penum, preloc)
/*
diff --git a/gs/src/gzstate.h b/gs/src/gzstate.h
index 30a7474fc..63031c8b8 100644
--- a/gs/src/gzstate.h
+++ b/gs/src/gzstate.h
@@ -105,7 +105,7 @@ struct gs_state_s {
gs_matrix_fixed char_tm; /* font matrix * ctm */
#define char_tm_only(pgs) *(gs_matrix *)&(pgs)->char_tm
bool char_tm_valid; /* true if char_tm is valid */
- gs_in_cache_device_t in_cachedevice; /* (see gschar.h) */
+ gs_in_cache_device_t in_cachedevice; /* (see gscpm.h) */
gs_char_path_mode in_charpath; /* (see gscpm.h) */
gs_state *show_gstate; /* gstate when show was invoked */
/* (so charpath can append to path) */
@@ -124,8 +124,8 @@ struct gs_state_s {
gs_state_client_procs client_procs;
};
-#define private_st_gs_state() /* in gsstate.c */\
- gs_private_st_composite(st_gs_state, gs_state, "gs_state",\
+#define public_st_gs_state() /* in gsstate.c */\
+ gs_public_st_composite(st_gs_state, gs_state, "gs_state",\
gs_state_enum_ptrs, gs_state_reloc_ptrs)
#endif /* gzstate_INCLUDED */
diff --git a/gs/src/ialloc.c b/gs/src/ialloc.c
index 6063967d5..e75055463 100644
--- a/gs/src/ialloc.c
+++ b/gs/src/ialloc.c
@@ -34,7 +34,6 @@
* Define global and local instances.
*/
public_st_gs_dual_memory();
-gs_dual_memory_t gs_imemory;
/* Initialize the allocator */
void
@@ -42,11 +41,19 @@ ialloc_init(gs_dual_memory_t *dmem, gs_raw_memory_t * rmem, uint chunk_size,
bool level2)
{
gs_ref_memory_t *ilmem = ialloc_alloc_state(rmem, chunk_size);
- gs_ref_memory_t *igmem =
- (level2 ? ialloc_alloc_state(rmem, chunk_size) : ilmem);
+ gs_ref_memory_t *ilmem_stable = ialloc_alloc_state(rmem, chunk_size);
+ gs_ref_memory_t *igmem;
+ gs_ref_memory_t *igmem_stable;
gs_ref_memory_t *ismem = ialloc_alloc_state(rmem, chunk_size);
int i;
+ ilmem->stable_memory = (gs_memory_t *)ilmem_stable;
+ if (level2) {
+ igmem = ialloc_alloc_state(rmem, chunk_size);
+ igmem_stable = ialloc_alloc_state(rmem, chunk_size);
+ igmem->stable_memory = (gs_memory_t *)igmem_stable;
+ } else
+ igmem = ilmem, igmem_stable = ilmem_stable;
for (i = 0; i < countof(dmem->spaces_indexed); i++)
dmem->spaces_indexed[i] = 0;
dmem->space_local = ilmem;
@@ -54,11 +61,11 @@ ialloc_init(gs_dual_memory_t *dmem, gs_raw_memory_t * rmem, uint chunk_size,
dmem->space_system = ismem;
dmem->spaces.vm_reclaim = gs_gc_reclaim; /* real GC */
dmem->reclaim = 0; /* no interpreter GC yet */
- dmem->reclaim_data = 0;
/* Level 1 systems have only local VM. */
igmem->space = avm_global;
+ igmem_stable->space = avm_global;
ilmem->space = avm_local; /* overrides if ilmem == igmem */
- igmem->global = ilmem->global = igmem;
+ ilmem_stable->space = avm_local; /* ditto */
ismem->space = avm_system;
ialloc_set_space(dmem, avm_global);
}
@@ -67,7 +74,7 @@ ialloc_init(gs_dual_memory_t *dmem, gs_raw_memory_t * rmem, uint chunk_size,
/* Get the space attribute of an allocator */
uint
-imemory_space(gs_ref_memory_t * iimem)
+imemory_space(const gs_ref_memory_t * iimem)
{
return iimem->space;
}
@@ -82,6 +89,21 @@ ialloc_set_space(gs_dual_memory_t * dmem, uint space)
dmem->current_space = mem->space;
}
+/* Get the l_new attribute of a current allocator. */
+/* (A copy of the new_mask in the gs_dual_memory_t.) */
+uint
+imemory_new_mask(const gs_ref_memory_t *imem)
+{
+ return imem->new_mask;
+}
+
+/* Get the save level of an allocator. */
+int
+imemory_save_level(const gs_ref_memory_t *imem)
+{
+ return imem->save_level;
+}
+
/* Reset the requests. */
void
ialloc_reset_requested(gs_dual_memory_t * dmem)
@@ -93,6 +115,14 @@ ialloc_reset_requested(gs_dual_memory_t * dmem)
/* ================ Refs ================ */
+#ifdef DEBUG
+private int
+ialloc_trace_space(const gs_ref_memory_t *imem)
+{
+ return imem->space + (imem->stable_memory == (gs_memory_t *)imem);
+}
+#endif
+
/* Register a ref root. */
int
gs_register_ref_root(gs_memory_t *mem, gs_gc_root_t *root,
@@ -125,8 +155,9 @@ gs_alloc_ref_array(gs_ref_memory_t * mem, ref * parr, uint attrs,
ref *end;
obj = (ref *) mem->cc.rtop - 1; /* back up over last ref */
- if_debug4('A', "[a%d:+$ ]%s(%u) = 0x%lx\n", mem->space,
- client_name_string(cname), num_refs, (ulong) obj);
+ if_debug4('A', "[a%d:+$ ]%s(%u) = 0x%lx\n",
+ ialloc_trace_space(mem), client_name_string(cname),
+ num_refs, (ulong) obj);
mem->cc.rcur[-1].o_size += num_refs * sizeof(ref);
end = (ref *) (mem->cc.rtop = mem->cc.cbot +=
num_refs * sizeof(ref));
@@ -191,14 +222,16 @@ gs_resize_ref_array(gs_ref_memory_t * mem, ref * parr,
ref *end = (ref *) (mem->cc.cbot = mem->cc.rtop -=
diff * sizeof(ref));
- if_debug4('A', "[a%d:<$ ]%s(%u) 0x%lx\n", mem->space,
- client_name_string(cname), diff, (ulong) obj);
+ if_debug4('A', "[a%d:<$ ]%s(%u) 0x%lx\n",
+ ialloc_trace_space(mem), client_name_string(cname), diff,
+ (ulong) obj);
mem->cc.rcur[-1].o_size -= diff * sizeof(ref);
make_mark(end - 1);
} else {
/* Punt. */
- if_debug4('A', "[a%d:<$#]%s(%u) 0x%lx\n", mem->space,
- client_name_string(cname), diff, (ulong) obj);
+ if_debug4('A', "[a%d:<$#]%s(%u) 0x%lx\n",
+ ialloc_trace_space(mem), client_name_string(cname), diff,
+ (ulong) obj);
mem->lost.refs += diff * sizeof(ref);
}
r_set_size(parr, new_num_refs);
@@ -232,7 +265,7 @@ gs_free_ref_array(gs_ref_memory_t * mem, ref * parr, client_name_t cname)
} else {
/* Deallocate it at the end of the refs object. */
if_debug4('A', "[a%d:-$ ]%s(%u) 0x%lx\n",
- mem->space, client_name_string(cname),
+ ialloc_trace_space(mem), client_name_string(cname),
num_refs, (ulong) obj);
mem->cc.rcur[-1].o_size -= num_refs * sizeof(ref);
mem->cc.rtop = mem->cc.cbot = (byte *) (obj + 1);
@@ -253,7 +286,7 @@ gs_free_ref_array(gs_ref_memory_t * mem, ref * parr, client_name_t cname)
) {
/* Free the chunk. */
if_debug4('a', "[a%d:-$L]%s(%u) 0x%lx\n",
- mem->space, client_name_string(cname),
+ ialloc_trace_space(mem), client_name_string(cname),
num_refs, (ulong) obj);
alloc_free_chunk(cl.cp, mem);
return;
@@ -261,8 +294,9 @@ gs_free_ref_array(gs_ref_memory_t * mem, ref * parr, client_name_t cname)
}
/* Punt, but fill the array with nulls so that there won't be */
/* dangling references to confuse the garbage collector. */
- if_debug4('A', "[a%d:-$#]%s(%u) 0x%lx\n", mem->space,
- client_name_string(cname), num_refs, (ulong) obj);
+ if_debug4('A', "[a%d:-$#]%s(%u) 0x%lx\n",
+ ialloc_trace_space(mem), client_name_string(cname), num_refs,
+ (ulong) obj);
{
uint size;
@@ -271,15 +305,15 @@ gs_free_ref_array(gs_ref_memory_t * mem, ref * parr, client_name_t cname)
size = num_refs * sizeof(ref_packed);
break;
case t_mixedarray:{
- /* We have to parse the array to compute the storage size. */
- uint i = 0;
- const ref_packed *p = parr->value.packed;
-
- for (; i < num_refs; ++i)
- p = packed_next(p);
- size = (const byte *)p - (const byte *)parr->value.packed;
- break;
- }
+ /* We have to parse the array to compute the storage size. */
+ uint i = 0;
+ const ref_packed *p = parr->value.packed;
+
+ for (; i < num_refs; ++i)
+ p = packed_next(p);
+ size = (const byte *)p - (const byte *)parr->value.packed;
+ break;
+ }
case t_array:
size = num_refs * sizeof(ref);
break;
@@ -288,9 +322,11 @@ gs_free_ref_array(gs_ref_memory_t * mem, ref * parr, client_name_t cname)
r_type(parr), num_refs, (ulong) obj);
return;
}
- /* If there are any leftover packed elements, we don't */
- /* worry about them, since they can't be dangling references. */
- refset_null(obj, size / sizeof(ref));
+ /*
+ * If there are any leftover packed elements, we don't
+ * worry about them, since they can't be dangling references.
+ */
+ refset_null_new(obj, size / sizeof(ref), 0);
mem->lost.refs += size;
}
}
diff --git a/gs/src/ialloc.h b/gs/src/ialloc.h
index a42e8da36..c9ef3ac13 100644
--- a/gs/src/ialloc.h
+++ b/gs/src/ialloc.h
@@ -27,8 +27,7 @@
/*
* Define the interpreter memory manager instance.
*/
-extern gs_dual_memory_t gs_imemory;
-
+#define gs_imemory (i_ctx_p->memory)
#define idmemory (&gs_imemory)
#define iimemory (gs_imemory.current)
#define imemory ((gs_memory_t *)iimemory)
@@ -83,11 +82,17 @@ void ialloc_validate_spaces(P1(const gs_dual_memory_t *));
/* Get the space attribute of the current allocator. */
#define ialloc_space(dmem) ((dmem)->current_space)
#define icurrent_space ialloc_space(idmemory)
-extern uint imemory_space(P1(gs_ref_memory_t *));
+uint imemory_space(P1(const gs_ref_memory_t *));
/* Select the allocation space. */
void ialloc_set_space(P2(gs_dual_memory_t *, uint));
+/* Get the l_new attribute of an allocator. */
+uint imemory_new_mask(P1(const gs_ref_memory_t *));
+
+/* Get the save level of an allocator. */
+int imemory_save_level(P1(const gs_ref_memory_t *));
+
/*
* Ref-related facilities.
*/
diff --git a/gs/src/ibnum.c b/gs/src/ibnum.c
index df48606f2..b26bcbdca 100644
--- a/gs/src/ibnum.c
+++ b/gs/src/ibnum.c
@@ -205,7 +205,7 @@ sdecodefloat(const byte * p, int format)
fnum = 0;
else {
mant += 0x800000;
- fnum = (float)ldexp((float)mant, expt - 127 - 24);
+ fnum = (float)ldexp((float)mant, expt - 127 - 23);
}
if (sign_expt & 0x100)
fnum = -fnum;
diff --git a/gs/src/iccfont.c b/gs/src/iccfont.c
index 62453f8bb..4c0ef15c1 100644
--- a/gs/src/iccfont.c
+++ b/gs/src/iccfont.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1992, 1995, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1992, 1995, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -40,16 +40,18 @@
/* ------ Private code ------ */
/* Forward references */
-private int cfont_ref_from_string(P3(ref *, const char *, uint));
+private int cfont_ref_from_string(P4(i_ctx_t *, ref *, const char *, uint));
typedef struct {
+ i_ctx_t *i_ctx_p;
const char *str_array;
ref next;
} str_enum;
inline private void
-init_str_enum(str_enum *pse, const char *ksa)
+init_str_enum(str_enum *pse, i_ctx_t *i_ctx_p, const char *ksa)
{
+ pse->i_ctx_p = i_ctx_p;
pse->str_array = ksa;
}
@@ -59,10 +61,11 @@ typedef struct {
} key_enum;
inline private void
-init_key_enum(key_enum *pke, const cfont_dict_keys *pkeys, const char *ksa)
+init_key_enum(key_enum *pke, i_ctx_t *i_ctx_p, const cfont_dict_keys *pkeys,
+ const char *ksa)
{
pke->keys = *pkeys;
- init_str_enum(&pke->strings, ksa);
+ init_str_enum(&pke->strings, i_ctx_p, ksa);
}
/* Check for reaching the end of the keys. */
@@ -89,7 +92,8 @@ cfont_next_string(str_enum * pse)
int code;
len = ((len & 0xff) << 8) + str[2];
- code = cfont_ref_from_string(&pse->next, (const char *)str + 3, len);
+ code = cfont_ref_from_string(pse->i_ctx_p, &pse->next,
+ (const char *)str + 3, len);
if (code < 0)
return code;
pse->str_array = str + 3 + len;
@@ -105,6 +109,7 @@ cfont_next_string(str_enum * pse)
private int
cfont_put_next(ref * pdict, key_enum * kep, const ref * pvalue)
{
+ i_ctx_t *i_ctx_p = kep->strings.i_ctx_p;
cfont_dict_keys * const kp = &kep->keys;
ref kname;
int code;
@@ -132,20 +137,21 @@ cfont_put_next(ref * pdict, key_enum * kep, const ref * pvalue)
}
if (code < 0)
return code;
- return dict_put(pdict, &kname, pvalue);
+ return dict_put(pdict, &kname, pvalue, &i_ctx_p->dict_stack);
}
/* ------ Routines called from compiled font initialization ------ */
/* Create a dictionary with general ref values. */
private int
-cfont_ref_dict_create(ref * pdict, const cfont_dict_keys * kp,
- cfont_string_array ksa, const ref * values)
+cfont_ref_dict_create(i_ctx_t *i_ctx_p, ref *pdict,
+ const cfont_dict_keys *kp, cfont_string_array ksa,
+ const ref *values)
{
key_enum kenum;
const ref *vp = values;
- init_key_enum(&kenum, kp, ksa);
+ init_key_enum(&kenum, i_ctx_p, kp, ksa);
pdict->value.pdict = 0;
while (more_keys(&kenum)) {
const ref *pvalue = vp++;
@@ -159,15 +165,16 @@ cfont_ref_dict_create(ref * pdict, const cfont_dict_keys * kp,
/* Create a dictionary with string/null values. */
private int
-cfont_string_dict_create(ref * pdict, const cfont_dict_keys * kp,
- cfont_string_array ksa, cfont_string_array kva)
+cfont_string_dict_create(i_ctx_t *i_ctx_p, ref *pdict,
+ const cfont_dict_keys *kp, cfont_string_array ksa,
+ cfont_string_array kva)
{
key_enum kenum;
str_enum senum;
uint attrs = kp->value_attrs;
- init_key_enum(&kenum, kp, ksa);
- init_str_enum(&senum, kva);
+ init_key_enum(&kenum, i_ctx_p, kp, ksa);
+ init_str_enum(&senum, i_ctx_p, kva);
pdict->value.pdict = 0;
while (more_keys(&kenum)) {
int code = cfont_next_string(&senum);
@@ -189,16 +196,16 @@ cfont_string_dict_create(ref * pdict, const cfont_dict_keys * kp,
/* Create a dictionary with number values. */
private int
-cfont_num_dict_create(ref * pdict, const cfont_dict_keys * kp,
- cfont_string_array ksa, const ref * values,
- const char *lengths)
+cfont_num_dict_create(i_ctx_t *i_ctx_p, ref * pdict,
+ const cfont_dict_keys * kp, cfont_string_array ksa,
+ const ref * values, const char *lengths)
{
key_enum kenum;
const ref *vp = values;
const char *lp = lengths;
ref vnum;
- init_key_enum(&kenum, kp, ksa);
+ init_key_enum(&kenum, i_ctx_p, kp, ksa);
pdict->value.pdict = 0;
while (more_keys(&kenum)) {
int len = (lp == 0 ? 0 : *lp++);
@@ -220,7 +227,8 @@ cfont_num_dict_create(ref * pdict, const cfont_dict_keys * kp,
/* Create an array with name values. */
private int
-cfont_name_array_create(ref * parray, cfont_string_array ksa, int size)
+cfont_name_array_create(i_ctx_t *i_ctx_p, ref * parray, cfont_string_array ksa,
+ int size)
{
int code = ialloc_ref_array(parray, a_readonly, size,
"cfont_name_array_create");
@@ -230,7 +238,7 @@ cfont_name_array_create(ref * parray, cfont_string_array ksa, int size)
if (code < 0)
return code;
- init_str_enum(&senum, ksa);
+ init_str_enum(&senum, i_ctx_p, ksa);
for (i = 0; i < size; i++, aptr++) {
ref nref;
int code = cfont_next_string(&senum);
@@ -248,8 +256,8 @@ cfont_name_array_create(ref * parray, cfont_string_array ksa, int size)
/* Create an array with string/null values. */
private int
-cfont_string_array_create(ref * parray, cfont_string_array ksa,
- int size, uint attrs)
+cfont_string_array_create(i_ctx_t *i_ctx_p, ref * parray,
+ cfont_string_array ksa, int size, uint attrs)
{
int code = ialloc_ref_array(parray, a_readonly, size,
"cfont_string_array_create");
@@ -259,7 +267,7 @@ cfont_string_array_create(ref * parray, cfont_string_array ksa,
if (code < 0)
return code;
- init_str_enum(&senum, ksa);
+ init_str_enum(&senum, i_ctx_p, ksa);
for (i = 0; i < size; i++, aptr++) {
int code = cfont_next_string(&senum);
@@ -277,16 +285,35 @@ cfont_string_array_create(ref * parray, cfont_string_array ksa,
return 0;
}
+/* Create an array with scalar values. */
+private int
+cfont_scalar_array_create(i_ctx_t *i_ctx_p, ref * parray,
+ const ref *va, int size, uint attrs)
+{
+ int code = ialloc_ref_array(parray, attrs, size,
+ "cfont_scalar_array_create");
+ ref *aptr = parray->value.refs;
+ uint elt_attrs = attrs | ialloc_new_mask;
+ int i;
+
+ if (code < 0)
+ return code;
+ memcpy(aptr, va, size * sizeof(ref));
+ for (i = 0; i < size; i++, aptr++)
+ r_set_attrs(aptr, elt_attrs);
+ return 0;
+}
+
/* Create a name. */
private int
-cfont_name_create(ref * pnref, const char *str)
+cfont_name_create(i_ctx_t *i_ctx_p, ref * pnref, const char *str)
{
return name_ref((const byte *)str, strlen(str), pnref, 0);
}
/* Create an object by parsing a string. */
private int
-cfont_ref_from_string(ref * pref, const char *str, uint len)
+cfont_ref_from_string(i_ctx_t *i_ctx_p, ref * pref, const char *str, uint len)
{
scanner_state sstate;
stream s;
@@ -294,20 +321,20 @@ cfont_ref_from_string(ref * pref, const char *str, uint len)
scanner_state_init(&sstate, false);
sread_string(&s, (const byte *)str, len);
- code = scan_token(&s, pref, &sstate);
+ code = scan_token(i_ctx_p, &s, pref, &sstate);
return (code <= 0 ? code : gs_note_error(e_Fatal));
}
/* ------ Initialization ------ */
/* Procedure vector passed to font initialization procedures. */
-private const cfont_procs ccfont_procs =
-{
+private const cfont_procs ccfont_procs = {
cfont_ref_dict_create,
cfont_string_dict_create,
cfont_num_dict_create,
cfont_name_array_create,
cfont_string_array_create,
+ cfont_scalar_array_create,
cfont_name_create,
cfont_ref_from_string
};
@@ -315,8 +342,9 @@ private const cfont_procs ccfont_procs =
/* null .getccfont <number-of-fonts> */
/* <int> .getccfont <font-object> */
private int
-zgetccfont(register os_ptr op)
+zgetccfont(i_ctx_t *i_ctx_p)
{
+ os_ptr op = osp;
int code;
const ccfont_fproc *fprocs;
int nfonts;
@@ -335,7 +363,7 @@ zgetccfont(register os_ptr op)
if (index < 0 || index >= nfonts)
return_error(e_rangecheck);
- return (*fprocs[index]) (&ccfont_procs, op);
+ return (*fprocs[index]) (i_ctx_p, &ccfont_procs, op);
}
/* Operator table initialization */
diff --git a/gs/src/ichar.h b/gs/src/ichar.h
index bf389c07a..cf7b07169 100644
--- a/gs/src/ichar.h
+++ b/gs/src/ichar.h
@@ -17,7 +17,7 @@
*/
-/* Requires gxchar.h */
+/* Requires gstext.h */
#ifndef ichar_INCLUDED
# define ichar_INCLUDED
@@ -26,42 +26,50 @@
* All the character rendering operators use the execution stack
* for loop control -- see estack.h for details.
* The information pushed by these operators is as follows:
- * the enumerator (t_struct, a gs_show_enum);
- * a slot for the procedure for kshow or cshow (probably t_array) or
- * the string or array for [x][y]show (t_string or t_array);
- * a slot for the string/array index for [x][y]show (t_integer);
+ * the enumerator (t_struct, a gs_text_enum_t);
+ * a slot for the procedure for kshow or cshow (probably t_array);
* a slot for the saved o-stack depth for cshow or stringwidth,
* and for error recovery (t_integer);
* a slot for the saved d-stack depth ditto (t_integer);
* a slot for the saved gstate level ditto (t_integer);
+ * a slot for saving the font during the cshow proc (t_struct);
+ * a slot for saving the root font during the cshow proc (t_struct);
* the procedure to be called at the end of the enumeration
* (t_operator, but called directly, not by the interpreter);
* the usual e-stack mark (t_null).
*/
-#define snumpush 8
-#define esenum(ep) r_ptr(ep, gs_show_enum)
+#define snumpush 9
+#define esenum(ep) r_ptr(ep, gs_text_enum_t)
#define senum esenum(esp)
#define esslot(ep) ((ep)[-1])
#define sslot esslot(esp)
-#define essindex(ep) ((ep)[-2])
-#define ssindex essindex(esp)
-#define esodepth(ep) ((ep)[-3])
+#define esodepth(ep) ((ep)[-2])
#define sodepth esodepth(esp)
-#define esddepth(ep) ((ep)[-4])
+#define esddepth(ep) ((ep)[-3])
#define sddepth esddepth(esp)
-#define esgslevel(ep) ((ep)[-5])
+#define esgslevel(ep) ((ep)[-4])
#define sgslevel esgslevel(esp)
-#define eseproc(ep) ((ep)[-6])
+#define essfont(ep) ((ep)[-5])
+#define ssfont essfont(esp)
+#define esrfont(ep) ((ep)[-6])
+#define srfont esrfont(esp)
+#define eseproc(ep) ((ep)[-7])
#define seproc eseproc(esp)
-/* Procedures exported by zchar.c for zchar1.c, zchar2.c, and/or zcharcid.c. */
-gs_show_enum *op_show_find(P1(i_ctx_t *));
-int op_show_setup(P3(i_ctx_t *, os_ptr, gs_show_enum **));
-int op_show_enum_setup(P2(i_ctx_t *, gs_show_enum **));
-void op_show_finish_setup(P4(i_ctx_t *, gs_show_enum *, int, op_proc_t));
+/* Procedures exported by zchar.c for zchar*.c. */
+gs_text_enum_t *op_show_find(P1(i_ctx_t *));
+int op_show_setup(P2(i_ctx_t *, os_ptr));
+int op_show_enum_setup(P1(i_ctx_t *));
+int op_show_finish_setup(P4(i_ctx_t *, gs_text_enum_t *, int, op_proc_t));
int op_show_continue(P1(i_ctx_t *));
int op_show_continue_pop(P2(i_ctx_t *, int));
int op_show_continue_dispatch(P3(i_ctx_t *, int, int));
int op_show_free(P2(i_ctx_t *, int));
+void glyph_ref(P2(gs_glyph, ref *));
+
+/* Exported by zchar.c for zcharout.c */
+bool zchar_show_width_only(P1(const gs_text_enum_t *));
+int zsetcachedevice(P1(i_ctx_t *));
+int zsetcachedevice2(P1(i_ctx_t *));
#endif /* ichar_INCLUDED */
diff --git a/gs/src/icharout.h b/gs/src/icharout.h
index 1688c6f6f..aa3a776af 100644
--- a/gs/src/icharout.h
+++ b/gs/src/icharout.h
@@ -39,6 +39,11 @@ int /*metrics_present*/
zchar_get_metrics(P3(const gs_font_base * pbfont, const ref * pcnref,
double psbw[4]));
+/* Get the vertical metrics for a character from Metrics2, if present. */
+int /*metrics_present*/
+ zchar_get_metrics2(P3(const gs_font_base * pbfont, const ref * pcnref,
+ double pwv[4]));
+
/*
* Consult Metrics2 and CDevProc, and call setcachedevice[2]. Return
* o_push_estack if we had to call a CDevProc, or if we are skipping the
@@ -50,4 +55,18 @@ int zchar_set_cache(P8(i_ctx_t *i_ctx_p, const gs_font_base * pbfont,
int (*cont_fill) (P1(i_ctx_t *)),
int (*cont_stroke) (P1(i_ctx_t *))));
+/*
+ * Get the CharString data corresponding to a glyph. Return typecheck
+ * if it isn't a string.
+ */
+int zchar_charstring_data(P3(gs_font *font, const ref *pgref,
+ gs_const_string *pstr));
+
+/*
+ * Enumerate the next glyph from a directory. This is essentially a
+ * wrapper around dict_first/dict_next to implement the enumerate_glyph
+ * font procedure.
+ */
+int zchar_enumerate_glyph(P3(const ref *prdict, int *pindex, gs_glyph *pglyph));
+
#endif /* icharout_INCLUDED */
diff --git a/gs/src/icontext.c b/gs/src/icontext.c
index 5bae357e1..f43c119eb 100644
--- a/gs/src/icontext.c
+++ b/gs/src/icontext.c
@@ -40,21 +40,19 @@ extern_st(st_dict_stack);
extern_st(st_exec_stack);
extern_st(st_op_stack);
-/* Initialization procedures */
-void zrand_state_init(P1(long *));
-
/* GC descriptors */
-#define pcst ((gs_context_state_t *)vptr)
private
CLEAR_MARKS_PROC(context_state_clear_marks)
{
+ gs_context_state_t *const pcst = vptr;
+
r_clear_attrs(&pcst->stdio[0], l_mark);
r_clear_attrs(&pcst->stdio[1], l_mark);
r_clear_attrs(&pcst->stdio[2], l_mark);
r_clear_attrs(&pcst->userparams, l_mark);
}
private
-ENUM_PTRS_BEGIN(context_state_enum_ptrs) {
+ENUM_PTRS_WITH(context_state_enum_ptrs, gs_context_state_t *pcst) {
index -= 5;
if (index < st_gs_dual_memory_num_ptrs)
return ENUM_USING(st_gs_dual_memory, &pcst->memory,
@@ -67,7 +65,7 @@ ENUM_PTRS_BEGIN(context_state_enum_ptrs) {
if (index < st_exec_stack_num_ptrs)
return ENUM_USING(st_exec_stack, &pcst->exec_stack,
sizeof(pcst->exec_stack), index);
- index -= st_dict_stack_num_ptrs;
+ index -= st_exec_stack_num_ptrs;
return ENUM_USING(st_op_stack, &pcst->op_stack,
sizeof(pcst->op_stack), index);
}
@@ -77,7 +75,7 @@ ENUM_PTRS_BEGIN(context_state_enum_ptrs) {
case 3: ENUM_RETURN_REF(&pcst->stdio[2]);
case 4: ENUM_RETURN_REF(&pcst->userparams);
ENUM_PTRS_END
-private RELOC_PTRS_BEGIN(context_state_reloc_ptrs);
+private RELOC_PTRS_WITH(context_state_reloc_ptrs, gs_context_state_t *pcst);
RELOC_PTR(gs_context_state_t, pgs);
RELOC_USING(st_gs_dual_memory, &pcst->memory, sizeof(pcst->memory));
RELOC_REF_VAR(pcst->stdio[0]);
@@ -89,12 +87,12 @@ private RELOC_PTRS_BEGIN(context_state_reloc_ptrs);
RELOC_USING(st_exec_stack, &pcst->exec_stack, sizeof(pcst->exec_stack));
RELOC_USING(st_op_stack, &pcst->op_stack, sizeof(pcst->op_stack));
RELOC_PTRS_END
-#undef pcst
public_st_context_state();
/* Allocate the state of a context. */
int
context_state_alloc(gs_context_state_t ** ppcst,
+ const ref *psystem_dict,
const gs_dual_memory_t * dmem)
{
gs_ref_memory_t *mem = dmem->space_local;
@@ -111,6 +109,12 @@ context_state_alloc(gs_context_state_t ** ppcst,
code = gs_interp_alloc_stacks(mem, pcst);
if (code < 0)
goto x0;
+ /*
+ * We have to initialize the dictionary stack early,
+ * for far-off references to systemdict.
+ */
+ pcst->dict_stack.system_dict = *psystem_dict;
+ pcst->dict_stack.min_size = 0;
pcst->pgs = int_gstate_alloc(dmem);
if (pcst->pgs == 0) {
code = gs_note_error(e_VMerror);
@@ -120,7 +124,7 @@ context_state_alloc(gs_context_state_t ** ppcst,
pcst->language_level = 1;
make_false(&pcst->array_packing);
make_int(&pcst->binary_object_format, 0);
- zrand_state_init(&pcst->rand_state);
+ pcst->rand_state = rand_state_initial;
pcst->usertime_total = 0;
pcst->keep_usertime = false;
{ /*
@@ -161,14 +165,13 @@ context_state_alloc(gs_context_state_t ** ppcst,
/* Load the interpreter state from a context. */
int
-context_state_load(gs_context_state_t * pcst)
+context_state_load(gs_context_state_t * i_ctx_p)
{
gs_ref_memory_t *lmem = iimemory_local;
- ref *system_dict = &pcst->dict_stack.system_dict;
+ ref *system_dict = systemdict;
uint space = r_space(system_dict);
int code;
- gs_imemory = pcst->memory;
/*
* Set systemdict.userparams to the saved copy, and then
* set the actual user parameters. Be careful to disable both
@@ -176,16 +179,16 @@ context_state_load(gs_context_state_t * pcst)
*/
r_set_space(system_dict, avm_max);
alloc_set_not_in_save(idmemory);
- code = dict_put_string(system_dict, "userparams", &pcst->userparams,
- &pcst->dict_stack);
+ code = dict_put_string(system_dict, "userparams", &i_ctx_p->userparams,
+ &idict_stack);
if (code >= 0)
- code = set_user_params(pcst, &pcst->userparams);
+ code = set_user_params(i_ctx_p, &i_ctx_p->userparams);
if (iimemory_local != lmem) {
/*
* Switch references in systemdict to local objects.
* userdict.localdicts holds these objects.
*/
- dict_stack_t *dstack = &pcst->dict_stack;
+ dict_stack_t *dstack = &idict_stack;
ref_stack_t *rdstack = &dstack->stack;
const ref *puserdict =
ref_stack_index(rdstack, ref_stack_count(rdstack) - 1 -
@@ -199,10 +202,10 @@ context_state_load(gs_context_state_t * pcst)
}
}
r_set_space(system_dict, space);
- if (idmemory->save_level > 0)
+ if (lmem->save_level > 0)
alloc_set_in_save(idmemory);
- estack_clear_cache(&pcst->exec_stack);
- dstack_set_top(&pcst->dict_stack);
+ estack_clear_cache(&iexec_stack);
+ dstack_set_top(&idict_stack);
return code;
}
@@ -213,7 +216,6 @@ context_state_store(gs_context_state_t * pcst)
ref_stack_cleanup(&pcst->dict_stack.stack);
ref_stack_cleanup(&pcst->exec_stack.stack);
ref_stack_cleanup(&pcst->op_stack.stack);
- pcst->memory = gs_imemory;
/*
* The user parameters in systemdict.userparams are kept
* up to date by PostScript code, but we still need to save
diff --git a/gs/src/icontext.h b/gs/src/icontext.h
index 5b2988aae..da2bdd6ac 100644
--- a/gs/src/icontext.h
+++ b/gs/src/icontext.h
@@ -37,7 +37,8 @@ extern int set_user_params(P2(i_ctx_t *i_ctx_p, const ref * paramdict));
/* Allocate the state of a context, always in local VM. */
/* If *ppcst == 0, allocate the state object as well. */
-int context_state_alloc(P2(gs_context_state_t ** ppcst,
+int context_state_alloc(P3(gs_context_state_t ** ppcst,
+ const ref *psystem_dict,
const gs_dual_memory_t * dmem));
/* Load the state of the interpreter from a context. */
diff --git a/gs/src/icstate.h b/gs/src/icstate.h
index 2abbb6f6f..0f2271953 100644
--- a/gs/src/icstate.h
+++ b/gs/src/icstate.h
@@ -55,6 +55,7 @@ struct gs_context_state_s {
exec_stack_t exec_stack;
op_stack_t op_stack;
};
+extern const long rand_state_initial; /* in zmath.c */
/*
* We make st_context_state public because zcontext.c must subclass it.
diff --git a/gs/src/idebug.c b/gs/src/idebug.c
index 8b2c89354..a5481c18c 100644
--- a/gs/src/idebug.c
+++ b/gs/src/idebug.c
@@ -23,7 +23,7 @@
#define DEBUG
#include "string_.h"
#include "ghost.h"
-#include "ialloc.h" /* for imemory for getting struct type */
+#include "gxalloc.h" /* for procs for getting struct type */
#include "idebug.h" /* defines interface */
#include "idict.h"
#include "iname.h"
@@ -130,10 +130,13 @@ debug_print_full_ref(const ref * pref)
case t_struct:
strct:{
obj_header_t *obj = (obj_header_t *) pref->value.pstruct;
+ /* HACK: We know this object was allocated with gsalloc.c. */
+ gs_memory_type_ptr_t otype =
+ gs_ref_memory_procs.object_type(NULL, obj);
dprintf2("struct %s 0x%lx",
(r_is_foreign(pref) ? "-foreign-" :
- gs_struct_type_name_string(gs_object_type(imemory, obj))),
+ gs_struct_type_name_string(otype)),
(ulong) obj);
}
break;
@@ -170,14 +173,19 @@ debug_print_packed_ref(const ref_packed * pref)
}
}
void
-debug_print_ref(const ref * pref)
+debug_print_ref_packed(const ref_packed *rpp)
{
- if (r_is_packed(pref))
- debug_print_packed_ref((const ref_packed *)pref);
+ if (r_is_packed(rpp))
+ debug_print_packed_ref(rpp);
else
- debug_print_full_ref(pref);
+ debug_print_full_ref((const ref *)rpp);
fflush(dstderr);
}
+void
+debug_print_ref(const ref * pref)
+{
+ debug_print_ref_packed((const ref_packed *)pref);
+}
/* Dump one ref. */
private void print_ref_data(P1(const ref *));
@@ -292,10 +300,10 @@ debug_dump_array(const ref * array)
packed_get(pp, &temp);
if (r_is_packed(pp)) {
- dprintf2("0x%lx* 0x%04x", (ulong)pp, (uint)*pp);
+ dprintf2("0x%lx* 0x%04x ", (ulong)pp, (uint)*pp);
print_ref_data(&temp);
} else {
- dprintf2("0x%lx: 0x%02x", (ulong)pp, r_type(&temp));
+ dprintf2("0x%lx: 0x%02x ", (ulong)pp, r_type(&temp));
debug_dump_one_ref(&temp);
}
dputc('\n');
diff --git a/gs/src/idebug.h b/gs/src/idebug.h
index aea97de4f..621d8ca4b 100644
--- a/gs/src/idebug.h
+++ b/gs/src/idebug.h
@@ -25,6 +25,7 @@
/* Print individual values. */
void debug_print_name(P1(const ref *));
void debug_print_ref(P1(const ref *));
+void debug_print_ref_packed(P1(const ref_packed *));
/* Dump regions of memory. */
void debug_dump_one_ref(P1(const ref *));
@@ -33,7 +34,7 @@ void debug_dump_array(P1(const ref * array));
/* Dump a stack. Using this requires istack.h. */
#ifndef ref_stack_DEFINED
-typedef struct ref_stack_s ref_stack_t; /* also defined in istack.h */
+typedef struct ref_stack_s ref_stack_t; /* also defined in isdata.h */
# define ref_stack_DEFINED
#endif
void debug_dump_stack(P2(const ref_stack_t * pstack, const char *msg));
diff --git a/gs/src/idict.c b/gs/src/idict.c
index ceacd4b09..45e7306ba 100644
--- a/gs/src/idict.c
+++ b/gs/src/idict.c
@@ -20,6 +20,7 @@
/* Dictionary implementation */
#include "string_.h" /* for strlen */
#include "ghost.h"
+#include "gxalloc.h" /* for accessing masks */
#include "errors.h"
#include "imemory.h"
#include "idebug.h" /* for debug_print_name */
@@ -128,16 +129,17 @@ dict_alloc(gs_ref_memory_t * mem, uint size, ref * pdref)
{
ref arr;
int code =
- gs_alloc_ref_array(mem, &arr, a_all, sizeof(dict) / sizeof(ref),
- "dict_alloc");
+ gs_alloc_ref_array(mem, &arr, a_all, sizeof(dict) / sizeof(ref),
+ "dict_alloc");
dict *pdict;
ref dref;
if (code < 0)
return code;
pdict = (dict *) arr.value.refs;
- make_tav_new(&dref, t_dictionary, r_space(&arr) | a_all,
- pdict, pdict);
+ make_tav(&dref, t_dictionary,
+ r_space(&arr) | imemory_new_mask(mem) | a_all,
+ pdict, pdict);
make_struct(&pdict->memory, avm_foreign, mem);
code = dict_create_contents(size, &dref, dict_default_pack);
if (code < 0) {
@@ -159,10 +161,11 @@ dict_create_unpacked_keys(uint asize, const ref * pdref)
code = gs_alloc_ref_array(mem, &pdict->keys, a_all, asize,
"dict_create_unpacked_keys");
if (code >= 0) {
+ uint new_mask = imemory_new_mask(mem);
ref *kp = pdict->keys.value.refs;
- ref_mark_new(&pdict->keys);
- refset_null(kp, asize);
+ r_set_attrs(&pdict->keys, new_mask);
+ refset_null_new(kp, asize, new_mask);
r_set_attrs(kp, a_executable); /* wraparound entry */
}
return code;
@@ -175,6 +178,7 @@ dict_create_contents(uint size, const ref * pdref, bool pack)
{
dict *pdict = pdref->value.pdict;
gs_ref_memory_t *mem = dict_memory(pdict);
+ uint new_mask = imemory_new_mask(mem);
uint asize = dict_round_size((size == 0 ? 1 : size));
int code;
register uint i;
@@ -186,8 +190,8 @@ dict_create_contents(uint size, const ref * pdref, bool pack)
"dict_create_contents(values)");
if (code < 0)
return code;
- ref_mark_new(&pdict->values);
- refset_null(pdict->values.value.refs, asize);
+ r_set_attrs(&pdict->values, new_mask);
+ refset_null_new(pdict->values.value.refs, asize, new_mask);
if (pack) {
uint ksize = (asize + packed_per_ref - 1) / packed_per_ref;
ref arr;
@@ -199,9 +203,9 @@ dict_create_contents(uint size, const ref * pdref, bool pack)
if (code < 0)
return code;
pkp = (ref_packed *) arr.value.refs;
- make_tasv_new(&pdict->keys, t_shortarray,
- r_space(&arr) | a_all,
- asize, packed, pkp);
+ make_tasv(&pdict->keys, t_shortarray,
+ r_space(&arr) | a_all | new_mask,
+ asize, packed, pkp);
for (pzp = pkp, i = 0; i < asize || i % packed_per_ref; pzp++, i++)
*pzp = packed_key_empty;
*pkp = packed_key_deleted; /* wraparound entry */
@@ -211,8 +215,8 @@ dict_create_contents(uint size, const ref * pdref, bool pack)
if (code < 0)
return code;
}
- make_int_new(&pdict->count, 0);
- make_int_new(&pdict->maxlength, size);
+ make_tav(&pdict->count, t_integer, new_mask, intval, 0);
+ make_tav(&pdict->maxlength, t_integer, new_mask, intval, size);
return 0;
}
@@ -228,6 +232,7 @@ dict_unpack(ref * pdref, dict_stack_t *pds)
if (!dict_is_packed(pdict))
return 0; /* nothing to do */
{
+ gs_ref_memory_t *mem = dict_memory(pdict);
uint count = nslots(pdict);
const ref_packed *okp = pdict->keys.value.packed;
ref old_keys;
@@ -235,20 +240,19 @@ dict_unpack(ref * pdref, dict_stack_t *pds)
ref *nkp;
old_keys = pdict->keys;
- if (ref_must_save(&old_keys))
- ref_do_save(pdref, &pdict->keys, "dict_unpack(keys)");
+ if (ref_must_save_in(mem, &old_keys))
+ ref_do_save_in(mem, pdref, &pdict->keys, "dict_unpack(keys)");
code = dict_create_unpacked_keys(count, pdref);
if (code < 0)
return code;
for (nkp = pdict->keys.value.refs; count--; okp++, nkp++)
if (r_packed_is_name(okp)) {
packed_get(okp, nkp);
- ref_mark_new(nkp);
+ ref_mark_new_in(mem, nkp);
} else if (*okp == packed_key_deleted)
r_set_attrs(nkp, a_executable);
- if (!ref_must_save(&old_keys))
- gs_free_ref_array(dict_memory(pdict), &old_keys,
- "dict_unpack(old keys)");
+ if (!ref_must_save_in(mem, &old_keys))
+ gs_free_ref_array(mem, &old_keys, "dict_unpack(old keys)");
if (pds)
dstack_set_top(pds); /* just in case */
}
@@ -401,6 +405,8 @@ int
dict_put(ref * pdref /* t_dictionary */ , const ref * pkey, const ref * pvalue,
dict_stack_t *pds)
{
+ dict *pdict = pdref->value.pdict;
+ gs_ref_memory_t *mem = dict_memory(pdict);
int rcode = 0;
int code;
ref *pvslot;
@@ -408,7 +414,6 @@ dict_put(ref * pdref /* t_dictionary */ , const ref * pkey, const ref * pvalue,
/* Check the value. */
store_check_dest(pdref, pvalue);
top:if ((code = dict_find(pdref, pkey, &pvslot)) <= 0) { /* not found *//* Check for overflow */
- dict *pdict = pdref->value.pdict;
ref kname;
uint index;
@@ -450,10 +455,10 @@ dict_put(ref * pdref /* t_dictionary */ , const ref * pkey, const ref * pvalue,
goto top;
}
kp = pdict->keys.value.writable_packed + index;
- if (ref_must_save(&pdict->keys)) { /* See initial comment for why it is safe */
+ if (ref_must_save_in(mem, &pdict->keys)) { /* See initial comment for why it is safe */
/* not to save the change if the keys */
/* array itself is new. */
- ref_do_save(&pdict->keys, kp, "dict_put(key)");
+ ref_do_save_in(mem, &pdict->keys, kp, "dict_put(key)");
}
*kp = pt_tag(pt_literal_name) + name_index(pkey);
} else {
@@ -462,10 +467,10 @@ dict_put(ref * pdref /* t_dictionary */ , const ref * pkey, const ref * pvalue,
if_debug2('d', "[d]0x%lx: fill key at 0x%lx\n",
(ulong) pdict, (ulong) kp);
store_check_dest(pdref, pkey);
- ref_assign_old(&pdict->keys, kp, pkey,
- "dict_put(key)"); /* set key of pair */
+ ref_assign_old_in(mem, &pdict->keys, kp, pkey,
+ "dict_put(key)"); /* set key of pair */
}
- ref_save(pdref, &pdict->count, "dict_put(count)");
+ ref_save_in(mem, pdref, &pdict->count, "dict_put(count)");
pdict->count.value.intval++;
/* If the key is a name, update its 1-element cache. */
if (r_has_type(pkey, t_name)) {
@@ -477,7 +482,7 @@ dict_put(ref * pdref /* t_dictionary */ , const ref * pkey, const ref * pvalue,
* Only set the cache if we aren't inside a save.
* This way, we never have to undo setting the cache.
*/
- alloc_save_level(idmemory) == 0
+ !ref_saving_in(mem)
) { /* Set the cache. */
if_debug0('d', "[d]set cache\n");
pname->pvalue = pvslot;
@@ -494,8 +499,8 @@ dict_put(ref * pdref /* t_dictionary */ , const ref * pkey, const ref * pvalue,
(ulong) pvslot,
((const ulong *)pvslot)[0], ((const ulong *)pvslot)[1],
((const ulong *)pvalue)[0], ((const ulong *)pvalue)[1]);
- ref_assign_old(&pdref->value.pdict->values, pvslot, pvalue,
- "dict_put(value)");
+ ref_assign_old_in(mem, &pdref->value.pdict->values, pvslot, pvalue,
+ "dict_put(value)");
return rcode;
}
@@ -518,6 +523,7 @@ dict_put_string(ref * pdref, const char *kstr, const ref * pvalue,
int
dict_undef(ref * pdref, const ref * pkey, dict_stack_t *pds)
{
+ gs_ref_memory_t *mem;
ref *pvslot;
dict *pdict;
uint index;
@@ -527,6 +533,7 @@ dict_undef(ref * pdref, const ref * pkey, dict_stack_t *pds)
/* Remove the entry from the dictionary. */
pdict = pdref->value.pdict;
index = pvslot - pdict->values.value.refs;
+ mem = dict_memory(pdict);
if (dict_is_packed(pdict)) {
ref_packed *pkp = pdict->keys.value.writable_packed + index;
@@ -534,8 +541,8 @@ dict_undef(ref * pdref, const ref * pkey, dict_stack_t *pds)
(ulong)pdict, (ulong)pkp, (uint)*pkp);
/* See the initial comment for why it is safe not to save */
/* the change if the keys array itself is new. */
- if (ref_must_save(&pdict->keys))
- ref_do_save(&pdict->keys, pkp, "dict_undef(key)");
+ if (ref_must_save_in(mem, &pdict->keys))
+ ref_do_save_in(mem, &pdict->keys, pkp, "dict_undef(key)");
/*
* Accumulating deleted entries slows down lookup.
* Detect the easy case where we can use an empty entry
@@ -559,7 +566,7 @@ dict_undef(ref * pdref, const ref * pkey, dict_stack_t *pds)
if_debug4('d', "[d]0x%lx: removing key at 0%lx: 0x%lx 0x%lx\n",
(ulong)pdict, (ulong)kp, ((ulong *)kp)[0], ((ulong *)kp)[1]);
- make_null_old(&pdict->keys, kp, "dict_undef(key)");
+ make_null_old_in(mem, &pdict->keys, kp, "dict_undef(key)");
/*
* Accumulating deleted entries slows down lookup.
* Detect the easy case where we can use an empty entry
@@ -571,7 +578,7 @@ dict_undef(ref * pdref, const ref * pkey, dict_stack_t *pds)
)
r_set_attrs(kp, a_executable); /* mark as deleted */
}
- ref_save(pdref, &pdict->count, "dict_undef(count)");
+ ref_save_in(mem, pdref, &pdict->count, "dict_undef(count)");
pdict->count.value.intval--;
/* If the key is a name, update its 1-element cache. */
if (r_has_type(pkey, t_name)) {
@@ -588,7 +595,7 @@ dict_undef(ref * pdref, const ref * pkey, dict_stack_t *pds)
pname->pvalue = pv_no_defn;
}
}
- make_null_old(&pdict->values, pvslot, "dict_undef(value)");
+ make_null_old_in(mem, &pdict->values, pvslot, "dict_undef(value)");
return 0;
}
@@ -652,6 +659,7 @@ dict_resize(ref * pdref, uint new_size, dict_stack_t *pds)
{
dict *pdict = pdref->value.pdict;
gs_ref_memory_t *mem = dict_memory(pdict);
+ uint new_mask = imemory_new_mask(mem);
dict dnew;
ref drto;
int code;
@@ -661,8 +669,8 @@ dict_resize(ref * pdref, uint new_size, dict_stack_t *pds)
return_error(e_dictfull);
new_size = d_length(pdict);
}
- make_tav_new(&drto, t_dictionary, r_space(pdref) | a_all,
- pdict, &dnew);
+ make_tav(&drto, t_dictionary, r_space(pdref) | a_all | new_mask,
+ pdict, &dnew);
dnew.memory = pdict->memory;
if ((code = dict_create_contents(new_size, &drto, dict_is_packed(pdict))) < 0)
return code;
@@ -672,17 +680,18 @@ dict_resize(ref * pdref, uint new_size, dict_stack_t *pds)
r_set_space(&drto, avm_local);
dict_copy(pdref, &drto, pds); /* can't fail */
/* Save or free the old dictionary. */
- if (ref_must_save(&pdict->values))
- ref_do_save(pdref, &pdict->values, "dict_resize(values)");
+ if (ref_must_save_in(mem, &pdict->values))
+ ref_do_save_in(mem, pdref, &pdict->values, "dict_resize(values)");
else
gs_free_ref_array(mem, &pdict->values, "dict_resize(old values)");
- if (ref_must_save(&pdict->keys))
- ref_do_save(pdref, &pdict->keys, "dict_resize(keys)");
+ if (ref_must_save_in(mem, &pdict->keys))
+ ref_do_save_in(mem, pdref, &pdict->keys, "dict_resize(keys)");
else
gs_free_ref_array(mem, &pdict->keys, "dict_resize(old keys)");
ref_assign(&pdict->keys, &dnew.keys);
ref_assign(&pdict->values, &dnew.values);
- ref_save(pdref, &pdict->maxlength, "dict_resize(maxlength)");
+ ref_save_in(dict_memory(pdict), pdref, &pdict->maxlength,
+ "dict_resize(maxlength)");
d_set_maxlength(pdict, new_size);
if (pds)
dstack_set_top(pds); /* just in case this is the top dict */
@@ -694,7 +703,6 @@ int
dict_grow(ref * pdref, dict_stack_t *pds)
{
dict *pdict = pdref->value.pdict;
-
/* We might have maxlength < npairs, if */
/* dict_round_size increased the size. */
ulong new_size = (ulong) d_maxlength(pdict) * 3 / 2 + 2;
@@ -721,7 +729,8 @@ dict_grow(ref * pdref, dict_stack_t *pds)
new_size = npairs(pdict);
}
/* maxlength < npairs, we can grow in place */
- ref_save(pdref, &pdict->maxlength, "dict_put(maxlength)");
+ ref_save_in(dict_memory(pdict), pdref, &pdict->maxlength,
+ "dict_put(maxlength)");
d_set_maxlength(pdict, new_size);
return 0;
}
diff --git a/gs/src/idosave.h b/gs/src/idosave.h
new file mode 100644
index 000000000..496a53fde
--- /dev/null
+++ b/gs/src/idosave.h
@@ -0,0 +1,42 @@
+/* Copyright (C) 1999 Aladdin Enterprises. All rights reserved.
+
+ This file is part of Aladdin Ghostscript.
+
+ Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
+ or distributor accepts any responsibility for the consequences of using it,
+ or for whether it serves any particular purpose or works at all, unless he
+ or she says so in writing. Refer to the Aladdin Ghostscript Free Public
+ License (the "License") for full details.
+
+ Every copy of Aladdin Ghostscript must include a copy of the License,
+ normally in a plain ASCII text file named PUBLIC. The License grants you
+ the right to copy, modify and redistribute Aladdin Ghostscript, but only
+ under certain conditions described in the License. Among other things, the
+ License requires that the copyright notice and this notice be preserved on
+ all copies.
+ */
+
+
+/* Supporting procedures for 'save' recording. */
+
+#ifndef idosave_INCLUDED
+# define idosave_INCLUDED
+
+/*
+ * Save a change that must be undone by restore. We have to pass the
+ * pointer to the containing object to alloc_save_change for two reasons:
+ *
+ * - We need to know which VM the containing object is in, so we can
+ * know on which chain of saved changes to put the new change.
+ *
+ * - We need to know whether the object is an array of refs (which
+ * includes dictionaries) or a struct, so we can properly trace and
+ * relocate the pointer to it from the change record during garbage
+ * collection.
+ */
+int alloc_save_change(P4(gs_dual_memory_t *dmem, const ref *pcont,
+ ref_packed *ptr, client_name_t cname));
+int alloc_save_change_in(P4(gs_ref_memory_t *mem, const ref *pcont,
+ ref_packed *ptr, client_name_t cname));
+
+#endif /* idosave_INCLUDED */
diff --git a/gs/src/ifilter2.h b/gs/src/ifilter2.h
new file mode 100644
index 000000000..207388f0b
--- /dev/null
+++ b/gs/src/ifilter2.h
@@ -0,0 +1,31 @@
+/* Copyright (C) 1999 Aladdin Enterprises. All rights reserved.
+
+ This file is part of Aladdin Ghostscript.
+
+ Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
+ or distributor accepts any responsibility for the consequences of using it,
+ or for whether it serves any particular purpose or works at all, unless he
+ or she says so in writing. Refer to the Aladdin Ghostscript Free Public
+ License (the "License") for full details.
+
+ Every copy of Aladdin Ghostscript must include a copy of the License,
+ normally in a plain ASCII text file named PUBLIC. The License grants you
+ the right to copy, modify and redistribute Aladdin Ghostscript, but only
+ under certain conditions described in the License. Among other things, the
+ License requires that the copyright notice and this notice be preserved on
+ all copies.
+ */
+
+
+/* Utilities for Level 2 filters */
+
+#ifndef ifilter2_INCLUDED
+# define ifilter2_INCLUDED
+
+/* Import setup code from zfdecode.c */
+int zcf_setup(P3(os_ptr op, stream_CF_state * pcfs, gs_ref_memory_t *imem));
+int zlz_setup(P2(os_ptr op, stream_LZW_state * plzs));
+int zpd_setup(P2(os_ptr op, stream_PDiff_state * ppds));
+int zpp_setup(P2(os_ptr op, stream_PNGP_state * ppps));
+
+#endif /* ifilter2_INCLUDED */
diff --git a/gs/src/ifont.h b/gs/src/ifont.h
index 16fbd41af..7e7e2eb18 100644
--- a/gs/src/ifont.h
+++ b/gs/src/ifont.h
@@ -22,7 +22,7 @@
#ifndef ifont_INCLUDED
# define ifont_INCLUDED
-#include "gsccode.h" /* for gs_glyph */
+#include "gsccode.h" /* for gs_glyph, NUM_KNOWN_ENCODINGS */
#include "gsstype.h" /* for extern_st */
/* The external definition of fonts is given in the PostScript manual, */
@@ -68,7 +68,7 @@ extern_st(st_font_data);
/* Registered encodings, for the benefit of platform fonts, `seac', */
/* and compiled font initialization. */
/* This is a t_array ref that points to the encodings. */
-#define registered_Encodings_countof 5
+#define registered_Encodings_countof NUM_KNOWN_ENCODINGS
extern ref registered_Encodings;
#define registered_Encoding(i) (registered_Encodings.value.refs[i])
@@ -83,7 +83,6 @@ int font_bbox_param(P2(const ref * pfdict, double bbox[4]));
#ifndef gs_font_DEFINED
# define gs_font_DEFINED
typedef struct gs_font_s gs_font;
-
#endif
int font_param(P2(const ref * pfdict, gs_font ** ppfont));
bool zfont_mark_glyph_name(P2(gs_glyph glyph, void *ignore_data));
diff --git a/gs/src/ifrpred.h b/gs/src/ifrpred.h
new file mode 100644
index 000000000..f92a8cef3
--- /dev/null
+++ b/gs/src/ifrpred.h
@@ -0,0 +1,30 @@
+/* Copyright (C) 1999 Aladdin Enterprises. All rights reserved.
+
+ This file is part of Aladdin Ghostscript.
+
+ Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
+ or distributor accepts any responsibility for the consequences of using it,
+ or for whether it serves any particular purpose or works at all, unless he
+ or she says so in writing. Refer to the Aladdin Ghostscript Free Public
+ License (the "License") for full details.
+
+ Every copy of Aladdin Ghostscript must include a copy of the License,
+ normally in a plain ASCII text file named PUBLIC. The License grants you
+ the right to copy, modify and redistribute Aladdin Ghostscript, but only
+ under certain conditions described in the License. Among other things, the
+ License requires that the copyright notice and this notice be preserved on
+ all copies.
+ */
+
+
+/* filter_read_predictor prototype */
+
+#ifndef ifrpred_INCLUDED
+# define ifrpred_INCLUDED
+
+/* Exported by zfdecode.c for zfzlib.c */
+int filter_read_predictor(P4(i_ctx_t *i_ctx_p, int npop,
+ const stream_template * template,
+ stream_state * st));
+
+#endif /* ifrpred_INCLUDED */
diff --git a/gs/src/ifunc.h b/gs/src/ifunc.h
index 88d46270e..8a7660ffb 100644
--- a/gs/src/ifunc.h
+++ b/gs/src/ifunc.h
@@ -26,8 +26,8 @@
/* Define build procedures for the various function types. */
#define build_function_proc(proc)\
- int proc(P4(const ref *op, const gs_function_params_t *params, int depth,\
- gs_function_t **ppfn))
+ int proc(P5(const ref *op, const gs_function_params_t *params, int depth,\
+ gs_function_t **ppfn, gs_memory_t *mem))
typedef build_function_proc((*build_function_proc_t));
/* Define the table of build procedures, indexed by FunctionType. */
@@ -39,13 +39,14 @@ extern const build_function_type_t build_function_type_table[];
extern const uint build_function_type_table_count;
/* Build a function structure from a PostScript dictionary. */
-int fn_build_sub_function(P3(const ref * op, gs_function_t ** ppfn, int depth));
-
-#define fn_build_function(op, ppfn)\
- fn_build_sub_function(op, ppfn, 0)
+int fn_build_function(P3(const ref * op, gs_function_t ** ppfn,
+ gs_memory_t *mem));
+int fn_build_sub_function(P4(const ref * op, gs_function_t ** ppfn,
+ int depth, gs_memory_t *mem));
/* Allocate an array of function objects. */
-int ialloc_function_array(P2(uint count, gs_function_t *** pFunctions));
+int alloc_function_array(P3(uint count, gs_function_t *** pFunctions,
+ gs_memory_t *mem));
/*
* Collect a heap-allocated array of floats. If the key is missing, set
@@ -53,7 +54,8 @@ int ialloc_function_array(P2(uint count, gs_function_t *** pFunctions));
* of elements. Note that 0-length arrays are acceptable, so if the value
* returned is 0, the caller must check whether *pparray == 0.
*/
-int fn_build_float_array(P5(const ref * op, const char *kstr, bool required,
- bool even, const float **pparray));
+int fn_build_float_array(P6(const ref * op, const char *kstr, bool required,
+ bool even, const float **pparray,
+ gs_memory_t *mem));
#endif /* ifunc_INCLUDED */
diff --git a/gs/src/ifwpred.h b/gs/src/ifwpred.h
new file mode 100644
index 000000000..33be68302
--- /dev/null
+++ b/gs/src/ifwpred.h
@@ -0,0 +1,30 @@
+/* Copyright (C) 1999 Aladdin Enterprises. All rights reserved.
+
+ This file is part of Aladdin Ghostscript.
+
+ Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
+ or distributor accepts any responsibility for the consequences of using it,
+ or for whether it serves any particular purpose or works at all, unless he
+ or she says so in writing. Refer to the Aladdin Ghostscript Free Public
+ License (the "License") for full details.
+
+ Every copy of Aladdin Ghostscript must include a copy of the License,
+ normally in a plain ASCII text file named PUBLIC. The License grants you
+ the right to copy, modify and redistribute Aladdin Ghostscript, but only
+ under certain conditions described in the License. Among other things, the
+ License requires that the copyright notice and this notice be preserved on
+ all copies.
+ */
+
+
+/* filter_read_predictor prototype */
+
+#ifndef ifwpred_INCLUDED
+# define ifwpred_INCLUDED
+
+/* Exported by zfilter2.c for zfzlib.c */
+int filter_write_predictor(P4(i_ctx_t *i_ctx_p, int npop,
+ const stream_template * template,
+ stream_state * st));
+
+#endif /* ifwpred_INCLUDED */
diff --git a/gs/src/igc.c b/gs/src/igc.c
index 2c407d62b..8b8e06ff0 100644
--- a/gs/src/igc.c
+++ b/gs/src/igc.c
@@ -90,19 +90,15 @@ private ptr_proc_unmark(ptr_struct_unmark);
private ptr_proc_mark(ptr_struct_mark);
private ptr_proc_unmark(ptr_string_unmark);
private ptr_proc_mark(ptr_string_mark);
-
- /*ptr_proc_unmark(ptr_ref_unmark); *//* in igc.h */
- /*ptr_proc_mark(ptr_ref_mark); *//* in igc.h */
+/*ptr_proc_unmark(ptr_ref_unmark); *//* in igc.h */
+/*ptr_proc_mark(ptr_ref_mark); *//* in igc.h */
private ptr_proc_reloc(igc_reloc_struct_ptr, void);
-string_proc_reloc(igc_reloc_string); /* in igcstr.c */
-const_string_proc_reloc(igc_reloc_const_string); /* in igcstr.c */
ptr_proc_reloc(igc_reloc_ref_ptr, ref_packed); /* in igcref.c */
refs_proc_reloc(igc_reloc_refs); /* in igcref.c */
/* Define this GC's procedure vector. */
-private const gc_procs_with_refs_t igc_procs =
-{
+private const gc_procs_with_refs_t igc_procs = {
igc_reloc_struct_ptr, igc_reloc_string, igc_reloc_const_string,
igc_reloc_ref_ptr, igc_reloc_refs
};
@@ -146,18 +142,30 @@ depth_dots(const ms_entry * sp, const gc_mark_stack * pms)
depth += pss->count - 1;
return depth_dots_string + (depth >= 10 ? 0 : 10 - depth);
}
-#else
+private void
+gc_validate_spaces(gs_ref_memory_t **spaces, int max_space, gc_state_t *gcst)
+{
+ int i;
+ gs_ref_memory_t *mem;
+
+ for (i = 1; i <= max_space; ++i)
+ if ((mem = spaces[i]) != 0)
+ ialloc_validate_memory(mem, gcst);
+}
+#else /* !DEBUG */
# define end_phase(str) DO_NOTHING
-#endif
+#endif /* DEBUG */
void
gs_gc_reclaim(vm_spaces * pspaces, bool global)
{
- vm_spaces spaces;
+#define nspaces ((i_vm_max + 1) * 2) /* * 2 for stable allocators */
-#define nspaces (i_vm_max + 1)
+ vm_spaces spaces;
+ gs_ref_memory_t *space_memories[nspaces];
gs_gc_root_t space_roots[nspaces];
- int max_trace; /* max space to trace */
- int min_collect; /* min space to collect */
+ int max_trace; /* max space_ to trace */
+ int min_collect; /* min space_ to collect */
+ int min_collect_vm_space; /* min VM space to collect */
int ispace;
gs_ref_memory_t *mem;
chunk_t *cp;
@@ -170,25 +178,39 @@ gs_gc_reclaim(vm_spaces * pspaces, bool global)
gc_mark_stack *mark_stack = &ms_default.stack;
/* Optionally force global GC for debugging. */
+
if (I_FORCE_GLOBAL_GC)
global = true;
- /* Determine which spaces we are collecting. */
+ /* Determine which spaces we are tracing and collecting. */
+
spaces = *pspaces;
- if (space_global != space_local)
- max_trace = i_vm_local;
- else
- max_trace = i_vm_global;
- min_collect = (global ? 1 : max_trace);
+ space_memories[1] = space_system;
+ space_memories[2] = space_global;
+ min_collect = max_trace = 2;
+ min_collect_vm_space = i_vm_global;
+ if (space_global->stable_memory != (gs_memory_t *)space_global)
+ space_memories[++max_trace] =
+ (gs_ref_memory_t *)space_global->stable_memory;
+ if (space_global != space_local) {
+ space_memories[++max_trace] = space_local;
+ min_collect = max_trace;
+ min_collect_vm_space = i_vm_local;
+ if (space_local->stable_memory != (gs_memory_t *)space_local)
+ space_memories[++max_trace] =
+ (gs_ref_memory_t *)space_local->stable_memory;
+ }
+ if (global)
+ min_collect = min_collect_vm_space = 1;
#define for_spaces(i, n)\
- for ( i = 1; i <= n; ++i )
+ for (i = 1; i <= n; ++i)
#define for_collected_spaces(i)\
- for ( i = min_collect; i <= max_trace; ++i )
+ for (i = min_collect; i <= max_trace; ++i)
#define for_space_mems(i, mem)\
- for ( mem = spaces_indexed[i]; mem != 0; mem = &mem->saved->state )
+ for (mem = space_memories[i]; mem != 0; mem = &mem->saved->state)
#define for_mem_chunks(mem, cp)\
- for ( cp = (mem)->cfirst; cp != 0; cp = cp->cnext )
+ for (cp = (mem)->cfirst; cp != 0; cp = cp->cnext)
#define for_space_chunks(i, mem, cp)\
for_space_mems(i, mem) for_mem_chunks(mem, cp)
#define for_chunks(n, mem, cp)\
@@ -197,15 +219,16 @@ gs_gc_reclaim(vm_spaces * pspaces, bool global)
for_collected_spaces(ispace) for_space_chunks(ispace, mem, cp)
#define for_roots(n, mem, rp)\
for_spaces(ispace, n)\
- for ( mem = spaces_indexed[ispace], rp = mem->roots; rp != 0; rp = rp->next )
+ for (mem = space_memories[ispace], rp = mem->roots; rp != 0; rp = rp->next)
/* Initialize the state. */
+
state.procs = &igc_procs;
state.loc.memory = space_global; /* any one will do */
state.loc.cp = 0;
state.spaces = spaces;
- state.min_collect = min_collect << r_space_shift;
+ state.min_collect = min_collect_vm_space << r_space_shift;
state.relocating_untraced = false;
state.heap = state.loc.memory->parent;
state.ntable = the_gs_name_table;
@@ -214,9 +237,9 @@ gs_gc_reclaim(vm_spaces * pspaces, bool global)
/* so we mark and relocate the change and save lists properly. */
for_spaces(ispace, max_trace)
- gs_register_struct_root((gs_memory_t *) spaces_indexed[ispace],
+ gs_register_struct_root((gs_memory_t *)space_memories[ispace],
&space_roots[ispace],
- (void **)&spaces_indexed[ispace],
+ (void **)&space_memories[ispace],
"gc_top_level");
end_phase("register space roots");
@@ -225,8 +248,7 @@ gs_gc_reclaim(vm_spaces * pspaces, bool global)
/* Pre-validate the state. This shouldn't be necessary.... */
- for_spaces(ispace, max_trace)
- ialloc_validate_memory(spaces_indexed[ispace], &state);
+ gc_validate_spaces(space_memories, max_trace, &state);
end_phase("pre-validate pointers");
@@ -235,6 +257,7 @@ gs_gc_reclaim(vm_spaces * pspaces, bool global)
if (I_BYPASS_GC) { /* Don't collect at all. */
goto no_collect;
}
+
/* Clear marks in spaces to be collected. */
for_collected_spaces(ispace)
@@ -249,10 +272,11 @@ gs_gc_reclaim(vm_spaces * pspaces, bool global)
/* since some roots are not in any chunk. */
for_roots(max_trace, mem, rp) {
- void *vptr = *rp->p;
+ enum_ptr_t eptr;
+ eptr.ptr = *rp->p;
if_debug_root('6', "[6]unmarking root", rp);
- (*rp->ptype->unmark) (vptr, &state);
+ (*rp->ptype->unmark)(&eptr, &state);
}
end_phase("clear root marks");
@@ -376,7 +400,7 @@ gs_gc_reclaim(vm_spaces * pspaces, bool global)
int i;
for_collected_spaces(i)
- gs_enable_free((gs_memory_t *) spaces_indexed[i], false);
+ gs_enable_free((gs_memory_t *)space_memories[i], false);
}
/* Compute relocation based on marks, in the spaces */
@@ -392,7 +416,7 @@ gs_gc_reclaim(vm_spaces * pspaces, bool global)
int i;
for_collected_spaces(i)
- gs_enable_free((gs_memory_t *) spaces_indexed[i], true);
+ gs_enable_free((gs_memory_t *)space_memories[i], true);
}
end_phase("set reloc");
@@ -446,9 +470,11 @@ gs_gc_reclaim(vm_spaces * pspaces, bool global)
/* Free empty chunks. */
- for_collected_spaces(ispace)
- for_space_mems(ispace, mem)
- gc_free_empty_chunks(mem);
+ for_collected_spaces(ispace) {
+ for_space_mems(ispace, mem) {
+ gc_free_empty_chunks(mem);
+ }
+ }
end_phase("free empty chunks");
@@ -467,7 +493,7 @@ gs_gc_reclaim(vm_spaces * pspaces, bool global)
alloc_save_t *next;
gs_memory_status_t total;
- for (curr = spaces_indexed[ispace]->saved; curr != 0;
+ for (curr = space_memories[ispace]->saved; curr != 0;
prev = curr, curr = next
) {
next = curr->state.saved;
@@ -489,7 +515,7 @@ gs_gc_reclaim(vm_spaces * pspaces, bool global)
mem->gc_allocated = mem->allocated + total.allocated;
mem->inherited = -mem->allocated;
}
- mem = spaces_indexed[ispace];
+ mem = space_memories[ispace];
mem->previous_status = total;
mem->gc_allocated = mem->allocated + total.allocated;
if_debug3('6', "[6]0x%lx previous allocated=%lu, used=%lu\n",
@@ -503,7 +529,7 @@ gs_gc_reclaim(vm_spaces * pspaces, bool global)
/* Unregister the allocator roots. */
for_spaces(ispace, max_trace)
- gs_unregister_root((gs_memory_t *) spaces_indexed[ispace],
+ gs_unregister_root((gs_memory_t *)space_memories[ispace],
&space_roots[ispace], "gc_top_level");
end_phase("unregister space roots");
@@ -512,8 +538,7 @@ gs_gc_reclaim(vm_spaces * pspaces, bool global)
/* Validate the state. This shouldn't be necessary.... */
- for_spaces(ispace, max_trace)
- ialloc_validate_memory(spaces_indexed[ispace], &state);
+ gc_validate_spaces(space_memories, max_trace, &state);
end_phase("validate pointers");
@@ -534,19 +559,19 @@ gs_gc_reclaim(vm_spaces * pspaces, bool global)
/* Unmark a single struct. */
private void
-ptr_struct_unmark(void *vptr, gc_state_t * ignored)
+ptr_struct_unmark(enum_ptr_t *pep, gc_state_t * ignored)
{
+ void *const vptr = (void *)pep->ptr; /* break const */
+
if (vptr != 0)
o_set_unmarked(((obj_header_t *) vptr - 1));
}
/* Unmark a single string. */
private void
-ptr_string_unmark(void *vptr, gc_state_t * gcst)
+ptr_string_unmark(enum_ptr_t *pep, gc_state_t * gcst)
{
- discard(gc_string_mark(((gs_string *) vptr)->data,
- ((gs_string *) vptr)->size,
- false, gcst));
+ discard(gc_string_mark(pep->ptr, pep->size, false, gcst));
}
/* Unmark the objects in a chunk. */
@@ -576,18 +601,18 @@ gc_objects_clear_marks(chunk_t * cp)
private void
gc_unmark_names(name_table * nt)
{
- register uint i;
+ uint i;
names_unmark_all(nt);
for (i = 0; i < op_array_table_global.count; i++) {
name_index_t nidx = op_array_table_global.nx_table[i];
- names_index_ptr(nt, nidx)->mark = 1;
+ names_mark_index(nt, nidx);
}
for (i = 0; i < op_array_table_local.count; i++) {
name_index_t nidx = op_array_table_local.nx_table[i];
- names_index_ptr(nt, nidx)->mark = 1;
+ names_mark_index(nt, nidx);
}
}
@@ -644,10 +669,11 @@ gc_rescan_chunk(chunk_t * cp, gc_state_t * pstate, gc_mark_stack * pmstack)
}
rp++;
} else {
- if (r_has_attr((ref *) rp, l_mark)) {
- r_clear_attrs((ref *) rp, l_mark);
- more |= gc_trace(&root, pstate,
- pmstack);
+ ref *const pref = (ref *)rp;
+
+ if (r_has_attr(pref, l_mark)) {
+ r_clear_attrs(pref, l_mark);
+ more |= gc_trace(&root, pstate, pmstack);
}
rp += packed_per_ref;
}
@@ -696,10 +722,11 @@ gc_trace_chunk(chunk_t * cp, gc_state_t * pstate, gc_mark_stack * pmstack)
if (r_is_packed(rp)) { /* No packed refs need tracing. */
rp++;
} else {
- if (r_space((ref *) rp) >= min_trace) {
- r_clear_attrs((ref *) rp, l_mark);
- more |= gc_trace(&root, pstate,
- pmstack);
+ ref *const pref = (ref *)rp;
+
+ if (r_space(pref) >= min_trace) {
+ r_clear_attrs(pref, l_mark);
+ more |= gc_trace(&root, pstate, pmstack);
}
rp += packed_per_ref;
}
@@ -739,17 +766,20 @@ gc_trace(gs_gc_root_t * rp, gc_state_t * pstate, gc_mark_stack * pmstack)
/* the entry beyond the top. */
ms_entry *stop = sp + pms->count - 2;
int new = 0;
- void *nptr = *rp->p;
+ enum_ptr_t nep;
+ void *nptr;
name_table *nt = pstate->ntable;
-#define mark_name(nidx, pname)\
- { if ( !pname->mark )\
- { pname->mark = 1;\
+#define mark_name(nidx)\
+ BEGIN\
+ if (names_mark_index(nt, nidx)) {\
new |= 1;\
- if_debug2('8', " [8]marked name 0x%lx(%u)\n", (ulong)pname, nidx);\
- }\
- }
+ if_debug2('8', " [8]marked name 0x%lx(%u)\n",\
+ (ulong)names_index_ptr(nt, nidx), nidx);\
+ }\
+ END
+ nptr = *rp->p;
if (nptr == 0)
return 0;
@@ -759,7 +789,8 @@ gc_trace(gs_gc_root_t * rp, gc_state_t * pstate, gc_mark_stack * pmstack)
sp->index = 1, sp->is_refs = true;
else {
sp->index = 0, sp->is_refs = false;
- if ((*rp->ptype->mark) (nptr, pstate))
+ nep.ptr = nptr;
+ if ((*rp->ptype->mark) (&nep, pstate))
new |= 1;
}
for (;;) {
@@ -794,28 +825,28 @@ gc_trace(gs_gc_root_t * rp, gc_state_t * pstate, gc_mark_stack * pmstack)
struct_type_name_string(ptr[-1].o_type),
(ulong) ptr, sp->index);
mproc = ptr[-1].o_type->enum_ptrs;
- /* The cast in the following statement is the one */
- /* place we need to break 'const' to make the */
- /* template for pointer enumeration work. */
if (mproc == gs_no_struct_enum_ptrs ||
(ptp = (*mproc)
(ptr, pre_obj_contents_size(ptr - 1),
- sp->index, (const void **)&nptr,
- ptr[-1].o_type, pstate)) == 0
+ sp->index, &nep, ptr[-1].o_type, pstate)) == 0
) {
if_debug0('7', " - done\n");
sp--;
continue;
}
+ /* The cast in the following statement is the one */
+ /* place we need to break 'const' to make the */
+ /* template for pointer enumeration work. */
+ nptr = (void *)nep.ptr;
sp->index++;
if_debug1('7', " = 0x%lx\n", (ulong) nptr);
- /* Descend into nptr, whose pointer type is ptp. */
+ /* Descend into nep.ptr, whose pointer type is ptp. */
if (ptp == ptr_struct_type) {
sp[1].index = 0;
sp[1].is_refs = false;
if (sp == stop)
goto push;
- if (!ptr_struct_mark(nptr, pstate))
+ if (!ptr_struct_mark(&nep, pstate))
goto ts;
new |= 1;
(++sp)->ptr = nptr;
@@ -830,7 +861,7 @@ gc_trace(gs_gc_root_t * rp, gc_state_t * pstate, gc_mark_stack * pmstack)
goto do_refs;
} else { /* We assume this is some non-pointer- */
/* containing type. */
- if ((*ptp->mark) (nptr, pstate))
+ if ((*ptp->mark) (&nep, pstate))
new |= 1;
goto ts;
}
@@ -850,25 +881,24 @@ gc_trace(gs_gc_root_t * rp, gc_state_t * pstate, gc_mark_stack * pmstack)
--(sp->index);
if_debug3('8', " [8]%smarking refs 0x%lx[%u]\n",
depth_dots(sp, pms), (ulong) pptr, sp->index);
- if (r_is_packed((ref *) pptr)) {
+ if (r_is_packed(pptr)) {
if (!r_has_pmark(pptr)) {
r_set_pmark(pptr);
new |= 1;
if (r_packed_is_name(pptr)) {
name_index_t nidx = packed_name_index(pptr);
- name *pname = names_index_ptr(nt, nidx);
- mark_name(nidx, pname);
+ mark_name(nidx);
}
}
++pptr;
goto tr;
}
- if (r_has_attr((ref *) pptr, l_mark)) {
- pptr = (ref_packed *) ((ref *) pptr + 1);
+ rptr = (ref *) pptr; /* * const beyond here */
+ if (r_has_attr(rptr, l_mark)) {
+ pptr = (ref_packed *)(rptr + 1);
goto tr;
}
- rptr = (ref *) pptr; /* * const beyond here */
r_set_attrs(rptr, l_mark);
new |= 1;
if (r_space(rptr) < min_trace) { /* Note that this always picks up all scalars. */
@@ -886,7 +916,8 @@ gc_trace(gs_gc_root_t * rp, gc_state_t * pstate, gc_mark_stack * pmstack)
ptp = ptr_struct_type;
break;
}
- if (!ptr_struct_mark(nptr, pstate))
+ nep.ptr = nptr;
+ if (!ptr_struct_mark(&nep, pstate))
goto nr;
new |= 1;
(++sp)->ptr = nptr;
@@ -932,7 +963,7 @@ gc_trace(gs_gc_root_t * rp, gc_state_t * pstate, gc_mark_stack * pmstack)
nptr = rptr->value.writable_packed;
goto rr;
case t_name:
- mark_name(names_index(nt, rptr), rptr->value.pname);
+ mark_name(names_index(nt, rptr));
nr:pptr = (ref_packed *) (rptr + 1);
goto tr;
case t_string:
@@ -965,7 +996,8 @@ gc_trace(gs_gc_root_t * rp, gc_state_t * pstate, gc_mark_stack * pmstack)
}
/* index and is_refs are already set */
if (!sp[1].is_refs) {
- if (!(*ptp->mark) (nptr, pstate))
+ nep.ptr = nptr;
+ if (!(*ptp->mark) (&nep, pstate))
continue;
new |= 1;
}
@@ -1017,11 +1049,11 @@ gc_extend_stack(gc_mark_stack * pms, gc_state_t * pstate)
/* Mark a struct. Return true if new mark. */
private bool
-ptr_struct_mark(void *vptr, gc_state_t * ignored)
+ptr_struct_mark(enum_ptr_t *pep, gc_state_t * ignored)
{
- obj_header_t *ptr = vptr;
+ obj_header_t *ptr = (obj_header_t *)pep->ptr;
- if (vptr == 0)
+ if (ptr == 0)
return false;
ptr--; /* point to header */
if (!o_is_unmarked(ptr))
@@ -1032,11 +1064,9 @@ ptr_struct_mark(void *vptr, gc_state_t * ignored)
/* Mark a string. Return true if new mark. */
private bool
-ptr_string_mark(void *vptr, gc_state_t * gcst)
+ptr_string_mark(enum_ptr_t *pep, gc_state_t * gcst)
{
- return gc_string_mark(((gs_string *) vptr)->data,
- ((gs_string *) vptr)->size,
- true, gcst);
+ return gc_string_mark(pep->ptr, pep->size, true, gcst);
}
/* Finish tracing by marking names. */
@@ -1048,17 +1078,21 @@ gc_trace_finish(gc_state_t * pstate)
bool marked = false;
while ((nidx = names_next_valid_index(nt, nidx)) != 0) {
- name *pname = names_index_ptr(nt, nidx);
+ name_string_t *pnstr = names_index_string_inline(nt, nidx);
+
+ if (pnstr->mark) {
+ enum_ptr_t enst, ensst;
- if (pname->mark) {
- if (!pname->foreign_string &&
- gc_string_mark(pname->string_bytes, pname->string_size,
+ if (!pnstr->foreign_string &&
+ gc_string_mark(pnstr->string_bytes, pnstr->string_size,
true, pstate)
)
marked = true;
+ enst.ptr = names_index_sub_table(nt, nidx);
+ ensst.ptr = names_index_string_sub_table(nt, nidx);
marked |=
- ptr_struct_mark(names_index_ptr_sub_table(nt, nidx, pname),
- pstate);
+ ptr_struct_mark(&enst, pstate) |
+ ptr_struct_mark(&ensst, pstate);
}
}
return marked;
@@ -1094,8 +1128,7 @@ gc_clear_reloc(chunk_t * cp)
if (procs != 0)
(*procs->clear_reloc) (pre, size);
o_set_untraced(pre);
- if (!pre->o_large)
- pre->o_back = ((byte *) pre - pfree) >> obj_back_shift;
+ pre->o_back = ((byte *) pre - pfree) >> obj_back_shift;
END_OBJECTS_SCAN
gc_strings_set_marks(cp, true);
gc_strings_clear_reloc(cp);
@@ -1128,26 +1161,14 @@ gc_objects_set_reloc(chunk_t * cp)
(ulong) (pre + 1));
(*finalize) (pre + 1);
}
- if (pre->o_large) { /* We should chop this up into small */
- /* free blocks, but there's no value */
- /* in doing this right now. */
- o_set_unmarked_large(pre);
- } else {
- pfree = (byte *) pre;
- pre->o_back =
- (pfree - (byte *) chead) >> obj_back_shift;
- pre->o_nreloc = reloc;
- }
+ pfree = (byte *) pre;
+ pre->o_back = (pfree - (byte *) chead) >> obj_back_shift;
+ pre->o_nreloc = reloc;
if_debug3('7', " [7]at 0x%lx, unmarked %lu, new reloc = %u\n",
(ulong) pre, (ulong) size, reloc);
} else { /* Useful object */
debug_check_object(pre, cp, NULL);
- if (pre->o_large) {
- if (o_is_unmarked_large(pre))
- o_mark_large(pre);
- } else
- pre->o_back =
- ((byte *) pre - pfree) >> obj_back_shift;
+ pre->o_back = ((byte *) pre - pfree) >> obj_back_shift;
}
END_OBJECTS_SCAN
#ifdef DEBUG
@@ -1174,20 +1195,18 @@ gc_do_reloc(chunk_t * cp, gs_ref_memory_t * mem, gc_state_t * pstate)
/* An object is free iff its back pointer points to */
/* the chunk_head structure. */
if (o_is_untraced(pre) ||
- (pre->o_large ? !o_is_unmarked(pre) :
- pre->o_back << obj_back_shift !=
- (byte *) pre - (byte *) chead)
- ) {
- struct_proc_reloc_ptrs((*proc)) =
- pre->o_type->reloc_ptrs;
-
- if_debug3('7',
- " [7]relocating ptrs in %s(%lu) 0x%lx\n",
- struct_type_name_string(pre->o_type),
- (ulong) size, (ulong) pre);
- if (proc != 0)
- (*proc) (pre + 1, size, pre->o_type, pstate);
- }
+ pre->o_back << obj_back_shift != (byte *) pre - (byte *) chead
+ ) {
+ struct_proc_reloc_ptrs((*proc)) =
+ pre->o_type->reloc_ptrs;
+
+ if_debug3('7',
+ " [7]relocating ptrs in %s(%lu) 0x%lx\n",
+ struct_type_name_string(pre->o_type),
+ (ulong) size, (ulong) pre);
+ if (proc != 0)
+ (*proc) (pre + 1, size, pre->o_type, pstate);
+ }
END_OBJECTS_SCAN
}
@@ -1215,11 +1234,7 @@ igc_reloc_struct_ptr(const void /*obj_header_t */ *obj, gc_state_t * gcst)
return 0;
}
debug_check_object(optr - 1, NULL, gcst);
- /* The following should be a conditional expression, */
- /* but Sun's cc compiler can't handle it. */
- if (optr[-1].o_large)
- robj = obj;
- else {
+ {
uint back = optr[-1].o_back;
if (back == o_untraced)
@@ -1270,12 +1285,8 @@ gc_objects_compact(chunk_t * cp, gc_state_t * gcst)
DO_ALL
/* An object is free iff its back pointer points to */
/* the chunk_head structure. */
- if ((pre->o_large ? !o_is_unmarked(pre) :
- pre->o_back << obj_back_shift !=
- (byte *) pre - (byte *) chead)
- ) {
- const struct_shared_procs_t *procs =
- pre->o_type->shared;
+ if (pre->o_back << obj_back_shift != (byte *) pre - (byte *) chead) {
+ const struct_shared_procs_t *procs = pre->o_type->shared;
debug_check_object(pre, cp, gcst);
if_debug4('7',
diff --git a/gs/src/igc.h b/gs/src/igc.h
index 565432b94..4b47c59a4 100644
--- a/gs/src/igc.h
+++ b/gs/src/igc.h
@@ -72,9 +72,8 @@ struct gc_state_s {
};
/* Exported by igcref.c for igc.c */
-void ptr_ref_unmark(P2(void *, gc_state_t *));
-bool ptr_ref_mark(P2(void *, gc_state_t *));
-
+ptr_proc_unmark(ptr_ref_unmark);
+ptr_proc_mark(ptr_ref_mark);
/*ref_packed *gs_reloc_ref_ptr(P2(const ref_packed *, gc_state_t *)); */
/* Exported by ilocate.c for igc.c */
diff --git a/gs/src/igcref.c b/gs/src/igcref.c
index 1ed921859..0a5e06266 100644
--- a/gs/src/igcref.c
+++ b/gs/src/igcref.c
@@ -75,7 +75,7 @@ ENUM_PTRS_BEGIN_PROC(ref_struct_enum_ptrs)
{
if (index >= size / sizeof(ref))
return 0;
- *pep = (ref *) vptr + index;
+ pep->ptr = (const ref *)vptr + index;
return ptr_ref_type;
ENUM_PTRS_END_PROC
}
@@ -92,12 +92,14 @@ RELOC_PTRS_BEGIN(ref_struct_reloc_ptrs)
/* Unmark a single ref. */
void
-ptr_ref_unmark(void *vptr, gc_state_t * ignored)
+ptr_ref_unmark(enum_ptr_t *pep, gc_state_t * ignored)
{
- if (r_is_packed((ref *) vptr))
- r_clear_pmark((ref_packed *) vptr);
+ ref_packed *rpp = (ref_packed *)pep->ptr;
+
+ if (r_is_packed(rpp))
+ r_clear_pmark(rpp);
else
- r_clear_attrs((ref *) vptr, l_mark);
+ r_clear_attrs((ref *)rpp, l_mark);
}
/* Unmarking routine for ref objects. */
@@ -122,14 +124,16 @@ refs_clear_marks(void /*obj_header_t */ *vptr, uint size,
r_clear_pmark(rp);
rp++;
} else { /* full-size ref */
+ ref *const pref = (ref *)rp;
+
#ifdef DEBUG
if (gs_debug_c('8')) {
dlprintf1(" [8]unmark ref 0x%lx ", (ulong) rp);
- debug_print_ref((ref *) rp);
+ debug_print_ref(pref);
dputs("\n");
}
#endif
- r_clear_attrs((ref *) rp, l_mark);
+ r_clear_attrs(pref, l_mark);
rp += packed_per_ref;
if (rp >= (ref_packed *) end)
break;
@@ -141,16 +145,20 @@ refs_clear_marks(void /*obj_header_t */ *vptr, uint size,
/* Mark a ref. Return true if new mark. */
bool
-ptr_ref_mark(void *vptr, gc_state_t * ignored)
+ptr_ref_mark(enum_ptr_t *pep, gc_state_t * ignored)
{
- if (r_is_packed(vptr)) {
- if (r_has_pmark((ref_packed *) vptr))
+ ref_packed *rpp = (void *)pep->ptr;
+
+ if (r_is_packed(rpp)) {
+ if (r_has_pmark(rpp))
return false;
- r_set_pmark((ref_packed *) vptr);
+ r_set_pmark(rpp);
} else {
- if (r_has_attr((ref *) vptr, l_mark))
+ ref *const pref = (ref *)rpp;
+
+ if (r_has_attr(pref, l_mark))
return false;
- r_set_attrs((ref *) vptr, l_mark);
+ r_set_attrs(pref, l_mark);
}
return true;
}
@@ -169,18 +177,19 @@ ptr_ref_mark(void *vptr, gc_state_t * ignored)
private void
refs_clear_reloc(obj_header_t * hdr, uint size)
{
- register ref_packed *rp = (ref_packed *) (hdr + 1);
+ ref_packed *rp = (ref_packed *) (hdr + 1);
ref_packed *end = (ref_packed *) ((byte *) rp + size);
while (rp < end) {
if (r_is_packed(rp))
rp++;
- else { /* full-size ref *//* Store the relocation here if possible. */
- if (!ref_type_uses_size_or_null(r_type((ref *) rp))) {
- if_debug1('8',
- " [8]clearing reloc at 0x%lx\n",
- (ulong) rp);
- r_set_size((ref *) rp, 0);
+ else {
+ /* Full-size ref. Store the relocation here if possible. */
+ ref *const pref = (ref *)rp;
+
+ if (!ref_type_uses_size_or_null(r_type(pref))) {
+ if_debug1('8', " [8]clearing reloc at 0x%lx\n", (ulong) rp);
+ r_set_size(pref, 0);
}
rp += packed_per_ref;
}
@@ -380,6 +389,17 @@ igc_reloc_refs(ref_packed * from, ref_packed * to, gc_state_t * gcst)
while (rp < to) {
ref *pref;
+#ifdef DEBUG
+ const void *before = 0;
+ const void *after = 0;
+# define DO_RELOC(var, stat)\
+ BEGIN before = (var); stat; after = (var); END
+# define SET_RELOC(var, expr)\
+ BEGIN before = (var); after = (var) = (expr); END
+#else
+# define DO_RELOC(var, stat) stat
+# define SET_RELOC(var, expr) var = expr
+#endif
if (r_is_packed(rp)) {
rp++;
@@ -388,49 +408,53 @@ igc_reloc_refs(ref_packed * from, ref_packed * to, gc_state_t * gcst)
/* The following assignment is logically unnecessary; */
/* we do it only for convenience in debugging. */
pref = (ref *) rp;
- if_debug3('8', " [8]relocating %s %d ref at 0x%lx\n",
+ if_debug3('8', " [8]relocating %s %d ref at 0x%lx",
(r_has_attr(pref, l_mark) ? "marked" : "unmarked"),
r_btype(pref), (ulong) pref);
if ((r_has_attr(pref, l_mark) || do_all) &&
r_space(pref) >= min_trace
- )
+ ) {
switch (r_type(pref)) {
/* Struct cases */
case t_file:
- RELOC_VAR(pref->value.pfile);
+ DO_RELOC(pref->value.pfile, RELOC_VAR(pref->value.pfile));
break;
case t_device:
- RELOC_VAR(pref->value.pdevice);
+ DO_RELOC(pref->value.pdevice,
+ RELOC_VAR(pref->value.pdevice));
break;
case t_fontID:
case t_struct:
case t_astruct:
- RELOC_VAR(pref->value.pstruct);
+ DO_RELOC(pref->value.pstruct,
+ RELOC_VAR(pref->value.pstruct));
break;
/* Non-trivial non-struct cases */
case t_dictionary:
rputc('d');
- pref->value.pdict =
- (dict *) igc_reloc_ref_ptr((ref_packed *) pref->value.pdict, gcst);
+ SET_RELOC(pref->value.pdict,
+ (dict *)igc_reloc_ref_ptr((ref_packed *)pref->value.pdict, gcst));
break;
case t_array:
{
uint size = r_size(pref);
- if (size != 0) { /* value.refs might be NULL *//*
- * If the array is large, we allocated it in its
- * own object (at least originally -- this might
- * be a pointer to a subarray.) In this case,
- * we know it is the only object in its
- * containing st_refs object, so we know that
- * the mark containing the relocation appears
- * just after it.
- */
+ if (size != 0) { /* value.refs might be NULL */
+
+ /*
+ * If the array is large, we allocated it in its
+ * own object (at least originally -- this might
+ * be a pointer to a subarray.) In this case,
+ * we know it is the only object in its
+ * containing st_refs object, so we know that
+ * the mark containing the relocation appears
+ * just after it.
+ */
if (size < max_size_st_refs / sizeof(ref)) {
rputc('a');
- pref->value.refs =
+ SET_RELOC(pref->value.refs,
(ref *) igc_reloc_ref_ptr(
- (ref_packed *) pref->value.refs, gcst);
+ (ref_packed *) pref->value.refs, gcst));
} else {
rputc('A');
/*
@@ -438,10 +462,10 @@ igc_reloc_refs(ref_packed * from, ref_packed * to, gc_state_t * gcst)
* decrement size.
*/
--size;
- pref->value.refs =
+ SET_RELOC(pref->value.refs,
(ref *) igc_reloc_ref_ptr(
(ref_packed *) (pref->value.refs + size),
- gcst) - size;
+ gcst) - size);
}
}
}
@@ -449,8 +473,8 @@ igc_reloc_refs(ref_packed * from, ref_packed * to, gc_state_t * gcst)
case t_mixedarray:
if (r_size(pref) != 0) { /* value.refs might be NULL */
rputc('m');
- pref->value.packed =
- igc_reloc_ref_ptr(pref->value.packed, gcst);
+ SET_RELOC(pref->value.packed,
+ igc_reloc_ref_ptr(pref->value.packed, gcst));
}
break;
case t_shortarray:
@@ -477,9 +501,9 @@ igc_reloc_refs(ref_packed * from, ref_packed * to, gc_state_t * gcst)
* array, rather than just beyond it.
*/
--size;
- pref->value.packed =
+ SET_RELOC(pref->value.packed,
igc_reloc_ref_ptr(pref->value.packed + size,
- gcst) - size;
+ gcst) - size);
}
}
break;
@@ -488,8 +512,10 @@ igc_reloc_refs(ref_packed * from, ref_packed * to, gc_state_t * gcst)
void *psub = name_ref_sub_table(pref);
void *rsub = RELOC_OBJ(psub); /* gcst implicit */
- pref->value.pname = (name *)
- ((char *)rsub + ((char *)pref->value.pname - (char *)psub));
+ SET_RELOC(pref->value.pname,
+ (name *)
+ ((char *)rsub + ((char *)pref->value.pname -
+ (char *)psub)));
} break;
case t_string:
{
@@ -498,16 +524,22 @@ igc_reloc_refs(ref_packed * from, ref_packed * to, gc_state_t * gcst)
str.data = pref->value.bytes;
str.size = r_size(pref);
- RELOC_STRING_VAR(str);
+ DO_RELOC(str.data, RELOC_STRING_VAR(str));
pref->value.bytes = str.data;
}
break;
case t_oparray:
rputc('o');
- pref->value.const_refs =
- (const ref *)igc_reloc_ref_ptr((const ref_packed *)pref->value.const_refs, gcst);
+ SET_RELOC(pref->value.const_refs,
+ (const ref *)igc_reloc_ref_ptr((const ref_packed *)pref->value.const_refs, gcst));
break;
+ default:
+ goto no_reloc; /* don't print trace message */
}
+ if_debug2('8', ", 0x%lx => 0x%lx", (ulong)before, (ulong)after);
+ }
+no_reloc:
+ if_debug0('8', "\n");
rp += packed_per_ref;
}
}
@@ -521,8 +553,14 @@ igc_reloc_ref_ptr(const ref_packed * prp, gc_state_t * ignored)
* Search forward for relocation. This algorithm is intrinsically very
* inefficient; we hope eventually to replace it with a better one.
*/
- register const ref_packed *rp = prp;
+ const ref_packed *rp = prp;
uint dec = 0;
+#ifdef ALIGNMENT_ALIASING_BUG
+ const ref *rpref;
+# define RP_REF(rp) (rpref = (const ref *)rp, rpref)
+#else
+# define RP_REF(rp) ((const ref *)rp)
+#endif
/*
* Iff this pointer points into a space that wasn't traced,
@@ -533,10 +571,11 @@ igc_reloc_ref_ptr(const ref_packed * prp, gc_state_t * ignored)
if (!r_has_pmark(rp))
goto ret_rp;
} else {
- if (!r_has_attr((const ref *)rp, l_mark))
+ if (!r_has_attr(RP_REF(rp), l_mark))
goto ret_rp;
}
for (;;) {
+
if (r_is_packed(rp)) {
/*
* Normally, an unmarked packed ref will be an
@@ -548,7 +587,8 @@ igc_reloc_ref_ptr(const ref_packed * prp, gc_state_t * ignored)
*/
rputc((*rp & lp_mark ? '1' : '0'));
if (!(*rp & lp_mark)) {
- if (*rp != pt_tag(pt_integer) + packed_max_value) { /* This is a stored relocation value. */
+ if (*rp != pt_tag(pt_integer) + packed_max_value) {
+ /* This is a stored relocation value. */
rputc('\n');
rp = print_reloc(prp, "ref",
(const ref_packed *)
@@ -567,12 +607,14 @@ igc_reloc_ref_ptr(const ref_packed * prp, gc_state_t * ignored)
rp++;
continue;
}
- if (!ref_type_uses_size_or_null(r_type((const ref *)rp))) { /* reloc is in r_size */
+ if (!ref_type_uses_size_or_null(r_type(RP_REF(rp)))) {
+ /* reloc is in r_size */
rputc('\n');
rp = print_reloc(prp, "ref",
(const ref_packed *)
- (r_size((const ref *)rp) == 0 ? prp :
- (const ref_packed *)((const char *)prp - r_size((const ref *)rp) + dec)));
+ (r_size(RP_REF(rp)) == 0 ? prp :
+ (const ref_packed *)((const char *)prp -
+ r_size(RP_REF(rp)) + dec)));
break;
}
rputc('u');
@@ -617,11 +659,12 @@ refs_compact(obj_header_t * pre, obj_header_t * dpre, uint size)
*src &= ~lp_mark;
src++;
} else { /* full-size ref */
- if (!r_has_attr((ref *) src, l_mark))
+ ref *const pref = (ref *)src;
+
+ if (!r_has_attr(pref, l_mark))
break;
- if_debug1('8', " [8]ref 0x%lx \"copied\"\n",
- (ulong) src);
- r_clear_attrs((ref *) src, l_mark);
+ if_debug1('8', " [8]ref 0x%lx \"copied\"\n", (ulong) src);
+ r_clear_attrs(pref, l_mark);
src += packed_per_ref;
}
} else
@@ -680,7 +723,7 @@ refs_compact(obj_header_t * pre, obj_header_t * dpre, uint size)
} else {
obj_header_t *pfree = (obj_header_t *) ((ref *) dest + 1);
- pfree->o_large = 0;
+ pfree->o_alone = 0;
pfree->o_size = size - new_size - sizeof(obj_header_t);
pfree->o_type = &st_bytes;
}
diff --git a/gs/src/igcstr.h b/gs/src/igcstr.h
index 0cf403a40..d0b2fe048 100644
--- a/gs/src/igcstr.h
+++ b/gs/src/igcstr.h
@@ -31,5 +31,7 @@ bool gc_string_mark(P4(const byte *, uint, bool, gc_state_t *));
void gc_strings_clear_reloc(P1(chunk_t *));
void gc_strings_set_reloc(P1(chunk_t *));
void gc_strings_compact(P1(chunk_t *));
+string_proc_reloc(igc_reloc_string);
+const_string_proc_reloc(igc_reloc_const_string);
#endif /* igcstr_INCLUDED */
diff --git a/gs/src/iimage.h b/gs/src/iimage.h
index 4636fc5c0..e53d4b671 100644
--- a/gs/src/iimage.h
+++ b/gs/src/iimage.h
@@ -24,7 +24,7 @@
/* These procedures are exported by zimage.c for other modules. */
-/* Exported for zcolor1.c and zdpnext.c */
+/* Exported for zcolor1.c */
int zimage_opaque_setup(P6(i_ctx_t *i_ctx_p, os_ptr op, bool multi,
gs_image_alpha_t alpha, const gs_color_space * pcs,
int npop));
@@ -38,4 +38,7 @@ int zimage_data_setup(P5(i_ctx_t *i_ctx_p, const gs_pixel_image_t * pim,
gx_image_enum_common_t * pie,
const ref * sources, int npop));
+/* Exported for zcolor1.c and zdpnext.c. */
+int zimage_multiple(P2(i_ctx_t *i_ctx_p, bool has_alpha));
+
#endif /* iimage_INCLUDED */
diff --git a/gs/src/iimage2.h b/gs/src/iimage2.h
index e8e5969f1..f742c2137 100644
--- a/gs/src/iimage2.h
+++ b/gs/src/iimage2.h
@@ -42,4 +42,13 @@ int pixel_image_params(P5(i_ctx_t *i_ctx_p, const ref *op,
gs_pixel_image_t *pim, image_params * pip,
int max_bits_per_component));
+/*
+ * Process an image that has no explicit source data. This isn't used by
+ * standard Level 2, but it's a very small procedure and is needed by
+ * both zdps.c and zdpnext.c.
+ */
+int process_non_source_image(P3(i_ctx_t *i_ctx_p,
+ const gs_image_common_t * pim,
+ client_name_t cname));
+
#endif /* iimage2_INCLUDED */
diff --git a/gs/src/iinit.c b/gs/src/iinit.c
index 5814d9484..5a95d9638 100644
--- a/gs/src/iinit.c
+++ b/gs/src/iinit.c
@@ -28,6 +28,7 @@
#include "iddict.h"
#include "dstack.h"
#include "ilevel.h"
+#include "iinit.h"
#include "iname.h"
#include "interp.h"
#include "ipacked.h"
@@ -88,7 +89,7 @@ const char *const gs_error_names[] =
op_array_table op_array_table_global, op_array_table_local; /* definitions of `operator' procedures */
/* Enter a name and value into a dictionary. */
-void
+private void
i_initial_enter_name_in(i_ctx_t *i_ctx_p, ref *pdict, const char *nstr,
const ref * pref)
{
@@ -226,7 +227,7 @@ make_initial_dict(i_ctx_t *i_ctx_p, const char *iname, ref idicts[])
/* Initialize objects other than operators. In particular, */
/* initialize the dictionaries that hold operator definitions. */
void
-obj_init(i_ctx_t **pi_ctx_p)
+obj_init(i_ctx_t **pi_ctx_p, gs_dual_memory_t *idmem)
{
bool level2 = gs_have_level2();
ref system_dict;
@@ -236,12 +237,12 @@ obj_init(i_ctx_t **pi_ctx_p)
* Create systemdict. The context machinery requires that
* we do this before initializing the interpreter.
*/
- dict_alloc(iimemory_global,
+ dict_alloc(idmem->space_global,
(level2 ? SYSTEMDICT_LEVEL2_SIZE : SYSTEMDICT_SIZE),
&system_dict);
/* Initialize the interpreter. */
- gs_interp_init(pi_ctx_p, &system_dict);
+ gs_interp_init(pi_ctx_p, &system_dict, idmem);
i_ctx_p = *pi_ctx_p;
{
@@ -385,7 +386,8 @@ zop_init(i_ctx_t *i_ctx_p)
/* Create an op_array table. */
private int
-alloc_op_array_table(uint size, uint space, op_array_table * opt)
+alloc_op_array_table(i_ctx_t *i_ctx_p, uint size, uint space,
+ op_array_table *opt)
{
uint save_space = ialloc_space(idmemory);
int code;
@@ -459,7 +461,7 @@ op_init(i_ctx_t *i_ctx_p)
/* Allocate the tables for `operator' procedures. */
/* Make one of them local so we can have local operators. */
- if (alloc_op_array_table(OP_ARRAY_TABLE_GLOBAL_SIZE,
+ if (alloc_op_array_table(i_ctx_p, OP_ARRAY_TABLE_GLOBAL_SIZE,
avm_global, &op_array_table_global) < 0)
gs_abort();
op_array_table_global.base_index = op_def_count;
@@ -470,7 +472,7 @@ op_init(i_ctx_t *i_ctx_p)
(void **)&op_array_table_global.nx_table,
"op_array nx_table(global)");
- if (alloc_op_array_table(OP_ARRAY_TABLE_LOCAL_SIZE,
+ if (alloc_op_array_table(i_ctx_p, OP_ARRAY_TABLE_LOCAL_SIZE,
avm_local, &op_array_table_local) < 0)
gs_abort();
op_array_table_local.base_index =
diff --git a/gs/src/iinit.h b/gs/src/iinit.h
new file mode 100644
index 000000000..f98472eed
--- /dev/null
+++ b/gs/src/iinit.h
@@ -0,0 +1,40 @@
+/* Copyright (C) 1999 Aladdin Enterprises. All rights reserved.
+
+ This file is part of Aladdin Ghostscript.
+
+ Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
+ or distributor accepts any responsibility for the consequences of using it,
+ or for whether it serves any particular purpose or works at all, unless he
+ or she says so in writing. Refer to the Aladdin Ghostscript Free Public
+ License (the "License") for full details.
+
+ Every copy of Aladdin Ghostscript must include a copy of the License,
+ normally in a plain ASCII text file named PUBLIC. The License grants you
+ the right to copy, modify and redistribute Aladdin Ghostscript, but only
+ under certain conditions described in the License. Among other things, the
+ License requires that the copyright notice and this notice be preserved on
+ all copies.
+ */
+
+
+/* (Internal) interface to iinit.c */
+
+#ifndef iinit_INCLUDED
+# define iinit_INCLUDED
+
+/*
+ * Declare initialization procedures exported by iinit.c for imain.c.
+ * These must be executed in the order they are declared below.
+ */
+void obj_init(P2(i_ctx_t **, gs_dual_memory_t *));
+void zop_init(P1(i_ctx_t *));
+void op_init(P1(i_ctx_t *));
+
+/*
+ * Test whether there are any Level 2 operators in the executable.
+ * (This is different from the language level in which the interpreter is
+ * actually running: it is only tested during initialization.)
+ */
+bool gs_have_level2(P0());
+
+#endif /* iinit_INCLUDED */
diff --git a/gs/src/ilocate.c b/gs/src/ilocate.c
index b469ef0e2..b42686d58 100644
--- a/gs/src/ilocate.c
+++ b/gs/src/ilocate.c
@@ -42,19 +42,46 @@ chunk_t *
gc_locate(const void *ptr, gc_state_t * gcst)
{
const gs_ref_memory_t *mem;
+ const gs_ref_memory_t *other;
if (chunk_locate(ptr, &gcst->loc))
return gcst->loc.cp;
mem = gcst->loc.memory;
- /* Try the other space, if there is one. */
+ /*
+ * Try the stable allocator of this space, or, if the current memory
+ * is the stable one, the non-stable allocator of this space.
+ */
+
+ if ((other = (const gs_ref_memory_t *)mem->stable_memory) != mem ||
+ (other = gcst->spaces_indexed[mem->space >> r_space_shift]) != mem
+ ) {
+ gcst->loc.memory = other;
+ gcst->loc.cp = 0;
+ if (chunk_locate(ptr, &gcst->loc))
+ return gcst->loc.cp;
+ }
+
+ /*
+ * Try the other space, if there is one, including its stable allocator
+ * and all save levels. (If the original space is system space, try
+ * local space.)
+ */
if (gcst->space_local != gcst->space_global) {
- gcst->loc.memory =
+ gcst->loc.memory = other =
(mem->space == avm_local ? gcst->space_global : gcst->space_local);
gcst->loc.cp = 0;
if (chunk_locate(ptr, &gcst->loc))
return gcst->loc.cp;
+ /* Try its stable allocator. */
+ if (other->stable_memory != (const gs_memory_t *)other) {
+ gcst->loc.memory = (gs_ref_memory_t *)other->stable_memory;
+ gcst->loc.cp = 0;
+ if (chunk_locate(ptr, &gcst->loc))
+ return gcst->loc.cp;
+ gcst->loc.memory = other;
+ }
/* Try other save levels of this space. */
while (gcst->loc.memory->saved != 0) {
gcst->loc.memory = &gcst->loc.memory->saved->state;
@@ -66,7 +93,7 @@ gc_locate(const void *ptr, gc_state_t * gcst)
/*
* Try system space. This is simpler because it isn't subject to
- * save/restore.
+ * save/restore and doesn't have a separate stable allocator.
*/
if (mem != gcst->space_system) {
@@ -79,12 +106,27 @@ gc_locate(const void *ptr, gc_state_t * gcst)
/*
* Try other save levels of the initial space, or of global space if the
* original space was system space. In the latter case, try all
- * levels.
+ * levels, and its stable allocator.
*/
- gcst->loc.memory =
- (mem == gcst->space_system || mem->space == avm_global ?
- gcst->space_global : gcst->space_local);
+ switch (mem->space) {
+ default: /* system */
+ other = gcst->space_global;
+ if (other->stable_memory != (const gs_memory_t *)other) {
+ gcst->loc.memory = (gs_ref_memory_t *)other->stable_memory;
+ gcst->loc.cp = 0;
+ if (chunk_locate(ptr, &gcst->loc))
+ return gcst->loc.cp;
+ }
+ gcst->loc.memory = other;
+ break;
+ case avm_global:
+ gcst->loc.memory = gcst->space_global;
+ break;
+ case avm_local:
+ gcst->loc.memory = gcst->space_local;
+ break;
+ }
for (;;) {
if (gcst->loc.memory != mem) { /* don't do twice */
gcst->loc.cp = 0;
@@ -96,7 +138,7 @@ gc_locate(const void *ptr, gc_state_t * gcst)
gcst->loc.memory = &gcst->loc.memory->saved->state;
}
- /* Restore locator to a legal state. */
+ /* Restore locator to a legal state and report failure. */
gcst->loc.memory = mem;
gcst->loc.cp = 0;
@@ -107,17 +149,56 @@ gc_locate(const void *ptr, gc_state_t * gcst)
#ifdef DEBUG
+/* Define the structure for temporarily saving allocator state. */
+typedef struct alloc_temp_save_s {
+ chunk_t cc;
+ uint rsize;
+ ref rlast;
+} alloc_temp_save_t;
+/* Temporarily save the state of an allocator. */
+private void
+alloc_temp_save(alloc_temp_save_t *pats, gs_ref_memory_t *mem)
+{
+ chunk_t *pcc = mem->pcc;
+ obj_header_t *rcur = mem->cc.rcur;
+
+ if (pcc != 0) {
+ pats->cc = *pcc;
+ *pcc = mem->cc;
+ }
+ if (rcur != 0) {
+ pats->rsize = rcur[-1].o_size;
+ rcur[-1].o_size = mem->cc.rtop - (byte *) rcur;
+ /* Create the final ref, reserved for the GC. */
+ pats->rlast = ((ref *) mem->cc.rtop)[-1];
+ make_mark((ref *) mem->cc.rtop - 1);
+ }
+}
+/* Restore the temporarily saved state. */
+private void
+alloc_temp_restore(alloc_temp_save_t *pats, gs_ref_memory_t *mem)
+{
+ chunk_t *pcc = mem->pcc;
+ obj_header_t *rcur = mem->cc.rcur;
+
+ if (rcur != 0) {
+ rcur[-1].o_size = pats->rsize;
+ ((ref *) mem->cc.rtop)[-1] = pats->rlast;
+ }
+ if (pcc != 0)
+ *pcc = pats->cc;
+}
+
/* Validate the contents of an allocator. */
void
ialloc_validate_spaces(const gs_dual_memory_t * dmem)
{
int i;
gc_state_t state;
- struct sm_ {
- chunk_t cc;
- uint rsize;
- ref rlast;
- } save[countof(dmem->spaces_indexed)];
+ alloc_temp_save_t
+ save[countof(dmem->spaces_indexed)],
+ save_stable[countof(dmem->spaces_indexed)];
+ gs_ref_memory_t *mem;
state.spaces = dmem->spaces;
state.loc.memory = state.space_local;
@@ -126,44 +207,31 @@ ialloc_validate_spaces(const gs_dual_memory_t * dmem)
/* Save everything we need to reset temporarily. */
for (i = 0; i < countof(save); i++)
- if (dmem->spaces_indexed[i] != 0) {
- gs_ref_memory_t *mem = dmem->spaces_indexed[i];
- chunk_t *pcc = mem->pcc;
- obj_header_t *rcur = mem->cc.rcur;
-
- if (pcc != 0) {
- save[i].cc = *pcc;
- *pcc = mem->cc;
- }
- if (rcur != 0) {
- save[i].rsize = rcur[-1].o_size;
- rcur[-1].o_size = mem->cc.rtop - (byte *) rcur;
- /* Create the final ref, reserved for the GC. */
- save[i].rlast = ((ref *) mem->cc.rtop)[-1];
- make_mark((ref *) mem->cc.rtop - 1);
- }
+ if ((mem = dmem->spaces_indexed[i]) != 0) {
+ alloc_temp_save(&save[i], mem);
+ if (mem->stable_memory != (gs_memory_t *)mem)
+ alloc_temp_save(&save_stable[i],
+ (gs_ref_memory_t *)mem->stable_memory);
}
/* Validate memory. */
for (i = 0; i < countof(save); i++)
- if (dmem->spaces_indexed[i] != 0)
- ialloc_validate_memory(dmem->spaces_indexed[i], &state);
+ if ((mem = dmem->spaces_indexed[i]) != 0) {
+ ialloc_validate_memory(mem, &state);
+ if (mem->stable_memory != (gs_memory_t *)mem)
+ ialloc_validate_memory((gs_ref_memory_t *)mem->stable_memory,
+ &state);
+ }
/* Undo temporary changes. */
for (i = 0; i < countof(save); i++)
- if (dmem->spaces_indexed[i] != 0) {
- gs_ref_memory_t *mem = dmem->spaces_indexed[i];
- chunk_t *pcc = mem->pcc;
- obj_header_t *rcur = mem->cc.rcur;
-
- if (rcur != 0) {
- rcur[-1].o_size = save[i].rsize;
- ((ref *) mem->cc.rtop)[-1] = save[i].rlast;
- }
- if (pcc != 0)
- *pcc = save[i].cc;
+ if ((mem = dmem->spaces_indexed[i]) != 0) {
+ if (mem->stable_memory != (gs_memory_t *)mem)
+ alloc_temp_restore(&save_stable[i],
+ (gs_ref_memory_t *)mem->stable_memory);
+ alloc_temp_restore(&save[i], mem);
}
}
void
@@ -214,12 +282,13 @@ ialloc_validate_memory(const gs_ref_memory_t * mem, gc_state_t * gcst)
inline private bool
object_size_valid(const obj_header_t * pre, uint size, const chunk_t * cp)
{
- return (pre->o_large ? (const byte *)pre == cp->cbase :
+ return (pre->o_alone ? (const byte *)pre == cp->cbase :
size <= cp->ctop - (const byte *)(pre + 1));
}
/* Validate all the objects in a chunk. */
private void ialloc_validate_ref(P2(const ref *, gc_state_t *));
+private void ialloc_validate_ref_packed(P2(const ref_packed *, gc_state_t *));
void
ialloc_validate_chunk(const chunk_t * cp, gc_state_t * gcst)
{
@@ -239,36 +308,41 @@ ialloc_validate_chunk(const chunk_t * cp, gc_state_t * gcst)
const ref_packed *rp = (const ref_packed *)(pre + 1);
const char *end = (const char *)rp + size;
- while ((const char *)rp < end)
- if (r_is_packed(rp)) {
- ref unpacked;
-
- packed_get(rp, &unpacked);
- ialloc_validate_ref(&unpacked, gcst);
- rp++;
- } else {
- ialloc_validate_ref((const ref *)rp, gcst);
- rp += packed_per_ref;
- }
+ while ((const char *)rp < end) {
+ ialloc_validate_ref_packed(rp, gcst);
+ rp = packed_next(rp);
+ }
} else {
struct_proc_enum_ptrs((*proc)) = pre->o_type->enum_ptrs;
uint index = 0;
- const void *ptr;
+ enum_ptr_t eptr;
gs_ptr_type_t ptype;
if (proc != gs_no_struct_enum_ptrs)
- for (; (ptype = (*proc) (pre + 1, size, index, &ptr, pre->o_type, NULL)) != 0; ++index)
- if (ptr == 0)
+ for (; (ptype = (*proc) (pre + 1, size, index, &eptr, pre->o_type, NULL)) != 0; ++index)
+ if (eptr.ptr == 0)
DO_NOTHING;
else if (ptype == ptr_struct_type)
- ialloc_validate_object(ptr, NULL, gcst);
+ ialloc_validate_object(eptr.ptr, NULL, gcst);
else if (ptype == ptr_ref_type)
- ialloc_validate_ref(ptr, gcst);
+ ialloc_validate_ref_packed(eptr.ptr, gcst);
}
END_OBJECTS_SCAN
}
/* Validate a ref. */
private void
+ialloc_validate_ref_packed(const ref_packed * rp, gc_state_t * gcst)
+{
+ if (r_is_packed(rp)) {
+ ref unpacked;
+
+ packed_get(rp, &unpacked);
+ ialloc_validate_ref(&unpacked, gcst);
+ } else {
+ ialloc_validate_ref((const ref *)rp, gcst);
+ }
+}
+private void
ialloc_validate_ref(const ref * pref, gc_state_t * gcst)
{
const void *optr;
diff --git a/gs/src/imain.c b/gs/src/imain.c
index 75095ec1e..85075321b 100644
--- a/gs/src/imain.c
+++ b/gs/src/imain.c
@@ -22,8 +22,8 @@
#include "string_.h"
/* Capture stdin/out/err before gs.h redefines them. */
#include <stdio.h>
-void
-gs_get_real_stdio(FILE * stdfiles[3])
+private void
+set_stdfiles(FILE * stdfiles[3])
{
stdfiles[0] = stdin;
stdfiles[1] = stdout;
@@ -46,6 +46,7 @@ gs_get_real_stdio(FILE * stdfiles[3])
#include "stream.h" /* for files.h */
#include "files.h"
#include "ialloc.h"
+#include "iinit.h"
#include "strimpl.h" /* for sfilter.h */
#include "sfilter.h" /* for iscan.h */
#include "iscan.h"
@@ -96,6 +97,13 @@ private void print_resource_usage(P3(const gs_main_instance *,
/* ------ Initialization ------ */
+/* Save the real stdio files. */
+void
+gs_get_real_stdio(FILE * stdfiles[3])
+{
+ set_stdfiles(stdfiles);
+}
+
/* Initialization to be done before anything else. */
void
gs_main_init0(gs_main_instance * minst, FILE * in, FILE * out, FILE * err,
@@ -134,18 +142,16 @@ void
gs_main_init1(gs_main_instance * minst)
{
if (minst->init_done < 1) {
- {
- extern bool gs_have_level2(P0());
+ gs_dual_memory_t idmem;
- ialloc_init(idmemory, (gs_raw_memory_t *)&gs_memory_default,
- minst->memory_chunk_size, gs_have_level2());
- gs_lib_init1((gs_memory_t *) imemory_system);
- alloc_save_init(idmemory);
- }
+ ialloc_init(&idmem, (gs_raw_memory_t *)&gs_memory_default,
+ minst->memory_chunk_size, gs_have_level2());
+ gs_lib_init1((gs_memory_t *)idmem.space_system);
+ alloc_save_init(&idmem);
{
- gs_memory_t *mem = imemory_system;
+ gs_memory_t *mem = (gs_memory_t *)idmem.space_system;
name_table *nt = names_init(minst->name_table_size,
- iimemory_system);
+ idmem.space_system);
if (nt == 0) {
puts("name_init failed");
@@ -155,11 +161,7 @@ gs_main_init1(gs_main_instance * minst)
gs_register_struct_root(mem, NULL, (void **)&the_gs_name_table,
"the_gs_name_table");
}
- {
- extern void obj_init(P1(i_ctx_t **));
-
- obj_init(&minst->i_ctx_p); /* requires name_init */
- }
+ obj_init(&minst->i_ctx_p, &idmem); /* requires name_init */
minst->init_done = 1;
}
}
@@ -179,27 +181,27 @@ init2_make_string_array(i_ctx_t *i_ctx_p, const ref * srefs, const char *aname)
void
gs_main_init2(gs_main_instance * minst)
{
+ i_ctx_t *i_ctx_p;
+
gs_main_init1(minst);
+ i_ctx_p = minst->i_ctx_p;
if (minst->init_done < 2) {
- i_ctx_t *i_ctx_p = minst->i_ctx_p;
int code, exit_code;
ref error_object;
+ zop_init(i_ctx_p);
{
- extern void zop_init(P1(i_ctx_t *));
-
- zop_init(i_ctx_p);
- }
- {
+ /*
+ * gs_iodev_init has to be called here (late), rather than
+ * with the rest of the library init procedures, because of
+ * some hacks specific to MS Windows for patching the
+ * stdxxx IODevices.
+ */
extern void gs_iodev_init(P1(gs_memory_t *));
gs_iodev_init(imemory);
}
- {
- extern void op_init(P1(i_ctx_t *));
-
- op_init(i_ctx_p); /* requires obj_init */
- }
+ op_init(i_ctx_p); /* requires obj_init */
/* Set up the array of additional initialization files. */
init2_make_string_array(i_ctx_p, gs_init_file_array, "INITFILES");
@@ -216,6 +218,7 @@ gs_main_init2(gs_main_instance * minst)
gs_exit_with_code((exit_code ? exit_code : 2), code);
}
minst->init_done = 2;
+ i_ctx_p = minst->i_ctx_p; /* init file may change it */
}
if (gs_debug_c(':'))
print_resource_usage(minst, &gs_imemory, "Start");
@@ -314,14 +317,16 @@ gs_main_set_lib_paths(gs_main_instance * minst)
/* Open a file, using the search paths. */
int
gs_main_lib_open(gs_main_instance * minst, const char *file_name, ref * pfile)
-{ /* This is a separate procedure only to avoid tying up */
+{
+ /* This is a separate procedure only to avoid tying up */
/* extra stack space while running the file. */
+ i_ctx_t *i_ctx_p = minst->i_ctx_p;
#define maxfn 200
byte fn[maxfn];
uint len;
return lib_file_open(file_name, strlen(file_name), fn, maxfn,
- &len, pfile);
+ &len, pfile, imemory);
}
/* Open and execute a file. */
@@ -362,8 +367,8 @@ gs_run_init_file(gs_main_instance * minst, int *pexit_code, ref * perror_object)
if (gs_init_string_sizeof == 0) { /* Read from gs_init_file. */
code = gs_main_run_file_open(minst, gs_init_file, &ifile);
} else { /* Read from gs_init_string. */
- code = file_read_string(gs_init_string, gs_init_string_sizeof,
- &ifile);
+ code = file_read_string(gs_init_string, gs_init_string_sizeof, &ifile,
+ iimemory);
}
if (code < 0) {
*pexit_code = 255;
@@ -601,12 +606,15 @@ gs_pop_string(gs_main_instance * minst, gs_string * result)
/* Free all resources and exit. */
void
gs_main_finit(gs_main_instance * minst, int exit_status, int code)
-{ /*
- * Previous versions of this code closed the devices in the
- * device list here. Since these devices are now prototypes,
- * they cannot be opened, so they do not need to be closed;
- * alloc_restore_all will close dynamically allocated devices.
- */
+{
+ i_ctx_t *i_ctx_p = minst->i_ctx_p;
+
+ /*
+ * Previous versions of this code closed the devices in the
+ * device list here. Since these devices are now prototypes,
+ * they cannot be opened, so they do not need to be closed;
+ * alloc_restore_all will close dynamically allocated devices.
+ */
gs_exit_status = exit_status; /* see above */
gp_readline_finit(minst->readline_data);
if (gs_debug_c(':'))
@@ -648,10 +656,17 @@ print_resource_usage(const gs_main_instance * minst, gs_dual_memory_t * dmem,
if (mem != 0 && (i == 0 || mem != dmem->spaces_indexed[i - 1])) {
gs_memory_status_t status;
+ gs_ref_memory_t *mem_stable =
+ (gs_ref_memory_t *)gs_memory_stable((gs_memory_t *)mem);
- gs_memory_status((gs_memory_t *) mem, &status);
+ gs_memory_status((gs_memory_t *)mem, &status);
allocated += status.allocated;
used += status.used;
+ if (mem_stable != mem) {
+ gs_memory_status((gs_memory_t *)mem_stable, &status);
+ allocated += status.allocated;
+ used += status.used;
+ }
}
}
}
diff --git a/gs/src/imain.h b/gs/src/imain.h
index 3ced68f2b..5a6439133 100644
--- a/gs/src/imain.h
+++ b/gs/src/imain.h
@@ -259,13 +259,4 @@ void gs_main_dump_stack(P3(gs_main_instance *minst, int code,
*/
void gs_main_finit(P3(gs_main_instance * minst, int exit_status, int code));
-/* ================ Other exported procedures ================ */
-
-/*
- * Define an internal interface to the interpreter. Clients do not
- * normally use this.
- */
-int gs_interpret(P5(i_ctx_t **pi_ctx_p, ref * pref, int user_errors,
- int *pexit_code, ref * perror_object));
-
#endif /* imain_INCLUDED */
diff --git a/gs/src/imainarg.c b/gs/src/imainarg.c
index fd9a08ce0..dbbed4810 100644
--- a/gs/src/imainarg.c
+++ b/gs/src/imainarg.c
@@ -463,6 +463,7 @@ run_stdin:
make_empty_string(&value, a_readonly);
} else {
int code;
+ i_ctx_t *i_ctx_p = minst->i_ctx_p;
uint space = icurrent_space;
*eqp++ = 0;
diff --git a/gs/src/imemory.h b/gs/src/imemory.h
index 5e7289b50..a80826064 100644
--- a/gs/src/imemory.h
+++ b/gs/src/imemory.h
@@ -75,25 +75,29 @@ int gs_register_ref_root(P4(gs_memory_t *mem, gs_gc_root_t *root,
* VM space, system VM, that exists in both modes and is used for objects
* that must not be affected by even the outermost save/restore (stack
* segments and names).
+ *
+ * NOTE: since the interpreter's (only) instances of gs_dual_memory_t are
+ * embedded in-line in context state structures, pointers to these
+ * instances must not be stored anywhere that might persist across a
+ * garbage collection.
*/
+#ifndef gs_dual_memory_DEFINED
+# define gs_dual_memory_DEFINED
typedef struct gs_dual_memory_s gs_dual_memory_t;
+#endif
struct gs_dual_memory_s {
gs_ref_memory_t *current; /* = ...global or ...local */
vm_spaces spaces; /* system, global, local */
uint current_space; /* = current->space */
- /* Save/restore machinery */
- int save_level;
/* Garbage collection hook */
int (*reclaim) (P2(gs_dual_memory_t *, int));
- void *reclaim_data;
/* Masks for store checking, see isave.h. */
uint test_mask;
uint new_mask;
};
#define public_st_gs_dual_memory() /* in ialloc.c */\
- gs_public_st_ptrs1(st_gs_dual_memory, gs_dual_memory_t, "gs_dual_memory_t",\
- dual_memory_enum_ptrs, dual_memory_reloc_ptrs, reclaim_data)
-#define st_gs_dual_memory_num_ptrs 1
+ gs_public_st_simple(st_gs_dual_memory, gs_dual_memory_t, "gs_dual_memory_t")
+#define st_gs_dual_memory_num_ptrs 0
#endif /* imemory_INCLUDED */
diff --git a/gs/src/iname.c b/gs/src/iname.c
index 9623d1239..79aa5b4fb 100644
--- a/gs/src/iname.c
+++ b/gs/src/iname.c
@@ -32,50 +32,21 @@
/* Public values */
const uint name_max_string = max_name_string;
-/* In the code below, we use the hashing method described in */
-/* "Fast Hashing of Variable-Length Text Strings" by Peter K. Pearson, */
-/* pp. 677-680, CACM 33(6), June 1990. */
-
-/* Define a pseudo-random permutation of the integers 0..255. */
-/* Pearson's article claims this permutation gave good results. */
-private const byte hash_permutation[256] =
-{
- 1, 87, 49, 12, 176, 178, 102, 166, 121, 193, 6, 84, 249, 230, 44, 163,
- 14, 197, 213, 181, 161, 85, 218, 80, 64, 239, 24, 226, 236, 142, 38, 200,
- 110, 177, 104, 103, 141, 253, 255, 50, 77, 101, 81, 18, 45, 96, 31, 222,
- 25, 107, 190, 70, 86, 237, 240, 34, 72, 242, 20, 214, 244, 227, 149, 235,
- 97, 234, 57, 22, 60, 250, 82, 175, 208, 5, 127, 199, 111, 62, 135, 248,
- 174, 169, 211, 58, 66, 154, 106, 195, 245, 171, 17, 187, 182, 179, 0, 243,
- 132, 56, 148, 75, 128, 133, 158, 100, 130, 126, 91, 13, 153, 246, 216, 219,
- 119, 68, 223, 78, 83, 88, 201, 99, 122, 11, 92, 32, 136, 114, 52, 10,
- 138, 30, 48, 183, 156, 35, 61, 26, 143, 74, 251, 94, 129, 162, 63, 152,
- 170, 7, 115, 167, 241, 206, 3, 150, 55, 59, 151, 220, 90, 53, 23, 131,
- 125, 173, 15, 238, 79, 95, 89, 16, 105, 137, 225, 224, 217, 160, 37, 123,
- 118, 73, 2, 157, 46, 116, 9, 145, 134, 228, 207, 212, 202, 215, 69, 229,
- 27, 188, 67, 124, 168, 252, 42, 4, 29, 108, 21, 247, 19, 205, 39, 203,
- 233, 40, 186, 147, 198, 192, 155, 33, 164, 191, 98, 204, 165, 180, 117, 76,
- 140, 36, 210, 172, 41, 54, 159, 8, 185, 232, 113, 196, 231, 47, 146, 120,
- 51, 65, 28, 144, 254, 221, 93, 189, 194, 139, 112, 43, 71, 109, 184, 209
+/* Define the permutation table for name hashing. */
+private const byte hash_permutation[256] = {
+ NAME_HASH_PERMUTATION_DATA
};
-/*
- * Definitions and structure for the name table.
- * Entry 0 is left unused.
- * The entry with count = 1 is the entry for the 0-length name.
- * The next nt_1char_size entries (in count order) are 1-character names.
- */
-#define nt_1char_size 128
-#define nt_1char_first 2
-private const byte nt_1char_names[128] = {
-#define q8(n) n,n+1,n+2,n+3,n+4,n+5,n+6,n+7
-#define q32(n) q8(n),q8(n+8),q8(n+16),q8(n+24)
- q32(0), q32(32), q32(64), q32(96)
-#undef q8
+/* Define the data for the 1-character names. */
+private const byte nt_1char_names[NT_1CHAR_SIZE] = {
+ NT_1CHAR_NAMES_DATA
};
/* Structure descriptors */
-gs_private_st_composite(st_name_sub_table, name_sub_table, "name_sub_table",
- name_sub_enum_ptrs, name_sub_reloc_ptrs);
+gs_private_st_simple(st_name_sub_table, name_sub_table, "name_sub_table");
+gs_private_st_composite(st_name_string_sub_table, name_string_sub_table_t,
+ "name_string_sub_table_t",
+ name_string_sub_enum_ptrs, name_string_sub_reloc_ptrs);
gs_private_st_composite(st_name_table, name_table, "name_table",
name_table_enum_ptrs, name_table_reloc_ptrs);
@@ -86,21 +57,23 @@ private void name_scan_sub(P3(name_table *, uint, bool));
/* Debugging printout */
#ifdef DEBUG
private void
-name_print(const char *msg, name * pname, uint nidx, const int *pflag)
+name_print(const char *msg, const name_table *nt, uint nidx, const int *pflag)
{
- const byte *ptr = pname->string_bytes;
+ const name_string_t *pnstr = names_index_string_inline(nt, nidx);
+ const name *pname = names_index_ptr_inline(nt, nidx);
+ const byte *str = pnstr->string_bytes;
dlprintf1("[n]%s", msg);
if (pflag)
dprintf1("(%d)", *pflag);
- dprintf2(" (0x%lx#%u)", (ulong) pname, nidx);
- debug_print_string(ptr, pname->string_size);
- dprintf2("(0x%lx,%u)\n", (ulong) ptr, pname->string_size);
+ dprintf2(" (0x%lx#%u)", (ulong)pname, nidx);
+ debug_print_string(str, pnstr->string_size);
+ dprintf2("(0x%lx,%u)\n", (ulong)str, pnstr->string_size);
}
-# define if_debug_name(msg, pname, nidx, pflag)\
- if ( gs_debug_c('n') ) name_print(msg, pname, nidx, pflag)
+# define if_debug_name(msg, nt, nidx, pflag)\
+ if ( gs_debug_c('n') ) name_print(msg, nt, nidx, pflag)
#else
-# define if_debug_name(msg, pname, nidx, pflag) DO_NOTHING
+# define if_debug_name(msg, nt, nidx, pflag) DO_NOTHING
#endif
/* Initialize a name table */
@@ -108,15 +81,14 @@ name_table *
names_init(ulong count, gs_ref_memory_t *imem)
{
gs_memory_t *mem = (gs_memory_t *)imem;
- register int i;
name_table *nt;
+ int i;
if (count == 0)
count = max_name_count + 1L;
else if (count - 1 > max_name_count)
return 0;
- nt =
- gs_alloc_struct(mem, name_table, &st_name_table, "name_init(nt)");
+ nt = gs_alloc_struct(mem, name_table, &st_name_table, "name_init(nt)");
memset(nt, 0, sizeof(name_table));
nt->max_sub_count =
((count - 1) | nt_sub_index_mask) >> nt_log2_sub_size;
@@ -124,23 +96,25 @@ names_init(ulong count, gs_ref_memory_t *imem)
nt->memory = mem;
/* Initialize the one-character names. */
/* Start by creating the necessary sub-tables. */
- for (i = 0; i < nt_1char_first + nt_1char_size; i += nt_sub_size)
+ for (i = 0; i < NT_1CHAR_FIRST + NT_1CHAR_SIZE; i += nt_sub_size)
name_alloc_sub(nt);
- for (i = -1; i < nt_1char_size; i++) {
- uint ncnt = nt_1char_first + i;
+ for (i = -1; i < NT_1CHAR_SIZE; i++) {
+ uint ncnt = NT_1CHAR_FIRST + i;
uint nidx = name_count_to_index(ncnt);
- register name *pname = names_index_ptr_inline(nt, nidx);
+ name *pname = names_index_ptr_inline(nt, nidx);
+ name_string_t *pnstr = names_index_string_inline(nt, nidx);
if (i < 0)
- pname->string_bytes = nt_1char_names,
- pname->string_size = 0;
+ pnstr->string_bytes = nt_1char_names,
+ pnstr->string_size = 0;
else
- pname->string_bytes = nt_1char_names + i,
- pname->string_size = 1;
- pname->foreign_string = 1;
- pname->mark = 1;
+ pnstr->string_bytes = nt_1char_names + i,
+ pnstr->string_size = 1;
+ pnstr->foreign_string = 1;
+ pnstr->mark = 1;
pname->pvalue = pv_no_defn;
}
+ nt->perm_count = NT_1CHAR_FIRST + NT_1CHAR_SIZE;
/* Reconstruct the free list. */
nt->free = 0;
names_trace_finish(nt, NULL);
@@ -159,49 +133,47 @@ names_memory(const name_table * nt)
/* The return may overlap the characters of the string! */
/* See iname.h for the meaning of enterflag. */
int
-names_ref(name_table * nt, const byte * ptr, uint size, ref * pref, int enterflag)
+names_ref(name_table *nt, const byte *ptr, uint size, ref *pref, int enterflag)
{
- register name *pname;
+ name *pname;
+ name_string_t *pnstr;
uint nidx;
uint *phash;
/* Compute a hash for the string. */
- {
- uint hash;
- const byte *p = ptr;
- uint n = size;
-
- /* Make a special check for 1-character names. */
- switch (size) {
- case 0:
- nidx = name_count_to_index(1);
- pname = names_index_ptr_inline(nt, nidx);
- goto mkn;
- case 1:
- if (*p < nt_1char_size) {
- hash = *p + nt_1char_first;
- nidx = name_count_to_index(hash);
- pname = names_index_ptr_inline(nt, nidx);
- goto mkn;
- }
- /* falls through */
- default:
- hash = hash_permutation[*p++];
- while (--n > 0)
- hash = (hash << 8) |
- hash_permutation[(byte) hash ^ *p++];
+ /* Make a special check for 1-character names. */
+ switch (size) {
+ case 0:
+ nidx = name_count_to_index(1);
+ pname = names_index_ptr_inline(nt, nidx);
+ goto mkn;
+ case 1:
+ if (*ptr < NT_1CHAR_SIZE) {
+ uint hash = *ptr + NT_1CHAR_FIRST;
+
+ nidx = name_count_to_index(hash);
+ pname = names_index_ptr_inline(nt, nidx);
+ goto mkn;
}
- phash = nt->hash + (hash & (nt_hash_size - 1));
+ /* falls through */
+ default: {
+ uint hash;
+
+ NAME_HASH(hash, hash_permutation, ptr, size);
+ phash = nt->hash + (hash & (NT_HASH_SIZE - 1));
+ }
}
for (nidx = *phash; nidx != 0;
- nidx = name_next_index(nidx, pname)
+ nidx = name_next_index(nidx, pnstr)
) {
- pname = names_index_ptr_inline(nt, nidx);
- if (pname->string_size == size &&
- !memcmp_inline(ptr, pname->string_bytes, size)
- )
+ pnstr = names_index_string_inline(nt, nidx);
+ if (pnstr->string_size == size &&
+ !memcmp_inline(ptr, pnstr->string_bytes, size)
+ ) {
+ pname = name_index_ptr_inline(nt, nidx);
goto mkn;
+ }
}
/* Name was not in the table. Make a new entry. */
if (enterflag < 0)
@@ -216,27 +188,29 @@ names_ref(name_table * nt, const byte * ptr, uint size, ref * pref, int enterfla
return code;
nidx = nt->free;
}
- pname = name_index_ptr_inline(nt, nidx);
+ pnstr = names_index_string_inline(nt, nidx);
if (enterflag == 1) {
- byte *cptr = (byte *) gs_alloc_string(nt->memory, size,
- "names_ref(string)");
+ byte *cptr = (byte *)gs_alloc_string(nt->memory, size,
+ "names_ref(string)");
if (cptr == 0)
return_error(e_VMerror);
memcpy(cptr, ptr, size);
- pname->string_bytes = cptr;
- pname->foreign_string = 0;
+ pnstr->string_bytes = cptr;
+ pnstr->foreign_string = 0;
} else {
- pname->string_bytes = ptr;
- pname->foreign_string = (enterflag == 0 ? 1 : 0);
+ pnstr->string_bytes = ptr;
+ pnstr->foreign_string = (enterflag == 0 ? 1 : 0);
}
- pname->string_size = size;
+ pnstr->string_size = size;
+ pname = name_index_ptr_inline(nt, nidx);
pname->pvalue = pv_no_defn;
- nt->free = name_next_index(nidx, pname);
- set_name_next_index(nidx, pname, *phash);
+ nt->free = name_next_index(nidx, pnstr);
+ set_name_next_index(nidx, pnstr, *phash);
*phash = nidx;
- if_debug_name("new name", pname, nidx, &enterflag);
- mkn:make_name(pref, nidx, pname);
+ if_debug_name("new name", nt, nidx, &enterflag);
+ mkn:
+ make_name(pref, nidx, pname);
return 0;
}
@@ -245,13 +219,13 @@ void
names_string_ref(const name_table * nt, const ref * pnref /* t_name */ ,
ref * psref /* result, t_string */ )
{
- const name *pname = pnref->value.pname;
+ const name_string_t *pnstr = names_string_inline(nt, pnref);
make_const_string(psref,
- (pname->foreign_string ? avm_foreign | a_readonly :
+ (pnstr->foreign_string ? avm_foreign | a_readonly :
nt->name_string_attrs),
- pname->string_size,
- (const byte *)pname->string_bytes);
+ pnstr->string_size,
+ (const byte *)pnstr->string_bytes);
}
/* Convert a t_string object to a name. */
@@ -307,8 +281,9 @@ names_index_ptr(const name_table * nt, name_index_t index)
name_index_t
names_next_valid_index(name_table * nt, name_index_t nidx)
{
- name_sub_table *sub = nt->sub_tables[nidx >> nt_log2_sub_size];
- name *pname;
+ const name_string_sub_table_t *ssub =
+ nt->sub[nidx >> nt_log2_sub_size].strings;
+ const name_string_t *pnstr;
do {
++nidx;
@@ -316,37 +291,34 @@ names_next_valid_index(name_table * nt, name_index_t nidx)
for (;; nidx += nt_sub_size) {
if ((nidx >> nt_log2_sub_size) >= nt->sub_count)
return 0;
- sub = nt->sub_tables[nidx >> nt_log2_sub_size];
- if (sub != 0)
+ ssub = nt->sub[nidx >> nt_log2_sub_size].strings;
+ if (ssub != 0)
break;
}
- pname = &sub->names[nidx & nt_sub_index_mask];
+ pnstr = &ssub->strings[nidx & nt_sub_index_mask];
}
- while (pname->string_bytes == 0);
+ while (pnstr->string_bytes == 0);
return nidx;
}
/* ------ Garbage collection ------ */
-/* Unmark all names, except for 1-character permanent names, */
-/* before a garbage collection. */
+/* Unmark all non-permanent names before a garbage collection. */
void
names_unmark_all(name_table * nt)
{
uint si;
- name_sub_table *sub;
+ name_string_sub_table_t *ssub;
for (si = 0; si < nt->sub_count; ++si)
- if ((sub = nt->sub_tables[si]) != 0) {
+ if ((ssub = nt->sub[si].strings) != 0) {
uint i;
+ /* We can make the test much more efficient if we want.... */
for (i = 0; i < nt_sub_size; ++i)
- sub->names[i].mark = 0;
- } {
- uint ncnt;
-
- for (ncnt = 1; ncnt <= nt_1char_size; ++ncnt)
- names_index_ptr(nt, name_count_to_index(ncnt))->mark = 1;
+ if (name_index_to_count((si << nt_log2_sub_size) + i) >=
+ nt->perm_count)
+ ssub->strings[i].mark = 0;
}
}
@@ -355,11 +327,11 @@ names_unmark_all(name_table * nt)
bool
names_mark_index(name_table * nt, name_index_t nidx)
{
- name *pname = names_index_ptr(nt, nidx);
+ name_string_t *pnstr = names_index_string_inline(nt, nidx);
- if (pname->mark)
+ if (pnstr->mark)
return false;
- pname->mark = 1;
+ pnstr->mark = 1;
return true;
}
@@ -367,16 +339,22 @@ names_mark_index(name_table * nt, name_index_t nidx)
/* The garbage collector needs this so it can relocate pointers to names. */
void /*obj_header_t */ *
names_ref_sub_table(name_table * nt, const ref * pnref)
-{ /* When this procedure is called, the pointers from the name table */
+{
+ /* When this procedure is called, the pointers from the name table */
/* to the sub-tables may or may not have been relocated already, */
/* so we can't use them. Instead, we have to work backwards from */
/* the name pointer itself. */
- return pnref->value.pname - (names_index_inline(nt, pnref) & nt_sub_index_mask);
+ return pnref->value.pname - (r_size(pnref) & nt_sub_index_mask);
}
void /*obj_header_t */ *
-names_index_ptr_sub_table(name_table * nt, name_index_t index, name * pname)
+names_index_sub_table(name_table * nt, name_index_t index)
{
- return pname - (index & nt_sub_index_mask);
+ return nt->sub[index >> nt_log2_sub_size].names;
+}
+void /*obj_header_t */ *
+names_index_string_sub_table(name_table * nt, name_index_t index)
+{
+ return nt->sub[index >> nt_log2_sub_size].strings;
}
/*
@@ -390,24 +368,28 @@ names_trace_finish(name_table * nt, gc_state_t * gcst)
uint *phash = &nt->hash[0];
uint i;
- for (i = 0; i < nt_hash_size; phash++, i++) {
+ for (i = 0; i < NT_HASH_SIZE; phash++, i++) {
name_index_t prev = 0;
- name *pnprev;
+ /*
+ * The following initialization is only to pacify compilers:
+ * pnprev is only referenced if prev has been set in the loop,
+ * in which case pnprev is also set.
+ */
+ name_string_t *pnprev = 0;
name_index_t nidx = *phash;
while (nidx != 0) {
- name *pname = names_index_ptr_inline(nt, nidx);
- name_index_t next = name_next_index(nidx, pname);
+ name_string_t *pnstr = names_index_string_inline(nt, nidx);
+ name_index_t next = name_next_index(nidx, pnstr);
- if (pname->mark) {
+ if (pnstr->mark) {
prev = nidx;
- pnprev = pname;
+ pnprev = pnstr;
} else {
- if_debug_name("GC remove name", pname, nidx,
- NULL);
+ if_debug_name("GC remove name", nt, nidx, NULL);
/* Zero out the string data for the GC. */
- pname->string_bytes = 0;
- pname->string_size = 0;
+ pnstr->string_bytes = 0;
+ pnstr->string_size = 0;
if (prev == 0)
*phash = next;
else
@@ -419,12 +401,15 @@ names_trace_finish(name_table * nt, gc_state_t * gcst)
/* Reconstruct the free list. */
nt->free = 0;
for (i = nt->sub_count; i--;) {
- name_sub_table *sub = nt->sub_tables[i];
+ name_sub_table *sub = nt->sub[i].names;
+ name_string_sub_table_t *ssub = nt->sub[i].strings;
if (sub != 0) {
name_scan_sub(nt, i, true);
- if (nt->sub_tables[i] == 0 && gcst != 0) { /* Mark the just-freed sub-table as unmarked. */
- o_set_unmarked((obj_header_t *) sub - 1);
+ if (nt->sub[i].names == 0 && gcst != 0) {
+ /* Mark the just-freed sub-table as unmarked. */
+ o_set_unmarked((obj_header_t *)sub - 1);
+ o_set_unmarked((obj_header_t *)ssub - 1);
}
}
if (i == 0)
@@ -443,25 +428,28 @@ names_trace_finish(name_table * nt, gc_state_t * gcst)
/* Currently we don't make any attempt to optimize this. */
void
names_restore(name_table * nt, alloc_save_t * save)
-{ /* We simply mark all names older than the save, */
+{
+ /* We simply mark all names older than the save, */
/* and let names_trace_finish sort everything out. */
uint si;
for (si = 0; si < nt->sub_count; ++si)
- if (nt->sub_tables[si] != 0) {
+ if (nt->sub[si].strings != 0) {
uint i;
for (i = 0; i < nt_sub_size; ++i) {
- name *pname =
- names_index_ptr_inline(nt, (si << nt_log2_sub_size) + i);
-
- if (pname->string_bytes == 0)
- pname->mark = 0;
- else if (pname->foreign_string)
- pname->mark = 1;
- else
- pname->mark =
- !alloc_is_since_save(pname->string_bytes, save);
+ name_string_t *pnstr =
+ names_index_string_inline(nt, (si << nt_log2_sub_size) + i);
+
+ if (pnstr->string_bytes == 0)
+ pnstr->mark = 0;
+ else if (pnstr->foreign_string) {
+ /* Avoid storing into a read-only name string. */
+ if (!pnstr->mark)
+ pnstr->mark = 1;
+ } else
+ pnstr->mark =
+ !alloc_is_since_save(pnstr->string_bytes, save);
}
}
names_trace_finish(nt, NULL);
@@ -473,35 +461,38 @@ names_restore(name_table * nt, alloc_save_t * save)
private int
name_alloc_sub(name_table * nt)
{
+ gs_memory_t *mem = nt->memory;
uint sub_index = nt->sub_next;
name_sub_table *sub;
+ name_string_sub_table_t *ssub;
for (;; ++sub_index) {
if (sub_index > nt->max_sub_count)
return_error(e_limitcheck);
- if (nt->sub_tables[sub_index] == 0)
+ if (nt->sub[sub_index].names == 0)
break;
}
nt->sub_next = sub_index + 1;
if (nt->sub_next > nt->sub_count)
nt->sub_count = nt->sub_next;
- sub = gs_alloc_struct(nt->memory, name_sub_table, &st_name_sub_table,
- "name_alloc_sub");
- if (sub == 0)
+ sub = gs_alloc_struct(mem, name_sub_table, &st_name_sub_table,
+ "name_alloc_sub(sub-table)");
+ ssub = gs_alloc_struct(mem, name_string_sub_table_t,
+ &st_name_string_sub_table,
+ "name_alloc_sub(string sub-table)");
+ if (sub == 0 || ssub == 0) {
+ gs_free_object(mem, ssub, "name_alloc_sub(string sub-table)");
+ gs_free_object(mem, sub, "name_alloc_sub(sub-table)");
return_error(e_VMerror);
+ }
memset(sub, 0, sizeof(name_sub_table));
+ memset(ssub, 0, sizeof(name_string_sub_table_t));
/* The following code is only used if EXTEND_NAMES is non-zero. */
#if name_extension_bits > 0
- if (sub_index >= 0x10000L >> nt_log2_sub_size) {
- /* Fill in my_extension in all the newly created names. */
- uint extn = sub_index >> (16 - nt_log2_sub_size);
- int i;
-
- for (i = 0; i < nt_sub_size; ++i)
- set_name_extension(&sub->names[i], extn);
- }
+ sub->high_index = sub_index >> (16 - nt_log2_sub_size);
#endif
- nt->sub_tables[sub_index] = sub;
+ nt->sub[sub_index].names = sub;
+ nt->sub[sub_index].strings = ssub;
/* Add the newly allocated entries to the free list. */
/* Note that the free list will only be properly sorted if */
/* it was empty initially. */
@@ -510,7 +501,7 @@ name_alloc_sub(name_table * nt)
if (gs_debug_c('n')) { /* Print the lengths of the hash chains. */
int i0;
- for (i0 = 0; i0 < nt_hash_size; i0 += 16) {
+ for (i0 = 0; i0 < NT_HASH_SIZE; i0 += 16) {
int i;
dlprintf1("[n]chain %d:", i0);
@@ -519,7 +510,8 @@ name_alloc_sub(name_table * nt)
uint nidx;
for (nidx = nt->hash[i]; nidx != 0;
- nidx = name_next_index(nidx, name_index_ptr_inline(nt, nidx))
+ nidx = name_next_index(nidx,
+ names_index_string_inline(nt, nidx))
)
n++;
dprintf1(" %d", n);
@@ -538,24 +530,24 @@ name_alloc_sub(name_table * nt)
private void
name_scan_sub(name_table * nt, uint sub_index, bool free_empty)
{
- name_sub_table *sub = nt->sub_tables[sub_index];
+ name_string_sub_table_t *ssub = nt->sub[sub_index].strings;
uint free = nt->free;
uint nbase = sub_index << nt_log2_sub_size;
uint ncnt = nbase + (nt_sub_size - 1);
bool keep = !free_empty;
- if (sub == 0)
+ if (ssub == 0)
return;
if (nbase == 0)
nbase = 1, keep = true; /* don't free name 0 */
for (;; --ncnt) {
uint nidx = name_count_to_index(ncnt);
- name *pname = &sub->names[nidx & nt_sub_index_mask];
+ name_string_t *pnstr = &ssub->strings[nidx & nt_sub_index_mask];
- if (pname->mark)
+ if (pnstr->mark)
keep = true;
else {
- set_name_next_index(nidx, pname, free);
+ set_name_next_index(nidx, pnstr, free);
free = nidx;
}
if (ncnt == nbase)
@@ -563,14 +555,18 @@ name_scan_sub(name_table * nt, uint sub_index, bool free_empty)
}
if (keep)
nt->free = free;
- else { /* No marked entries, free the sub-table. */
- gs_free_object(nt->memory, sub, "name_scan_sub");
- nt->sub_tables[sub_index] = 0;
+ else {
+ /* No marked entries, free the sub-table. */
+ gs_free_object(nt->memory, ssub, "name_scan_sub(string sub-table)");
+ gs_free_object(nt->memory, nt->sub[sub_index].names,
+ "name_scan_sub(sub-table)");
+ nt->sub[sub_index].names = 0;
+ nt->sub[sub_index].strings = 0;
if (sub_index == nt->sub_count - 1) {
/* Back up over a final run of deleted sub-tables. */
do {
--sub_index;
- } while (nt->sub_tables[sub_index] == 0);
+ } while (nt->sub[sub_index].names == 0);
nt->sub_count = sub_index + 1;
if (nt->sub_next > sub_index)
nt->sub_next = sub_index;
@@ -580,24 +576,30 @@ name_scan_sub(name_table * nt, uint sub_index, bool free_empty)
}
/* Garbage collector enumeration and relocation procedures. */
-#define ntptr ((name_table *)vptr)
private
ENUM_PTRS_BEGIN_PROC(name_table_enum_ptrs)
{
- if (index >= ntptr->sub_count)
+ EV_CONST name_table *const nt = vptr;
+ uint i = index >> 1;
+
+ if (i >= nt->sub_count)
return 0;
- ENUM_RETURN(ntptr->sub_tables[index]);
+ if (index & 1)
+ ENUM_RETURN(nt->sub[index].strings);
+ else
+ ENUM_RETURN(nt->sub[index].names);
}
ENUM_PTRS_END_PROC
-private RELOC_PTRS_BEGIN(name_table_reloc_ptrs)
+private RELOC_PTRS_WITH(name_table_reloc_ptrs, name_table *nt)
{
- name_sub_table **sub = ntptr->sub_tables;
- uint sub_count = ntptr->sub_count;
+ uint sub_count = nt->sub_count;
uint i;
/* Now we can relocate the sub-table pointers. */
- for (i = 0; i < sub_count; i++, sub++)
- RELOC_VAR(*sub);
+ for (i = 0; i < sub_count; i++) {
+ RELOC_VAR(nt->sub[i].names);
+ RELOC_VAR(nt->sub[i].strings);
+ }
/*
* We also need to relocate the cached value pointers.
* We don't do this here, but in a separate scan over the
@@ -605,26 +607,25 @@ private RELOC_PTRS_BEGIN(name_table_reloc_ptrs)
*/
}
RELOC_PTRS_END
-#undef ntptr
-private ENUM_PTRS_BEGIN_PROC(name_sub_enum_ptrs)
+private ENUM_PTRS_BEGIN_PROC(name_string_sub_enum_ptrs)
{
return 0;
}
ENUM_PTRS_END_PROC
-private RELOC_PTRS_BEGIN(name_sub_reloc_ptrs)
+private RELOC_PTRS_BEGIN(name_string_sub_reloc_ptrs)
{
- name *pname = ((name_sub_table *) vptr)->names;
+ name_string_t *pnstr = ((name_string_sub_table_t *)vptr)->strings;
uint i;
- for (i = 0; i < nt_sub_size; ++pname, ++i) {
- if (pname->string_bytes != 0 && !pname->foreign_string) {
+ for (i = 0; i < nt_sub_size; ++pnstr, ++i) {
+ if (pnstr->string_bytes != 0 && !pnstr->foreign_string) {
gs_const_string nstr;
- nstr.data = pname->string_bytes;
- nstr.size = pname->string_size;
+ nstr.data = pnstr->string_bytes;
+ nstr.size = pnstr->string_size;
RELOC_CONST_STRING_VAR(nstr);
- pname->string_bytes = nstr.data;
+ pnstr->string_bytes = nstr.data;
}
}
}
diff --git a/gs/src/iname.h b/gs/src/iname.h
index c961a73b8..e9ccc18b1 100644
--- a/gs/src/iname.h
+++ b/gs/src/iname.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1989, 1995, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1989, 1995, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -93,7 +93,5 @@ extern name_table *the_gs_name_table;
/* The garbage collector needs this so it can relocate pointers to names. */
#define name_ref_sub_table(pnref)\
names_ref_sub_table(the_gs_name_table, pnref)
-#define name_index_ptr_sub_table(nidx, pnref)\
- names_index_ptr_sub_table(the_gs_name_table, nidx, pnref)
#endif /* iname_INCLUDED */
diff --git a/gs/src/inamedef.h b/gs/src/inamedef.h
index 50b8bcca4..09539bb40 100644
--- a/gs/src/inamedef.h
+++ b/gs/src/inamedef.h
@@ -22,8 +22,9 @@
#ifndef inamedef_INCLUDED
# define inamedef_INCLUDED
+#include "inameidx.h"
+#include "inamestr.h"
#include "inames.h"
-#include "gconfigv.h" /* defines EXTEND_NAMES */
#include "gsstruct.h" /* for gc_state_t */
/*
@@ -31,13 +32,8 @@
* a faster one that limits the total number of names to 64K and allows
* names up to 16K in size, and a slightly slower one that limits
* the total to 4M and restricts names to 256 characters.
+ * The maximum number of names is 2^(16+EXTEND_NAMES)-1.
*/
-#if arch_sizeof_int < 4
-# undef EXTEND_NAMES /* no extended names if ints are short */
-#endif
-#ifndef EXTEND_NAMES /* # of bits beyond 16 */
-# define EXTEND_NAMES 0
-#endif
#define max_name_extension_bits 6
#if EXTEND_NAMES > max_name_extension_bits
# undef EXTEND_NAMES
@@ -55,28 +51,11 @@
/* ---------------- Structure definitions ---------------- */
/*
- * Define the structure of a name. The next_index "pointer" is used for
- * the chained hash table in the name_table, and also for the list of
- * free names. The pvalue member implements an important optimization
- * to avoid lookup for operator and other global names.
+ * Define the structure of a name. The pvalue member implements an
+ * important optimization to avoid lookup for operator and other global
+ * names.
*/
struct name_s {
- ushort next_index; /* (low bits of) next name in chain or 0 */
- unsigned foreign_string:1; /* string is allocated statically */
- unsigned mark:1; /* GC mark bit */
-#if EXTEND_NAMES
-# define name_extension_bits 6
- unsigned my_extension:name_extension_bits; /* high-order bits */
-# define set_name_extension(pname, xbits) ((pname)->my_extension = xbits)
-#else
-# define name_extension_bits 0
-# define set_name_extension(name, xbits) DO_NOTHING
-#endif
- /* of index for this name */
-#define name_string_size_bits (14 - name_extension_bits)
-#define max_name_string ((1 << name_string_size_bits) - 1)
- unsigned string_size:name_string_size_bits;
- const byte *string_bytes;
/* pvalue specifies the definition status of the name: */
/* pvalue == pv_no_defn: no definitions */
#define pv_no_defn ((ref *)0)
@@ -84,12 +63,11 @@ struct name_s {
#define pv_other ((ref *)1)
/* pvalue != pv_no_defn, pvalue != pv_other: pvalue is valid */
#define pv_valid(pvalue) ((unsigned long)(pvalue) > 1)
- ref *pvalue; /* if only defined in systemdict */
- /* or userdict, this points to */
- /* the value */
+ ref *pvalue; /* if only defined in systemdict or */
+ /* userdict, this points to the value */
};
- /*typedef struct name_s name; *//* in iref.h */
+/*typedef struct name_s name; *//* in iref.h */
/*
* Define the structure of a name table. Normally we would make this
@@ -101,31 +79,14 @@ struct name_s {
*
* First we define the name sub-table structure.
*/
-#define nt_log2_sub_size (8 + (EXTEND_NAMES / 2))
+#define nt_log2_sub_size NT_LOG2_SUB_SIZE /* in inameidx.h */
# define nt_sub_size (1 << nt_log2_sub_size)
# define nt_sub_index_mask (nt_sub_size - 1)
typedef struct name_sub_table_s {
- name names[nt_sub_size]; /* must be first */
-#if EXTEND_NAMES
- byte next_index_extension[nt_sub_size]; /* high-order bits */
- /* of next_index */
-# define name_next_index(nidx, pname)\
- ( (((name_sub_table *)((pname) - ((nidx) & nt_sub_index_mask)))->\
- next_index_extension[(nidx) & nt_sub_index_mask] << 16) +\
- ((pname)->next_index)\
- )
-# define set_name_next_index(nidx, pname, next)\
- ( ((name_sub_table *)((pname) - ((nidx) & nt_sub_index_mask)))->\
- next_index_extension[(nidx) & nt_sub_index_mask] =\
- (byte)((next) >> 16),\
- (pname)->next_index = (ushort)(next)\
- )
-#else /* !EXTEND_NAMES */
-# define name_next_index(nidx, pname)\
- ((pname)->next_index)
-# define set_name_next_index(nidx, pname, next)\
- ((pname)->next_index = (next))
-#endif /* (!)EXTEND_NAMES */
+ name names[NT_SUB_SIZE]; /* must be first */
+#ifdef EXTEND_NAMES
+ uint high_index; /* sub-table base index & (-1 << 16) */
+#endif
} name_sub_table;
/*
@@ -133,36 +94,50 @@ typedef struct name_sub_table_s {
* This must be made visible so that the interpreter can use the
* inline macros defined below.
*/
-#define nt_hash_size (1024 << (EXTEND_NAMES / 2)) /* must be a power of 2 */
struct name_table_s {
uint free; /* head of free list, which is sorted in */
/* increasing count (not index) order */
uint sub_next; /* index of next sub-table to allocate */
/* if not already allocated */
+ uint perm_count; /* # of permanent (read-only) strings */
uint sub_count; /* index of highest allocated sub-table +1 */
uint max_sub_count; /* max allowable value of sub_count */
uint name_string_attrs; /* imemory_space(memory) | a_readonly */
gs_memory_t *memory;
- uint hash[nt_hash_size];
- name_sub_table *sub_tables[max_name_index / nt_sub_size + 1];
+ uint hash[NT_HASH_SIZE];
+ struct sub_ { /* both ptrs are 0 or both are non-0 */
+ name_sub_table *names;
+ name_string_sub_table_t *strings;
+ } sub[max_name_index / nt_sub_size + 1];
};
/*typedef struct name_table_s name_table; *//* in inames.h */
/* ---------------- Procedural interface ---------------- */
-/* Convert between names and indices. Note that the inline versions, */
-/* but not the procedure versions, take a name_table argument. */
+/*
+ * Convert between names, indices, and strings. Note that the inline
+ * versions, but not the procedure versions, take a name_table argument.
+ */
+ /* index => string */
+#define names_index_string_inline(nt, nidx)\
+ ((nt)->sub[(nidx) >> nt_log2_sub_size].strings->strings +\
+ ((nidx) & nt_sub_index_mask))
+ /* ref => string */
+#define names_string_inline(nt, pnref)\
+ names_index_string_inline(nt, names_index_inline(nt, pnref))
/* ref => index */
#if EXTEND_NAMES
# define names_index_inline(nt_ignored, pnref)\
- ( ((uint)((pnref)->value.pname->my_extension) << 16) + r_size(pnref) )
+ ( ((const name_sub_table *)\
+ ((pnref)->value.pname - (r_size(pnref) & nt_sub_index_mask)))->high_index + r_size(pnref) )
#else
# define names_index_inline(nt_ignored, pnref) r_size(pnref)
#endif
#define names_index(nt_ignored, pnref) names_index_inline(nt_ignored, pnref)
/* index => name */
#define names_index_ptr_inline(nt, nidx)\
- ((nt)->sub_tables[(nidx) >> nt_log2_sub_size]->names + ((nidx) & nt_sub_index_mask))
+ ((nt)->sub[(nidx) >> nt_log2_sub_size].names->names +\
+ ((nidx) & nt_sub_index_mask))
/* index => ref */
#define names_index_ref_inline(nt, nidx, pnref)\
make_name(pnref, nidx, names_index_ptr_inline(nt, nidx));
@@ -171,7 +146,6 @@ struct name_table_s {
#define name_index_ptr_inline(nt, pnref) names_index_ptr_inline(nt, pnref)
#define name_index_ref_inline(nt, nidx, pnref)\
names_index_ref_inline(nt, nidx, pnref)
-
/* name => ref */
/* We have to set the space to system so that the garbage collector */
/* won't think names are foreign and therefore untraceable. */
@@ -180,8 +154,7 @@ struct name_table_s {
/* ------ Garbage collection ------ */
-/* Unmark all names, except for 1-character permanent names, */
-/* before a garbage collection. */
+/* Unmark all non-permanent names before a garbage collection. */
void names_unmark_all(P1(name_table * nt));
/* Finish tracing the name table by putting free names on the free list. */
@@ -189,38 +162,11 @@ void names_trace_finish(P2(name_table * nt, gc_state_t * gcst));
/* ------ Save/restore ------ */
-/* Clean up the name table before a restore, */
-/* by removing names whose count is less than old_count. */
+/* Clean up the name table before a restore. */
#ifndef alloc_save_t_DEFINED /* also in isave.h */
typedef struct alloc_save_s alloc_save_t;
# define alloc_save_t_DEFINED
#endif
void names_restore(P2(name_table * nt, alloc_save_t * save));
-/* ---------------- Name count/index maintenance ---------------- */
-
-/*
- * We scramble the assignment order within a sub-table, so that
- * dictionary lookup doesn't have to scramble the index.
- * The scrambling algorithm must have three properties:
- * - It must map 0 to 0;
- * - It must only scramble the sub-table index;
- * - It must be a permutation on the sub-table index.
- * Something very simple works just fine.
- */
-#define NAME_COUNT_TO_INDEX_FACTOR 23
-#define name_count_to_index(cnt)\
- (((cnt) & (-nt_sub_size)) +\
- (((cnt) * NAME_COUNT_TO_INDEX_FACTOR) & nt_sub_index_mask))
-/*
- * The reverse permutation requires finding a number R such that
- * NAME_COUNT_TO_INDEX_FACTOR * R = 1 mod nt_sub_size.
- * The value given below works for nt_sub_size any power of 2 up to 4096.
- * Currently, this is only needed for debugging printout.
- */
-#define NAME_INDEX_TO_COUNT_FACTOR 1959
-#define name_index_to_count(nidx)\
- (((nidx) & (-nt_sub_size)) +\
- (((nidx) * NAME_INDEX_TO_COUNT_FACTOR) & nt_sub_index_mask))
-
#endif /* inamedef_INCLUDED */
diff --git a/gs/src/inameidx.h b/gs/src/inameidx.h
new file mode 100644
index 000000000..b10857742
--- /dev/null
+++ b/gs/src/inameidx.h
@@ -0,0 +1,85 @@
+/* Copyright (C) 1999 Aladdin Enterprises. All rights reserved.
+
+ This file is part of Aladdin Ghostscript.
+
+ Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
+ or distributor accepts any responsibility for the consequences of using it,
+ or for whether it serves any particular purpose or works at all, unless he
+ or she says so in writing. Refer to the Aladdin Ghostscript Free Public
+ License (the "License") for full details.
+
+ Every copy of Aladdin Ghostscript must include a copy of the License,
+ normally in a plain ASCII text file named PUBLIC. The License grants you
+ the right to copy, modify and redistribute Aladdin Ghostscript, but only
+ under certain conditions described in the License. Among other things, the
+ License requires that the copyright notice and this notice be preserved on
+ all copies.
+ */
+
+
+/* Name index definitions */
+
+#ifndef inameidx_INCLUDED
+# define inameidx_INCLUDED
+
+#include "gconfigv.h" /* defines EXTEND_NAMES */
+
+/*
+ * The name table machinery has two slightly different configurations:
+ * a faster one that limits the total number of names to 64K and allows
+ * names up to 16K in size, and a slightly slower one that limits
+ * the total to 4M and restricts names to 256 characters.
+ */
+#ifndef EXTEND_NAMES /* # of bits beyond 16 */
+# define EXTEND_NAMES 0
+#endif
+
+/* Define the size of a name sub-table. */
+#define NT_LOG2_SUB_SIZE (8 + (EXTEND_NAMES / 2))
+# define NT_SUB_SIZE (1 << NT_LOG2_SUB_SIZE)
+# define NT_SUB_INDEX_MASK (NT_SUB_SIZE - 1)
+
+/*
+ * Define the first few entries of the name table. Entry 0 is left unused.
+ * The entry with count = 1 is the entry for the 0-length name.
+ * The next NT_1CHAR_SIZE entries (in count order) are 1-character names.
+ */
+#define NT_1CHAR_SIZE 128
+#define NT_1CHAR_FIRST 2
+#define NT_1CHAR_NAMES_DATA\
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,\
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,\
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,\
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,\
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,\
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,\
+ 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,\
+ 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127
+
+/* ---------------- Name count/index mapping ---------------- */
+
+/*
+ * We scramble the assignment order within a sub-table, so that
+ * dictionary lookup doesn't have to scramble the index.
+ * The scrambling algorithm must have three properties:
+ * - It must map 0 to 0;
+ * - It must only scramble the sub-table index;
+ * - It must be a permutation on the sub-table index.
+ * Something very simple works just fine.
+ */
+#define NAME_COUNT_TO_INDEX_FACTOR 23
+#define name_count_to_index(cnt)\
+ (((cnt) & (-NT_SUB_SIZE)) +\
+ (((cnt) * NAME_COUNT_TO_INDEX_FACTOR) & NT_SUB_INDEX_MASK))
+/*
+ * The reverse permutation requires finding a number R such that
+ * NAME_COUNT_TO_INDEX_FACTOR * R = 1 mod NT_SUB_SIZE.
+ * The value given below works for NT_SUB_SIZE any power of 2 up to 4096.
+ * This is not currently used anywhere.
+ */
+#define NAME_INDEX_TO_COUNT_FACTOR 1959
+#define name_index_to_count(nidx)\
+ (((nidx) & (-NT_SUB_SIZE)) +\
+ (((nidx) * NAME_INDEX_TO_COUNT_FACTOR) & NT_SUB_INDEX_MASK))
+
+#endif /* inameidx_INCLUDED */
diff --git a/gs/src/inames.h b/gs/src/inames.h
index bc3499d91..d4b6ca1c3 100644
--- a/gs/src/inames.h
+++ b/gs/src/inames.h
@@ -105,8 +105,10 @@ bool names_mark_index(P2(name_table * nt, name_index_t nidx));
/* Get the object (sub-table) containing a name. */
/* The garbage collector needs this so it can relocate pointers to names. */
void /*obj_header_t */ *
- names_ref_sub_table(P2(name_table * nt, const ref * pnref));
+ names_ref_sub_table(P2(name_table * nt, const ref * pnref));
void /*obj_header_t */ *
- names_index_ptr_sub_table(P3(name_table * nt, name_index_t nidx, name * pname));
+ names_index_sub_table(P2(name_table * nt, name_index_t nidx));
+void /*obj_header_t */ *
+ names_index_string_sub_table(P2(name_table * nt, name_index_t nidx));
#endif /* inames_INCLUDED */
diff --git a/gs/src/inamestr.h b/gs/src/inamestr.h
new file mode 100644
index 000000000..28bc6e2ab
--- /dev/null
+++ b/gs/src/inamestr.h
@@ -0,0 +1,98 @@
+/* Copyright (C) 1999 Aladdin Enterprises. All rights reserved.
+
+ This file is part of Aladdin Ghostscript.
+
+ Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
+ or distributor accepts any responsibility for the consequences of using it,
+ or for whether it serves any particular purpose or works at all, unless he
+ or she says so in writing. Refer to the Aladdin Ghostscript Free Public
+ License (the "License") for full details.
+
+ Every copy of Aladdin Ghostscript must include a copy of the License,
+ normally in a plain ASCII text file named PUBLIC. The License grants you
+ the right to copy, modify and redistribute Aladdin Ghostscript, but only
+ under certain conditions described in the License. Among other things, the
+ License requires that the copyright notice and this notice be preserved on
+ all copies.
+ */
+
+
+/* Name table strings definition */
+
+#ifndef inamestr_INCLUDED
+# define inamestr_INCLUDED
+
+#include "inameidx.h"
+
+/*
+ * In the code below, we use the hashing method described in
+ * "Fast Hashing of Variable-Length Text Strings" by Peter K. Pearson,
+ * pp. 677-680, CACM 33(6), June 1990.
+ */
+
+/*
+ * Define a pseudo-random permutation of the integers 0..255.
+ * Pearson's article claims this permutation gave good results.
+ */
+#define NAME_HASH_PERMUTATION_DATA\
+ 1, 87, 49, 12, 176, 178, 102, 166, 121, 193, 6, 84, 249, 230, 44, 163,\
+ 14, 197, 213, 181, 161, 85, 218, 80, 64, 239, 24, 226, 236, 142, 38, 200,\
+ 110, 177, 104, 103, 141, 253, 255, 50, 77, 101, 81, 18, 45, 96, 31, 222,\
+ 25, 107, 190, 70, 86, 237, 240, 34, 72, 242, 20, 214, 244, 227, 149, 235,\
+ 97, 234, 57, 22, 60, 250, 82, 175, 208, 5, 127, 199, 111, 62, 135, 248,\
+ 174, 169, 211, 58, 66, 154, 106, 195, 245, 171, 17, 187, 182, 179, 0, 243,\
+ 132, 56, 148, 75, 128, 133, 158, 100, 130, 126, 91, 13, 153, 246, 216, 219,\
+ 119, 68, 223, 78, 83, 88, 201, 99, 122, 11, 92, 32, 136, 114, 52, 10,\
+ 138, 30, 48, 183, 156, 35, 61, 26, 143, 74, 251, 94, 129, 162, 63, 152,\
+ 170, 7, 115, 167, 241, 206, 3, 150, 55, 59, 151, 220, 90, 53, 23, 131,\
+ 125, 173, 15, 238, 79, 95, 89, 16, 105, 137, 225, 224, 217, 160, 37, 123,\
+ 118, 73, 2, 157, 46, 116, 9, 145, 134, 228, 207, 212, 202, 215, 69, 229,\
+ 27, 188, 67, 124, 168, 252, 42, 4, 29, 108, 21, 247, 19, 205, 39, 203,\
+ 233, 40, 186, 147, 198, 192, 155, 33, 164, 191, 98, 204, 165, 180, 117, 76,\
+ 140, 36, 210, 172, 41, 54, 159, 8, 185, 232, 113, 196, 231, 47, 146, 120,\
+ 51, 65, 28, 144, 254, 221, 93, 189, 194, 139, 112, 43, 71, 109, 184, 209
+
+/* Compute the hash for a name string. Assume size >= 1. */
+#define NAME_HASH(hash, hperm, ptr, size)\
+ BEGIN\
+ const byte *p = ptr;\
+ uint n = size;\
+\
+ hash = hperm[*p++];\
+ while (--n > 0)\
+ hash = (hash << 8) | hperm[(byte)hash ^ *p++];\
+ END
+
+/*
+ * Define the structure for a name string. The next_index "pointer" is used
+ * both for the chained hash table in the name_table and for the list of
+ * free names.
+ */
+typedef struct name_string_s {
+#if EXTEND_NAMES
+# define name_extension_bits 6
+#else
+# define name_extension_bits 0
+#endif
+ unsigned next_index:16 + name_extension_bits; /* next name in chain or 0 */
+ unsigned foreign_string:1; /* string is allocated statically */
+ unsigned mark:1; /* GC mark bit of index for this name */
+#define name_string_size_bits (14 - name_extension_bits)
+#define max_name_string ((1 << name_string_size_bits) - 1)
+ unsigned string_size:name_string_size_bits;
+ const byte *string_bytes;
+} name_string_t;
+#define name_next_index(nidx, pnstr)\
+ ((pnstr)->next_index)
+#define set_name_next_index(nidx, pnstr, next)\
+ ((pnstr)->next_index = (next))
+
+/* Define a sub-table of name strings. */
+typedef struct name_string_sub_table_s {
+ name_string_t strings[NT_SUB_SIZE];
+} name_string_sub_table_t;
+
+/* Define the size of the name hash table. */
+#define NT_HASH_SIZE (1024 << (EXTEND_NAMES / 2)) /* must be a power of 2 */
+
+#endif /* inamestr_INCLUDED */
diff --git a/gs/src/inobtokn.c b/gs/src/inobtokn.c
index e585ab9e1..aee515b6e 100644
--- a/gs/src/inobtokn.c
+++ b/gs/src/inobtokn.c
@@ -22,6 +22,7 @@
#include "errors.h"
#include "stream.h"
#include "iscan.h"
+#include "iscanbin.h"
int
scan_binary_token(i_ctx_t *i_ctx_p, stream *s, ref *pref,
diff --git a/gs/src/instcopy b/gs/src/instcopy
new file mode 100755
index 000000000..b3412440d
--- /dev/null
+++ b/gs/src/instcopy
@@ -0,0 +1,31 @@
+#!/bin/sh
+
+#
+# Implement a uniform 'install' syntax independent of which of the two
+# "standard" install programs is installed. Based on ideas in, but not
+# copied from, the GNU fileutils install-sh script. Usage:
+# instcopy -c [-m <mode>] <file> <dir>
+
+c=$1
+mode=""
+
+ if [ "$2" = "-m" ]; then mode=$3; shift; shift; else true; fi
+
+src=$2
+dst=$3
+
+ if [ x"$c" = x-c -a -f $src -a -d $dst ]; then true; else
+ echo "Usage: instcopy -c [-m <mode>] <file> <dir>"
+ exit 1
+ fi
+
+dstdir=`echo $dst | sed -e 's,/$,,'`
+dsttmp=$dstdir/#inst.$$#
+dst="$dstdir"/`basename $src`
+
+cp $src $dsttmp &&
+trap "rm -f $dsttmp" 0 &&
+if [ x"$mode" != x ]; then chmod $mode $dsttmp; else true; fi &&
+rm -f $dst &&
+mv $dsttmp $dst &&
+exit 0
diff --git a/gs/src/int.mak b/gs/src/int.mak
index d09b10050..6e4330e90 100644
--- a/gs/src/int.mak
+++ b/gs/src/int.mak
@@ -52,13 +52,15 @@ idebug_h=$(PSSRC)idebug.h
iddstack_h=$(PSSRC)iddstack.h
idict_h=$(PSSRC)idict.h $(iddstack_h)
idictdef_h=$(PSSRC)idictdef.h
+idosave_h=$(PSSRC)idosave.h
igcstr_h=$(PSSRC)igcstr.h
inames_h=$(PSSRC)inames.h
iname_h=$(PSSRC)iname.h $(inames_h)
-inamedef_h=$(PSSRC)inamedef.h $(gconfigv_h) $(gsstruct_h) $(inames_h)
+inameidx_h=$(PSSRC)inameidx.h $(gconfigv_h)
+inamestr_h=$(PSSRC)inamestr.h $(inameidx_h)
ipacked_h=$(PSSRC)ipacked.h
iref_h=$(PSSRC)iref.h
-isave_h=$(PSSRC)isave.h
+isave_h=$(PSSRC)isave.h $(idosave_h)
isstate_h=$(PSSRC)isstate.h
istruct_h=$(PSSRC)istruct.h $(gsstruct_h)
iutil_h=$(PSSRC)iutil.h
@@ -71,7 +73,9 @@ imemory_h=$(PSSRC)imemory.h $(gsalloc_h) $(ivmspace_h)
ialloc_h=$(PSSRC)ialloc.h $(imemory_h)
iastruct_h=$(PSSRC)iastruct.h $(gxobj_h) $(ialloc_h)
iastate_h=$(PSSRC)iastate.h $(gxalloc_h) $(ialloc_h) $(istruct_h)
-store_h=$(PSSRC)store.h $(ialloc_h)
+inamedef_h=$(PSSRC)inamedef.h\
+ $(gsstruct_h) $(inameidx_h) $(inames_h) $(inamestr_h)
+store_h=$(PSSRC)store.h $(ialloc_h) $(idosave_h)
GH=$(AK) $(ghost_h)
@@ -132,7 +136,9 @@ interp_h=$(PSSRC)interp.h
iparam_h=$(PSSRC)iparam.h $(gsparam_h)
isdata_h=$(PSSRC)isdata.h
istack_h=$(PSSRC)istack.h $(isdata_h)
+istkparm_h=$(PSSRC)istkparm.h
iutil2_h=$(PSSRC)iutil2.h
+oparc_h=$(PSSRC)oparc.h
opcheck_h=$(PSSRC)opcheck.h
opextern_h=$(PSSRC)opextern.h
# Nested include files
@@ -150,12 +156,14 @@ ostack_h=$(PSSRC)ostack.h $(icstate_h) $(iostack_h)
oper_h=$(PSSRC)oper.h $(errors_h) $(iutil_h) $(opcheck_h) $(opdef_h) $(opextern_h) $(ostack_h)
$(PSOBJ)idebug.$(OBJ) : $(PSSRC)idebug.c $(GH) $(string__h)\
- $(ialloc_h) $(idebug_h) $(idict_h) $(iname_h) $(istack_h) $(iutil_h) $(ivmspace_h)\
+ $(gxalloc_h)\
+ $(idebug_h) $(idict_h) $(iname_h) $(istack_h) $(iutil_h) $(ivmspace_h)\
$(opdef_h) $(ipacked_h)
$(PSCC) $(PSO_)idebug.$(OBJ) $(C_) $(PSSRC)idebug.c
$(PSOBJ)idict.$(OBJ) : $(PSSRC)idict.c $(GH) $(string__h)\
$(errors_h)\
+ $(gxalloc_h)\
$(iddstack_h) $(idebug_h) $(idict_h) $(idictdef_h)\
$(imemory_h) $(iname_h) $(inamedef_h) $(ipacked_h) $(isave_h)\
$(iutil_h) $(ivmspace_h) $(store_h)
@@ -180,7 +188,8 @@ $(PSOBJ)iparam.$(OBJ) : $(PSSRC)iparam.c $(GH)\
$(PSOBJ)istack.$(OBJ) : $(PSSRC)istack.c $(GH) $(memory__h)\
$(errors_h) $(gsstruct_h) $(gsutil_h)\
- $(ialloc_h) $(istack_h) $(istruct_h) $(iutil_h) $(ivmspace_h) $(store_h)
+ $(ialloc_h) $(istack_h) $(istkparm_h) $(istruct_h) $(iutil_h) $(ivmspace_h)\
+ $(store_h)
$(PSCC) $(PSO_)istack.$(OBJ) $(C_) $(PSSRC)istack.c
$(PSOBJ)iutil.$(OBJ) : $(PSSRC)iutil.c $(GH) $(math__h) $(memory__h) $(string__h)\
@@ -205,14 +214,19 @@ icharout_h=$(PSSRC)icharout.h
icolor_h=$(PSSRC)icolor.h
icremap_h=$(PSSRC)icremap.h $(gsccolor_h)
icsmap_h=$(PSSRC)icsmap.h
+ifilter2_h=$(PSSRC)ifilter2.h
ifont_h=$(PSSRC)ifont.h $(gsccode_h) $(gsstype_h)
ifont1_h=$(PSSRC)ifont1.h
+ifrpred_h=$(PSSRC)ifrpred.h
+ifwpred_h=$(PSSRC)ifwpred.h
iht_h=$(PSSRC)iht.h
iimage_h=$(PSSRC)iimage.h
+iinit_h=$(PSSRC)iinit.h
imain_h=$(PSSRC)imain.h $(gsexit_h)
imainarg_h=$(PSSRC)imainarg.h
iminst_h=$(PSSRC)iminst.h
iparray_h=$(PSSRC)iparray.h
+iscanbin_h=$(PSSRC)iscanbin.h
iscannum_h=$(PSSRC)iscannum.h
istream_h=$(PSSRC)istream.h
main_h=$(PSSRC)main.h $(imain_h) $(iminst_h)
@@ -242,15 +256,16 @@ $(PSOBJ)iconfig.$(OBJ) : $(PSSRC)iconf.c $(stdio__h)\
$(PSOBJ)iinit.$(OBJ) : $(PSSRC)iinit.c $(GH) $(string__h)\
$(gscdefs_h) $(gsexit_h) $(gsstruct_h)\
- $(ialloc_h) $(iddict_h) $(dstack_h) $(errors_h)\
- $(ilevel_h) $(iname_h) $(interp_h) $(opdef_h)\
+ $(dstack_h) $(errors_h) $(ialloc_h) $(iddict_h)\
+ $(iinit_h) $(ilevel_h) $(iname_h) $(interp_h) $(opdef_h)\
$(ipacked_h) $(iparray_h) $(iutil_h) $(ivmspace_h) $(store_h)
$(PSCC) $(PSO_)iinit.$(OBJ) $(C_) $(PSSRC)iinit.c
$(PSOBJ)iscan.$(OBJ) : $(PSSRC)iscan.c $(GH) $(memory__h)\
$(btoken_h) $(dstack_h) $(errors_h) $(files_h)\
- $(ialloc_h) $(idict_h) $(ilevel_h) $(iutil_h) $(iscan_h) $(iscannum_h)\
- $(istruct_h) $(ivmspace_h) $(iname_h) $(ipacked_h) $(iparray_h) $(istream_h)\
+ $(ialloc_h) $(idict_h) $(ilevel_h) $(iname_h) $(ipacked_h) $(iparray_h)\
+ $(iscan_h) $(iscanbin_h) $(iscannum_h)\
+ $(istruct_h) $(istream_h) $(iutil_h) $(ivmspace_h)\
$(ostack_h) $(store_h)\
$(sa85d_h) $(stream_h) $(strimpl_h) $(sfilter_h) $(scanchar_h)
$(PSCC) $(PSO_)iscan.$(OBJ) $(C_) $(PSSRC)iscan.c
@@ -269,6 +284,8 @@ $(PSOBJ)sfilter1.$(OBJ) : $(PSSRC)sfilter1.c $(AK) $(stdio__h) $(memory__h)\
# Alexey Subbotin <A.Subbotin@lpi.ru> if you have questions.
# The references from a gp_ module to the interpreter are a bug,
# but they are intrinsic to what this implementation does.
+# NOTE: please see gp_gnrdl.c for information about licensing problems
+# that will arise if you add this feature to Aladdin Ghostscript.
gnrdline_=$(PSOBJ)gp_gnrdl.$(OBJ)
$(PSD)gnrdline.dev : $(INT_MAK) $(ECHOGS_XE) $(gnrdline_)
$(SETMOD) $(PSD)gnrdline $(gnrdline_)
@@ -278,8 +295,9 @@ $(PSD)gnrdline.dev : $(INT_MAK) $(ECHOGS_XE) $(gnrdline_)
$(PSOBJ)gp_gnrdl.$(OBJ) : $(PSSRC)gp_gnrdl.c $(AK)\
$(ctype__h) $(malloc__h) $(memory__h) $(string__h)\
- $(gp_h) $(gsmalloc_h) $(gsmemory_h) $(gsstruct_h) $(gxiodev_h) $(stream_h)\
- $(ghost_h) $(dstack_h) $(errors_h) $(idict_h) $(iname_h) $(iutil_h)\
+ $(gp_h) $(gscdefs_h) $(gsmalloc_h) $(gsmemory_h) $(gsstruct_h)\
+ $(gxiodev_h) $(stream_h)\
+ $(ghost_h) $(dstack_h) $(errors_h) $(ialloc_h) $(idict_h) $(iname_h) $(iutil_h)\
$(ostack_h)
$(PSCC) $(PSO_)gp_gnrdl.$(OBJ) $(C_) $(PSSRC)gp_gnrdl.c
@@ -306,8 +324,8 @@ $(PSOBJ)zdict.$(OBJ) : $(PSSRC)zdict.c $(OP)\
$(PSCC) $(PSO_)zdict.$(OBJ) $(C_) $(PSSRC)zdict.c
$(PSOBJ)zfile.$(OBJ) : $(PSSRC)zfile.c $(OP) $(memory__h) $(string__h) $(gp_h)\
- $(gscdefs_h) $(gsstruct_h) $(gxalloc_h) $(gxiodev_h)\
- $(ialloc_h) $(estack_h) $(files_h) $(fname_h) $(ilevel_h) $(interp_h) $(iutil_h)\
+ $(gscdefs_h) $(gsfname_h) $(gsstruct_h) $(gxalloc_h) $(gxiodev_h)\
+ $(ialloc_h) $(estack_h) $(files_h) $(ilevel_h) $(interp_h) $(iutil_h)\
$(isave_h) $(main_h) $(sfilter_h) $(stream_h) $(strimpl_h) $(store_h)
$(PSCC) $(PSO_)zfile.$(OBJ) $(C_) $(PSSRC)zfile.c
@@ -323,10 +341,6 @@ $(PSOBJ)zfilter.$(OBJ) : $(PSSRC)zfilter.c $(OP) $(memory__h)\
$(sfilter_h) $(srlx_h) $(sstring_h) $(stream_h) $(strimpl_h)
$(PSCC) $(PSO_)zfilter.$(OBJ) $(C_) $(PSSRC)zfilter.c
-$(PSOBJ)zfname.$(OBJ) : $(PSSRC)zfname.c $(OP) $(memory__h)\
- $(fname_h) $(gxiodev_h) $(ialloc_h) $(stream_h)
- $(PSCC) $(PSO_)zfname.$(OBJ) $(C_) $(PSSRC)zfname.c
-
$(PSOBJ)zfproc.$(OBJ) : $(PSSRC)zfproc.c $(GH) $(memory__h)\
$(oper_h)\
$(estack_h) $(files_h) $(gsstruct_h) $(ialloc_h) $(ifilter_h) $(istruct_h)\
@@ -397,23 +411,23 @@ $(PSOBJ)zvmem.$(OBJ) : $(PSSRC)zvmem.c $(OP)\
### Graphics operators
$(PSOBJ)zbfont.$(OBJ) : $(PSSRC)zbfont.c $(OP) $(memory__h) $(string__h)\
- $(gsmatrix_h) $(gxdevice_h) $(gschar_h) $(gxfixed_h) $(gxfont_h)\
+ $(gsmatrix_h) $(gxdevice_h) $(gxfixed_h) $(gxfont_h)\
$(bfont_h) $(ialloc_h) $(idict_h) $(idparam_h) $(ilevel_h)\
$(iname_h) $(interp_h) $(istruct_h) $(ipacked_h) $(store_h)
$(PSCC) $(PSO_)zbfont.$(OBJ) $(C_) $(PSSRC)zbfont.c
$(PSOBJ)zchar.$(OBJ) : $(PSSRC)zchar.c $(OP)\
- $(gsstruct_h) $(gxarith_h) $(gxfixed_h) $(gxmatrix_h)\
- $(gxchar_h) $(gxdevice_h) $(gxfont_h) $(gzstate_h)\
+ $(gsstruct_h) $(gstext_h) $(gxarith_h) $(gxfixed_h) $(gxmatrix_h)\
+ $(gxdevice_h) $(gxfont_h) $(gzstate_h)\
$(dstack_h) $(estack_h) $(ialloc_h) $(ichar_h) $(idict_h) $(ifont_h)\
$(ilevel_h) $(iname_h) $(igstate_h) $(ipacked_h) $(store_h)
$(PSCC) $(PSO_)zchar.$(OBJ) $(C_) $(PSSRC)zchar.c
# zcharout is used for Type 1 and Type 42 fonts only.
$(PSOBJ)zcharout.$(OBJ) : $(PSSRC)zcharout.c $(OP)\
- $(gschar_h) $(gxdevice_h) $(gxfont_h)\
+ $(gstext_h) $(gxdevice_h) $(gxfont_h)\
$(dstack_h) $(estack_h) $(ichar_h) $(icharout_h)\
- $(idict_h) $(ifont_h) $(igstate_h) $(store_h)
+ $(idict_h) $(ifont_h) $(igstate_h) $(iname_h) $(store_h)
$(PSCC) $(PSO_)zcharout.$(OBJ) $(C_) $(PSSRC)zcharout.c
$(PSOBJ)zcolor.$(OBJ) : $(PSSRC)zcolor.c $(OP)\
@@ -427,7 +441,7 @@ $(PSOBJ)zdevice.$(OBJ) : $(PSSRC)zdevice.c $(OP) $(string__h)\
$(PSCC) $(PSO_)zdevice.$(OBJ) $(C_) $(PSSRC)zdevice.c
$(PSOBJ)zfont.$(OBJ) : $(PSSRC)zfont.c $(OP)\
- $(gschar_h) $(gsstruct_h) $(gxdevice_h) $(gxfont_h) $(gxfcache_h)\
+ $(gsstruct_h) $(gxdevice_h) $(gxfont_h) $(gxfcache_h)\
$(gzstate_h)\
$(ialloc_h) $(iddict_h) $(igstate_h) $(iname_h) $(isave_h) $(ivmspace_h)\
$(bfont_h) $(store_h)
@@ -444,7 +458,7 @@ $(PSOBJ)zht.$(OBJ) : $(PSSRC)zht.c $(OP) $(memory__h)\
$(PSCC) $(PSO_)zht.$(OBJ) $(C_) $(PSSRC)zht.c
$(PSOBJ)zimage.$(OBJ) : $(PSSRC)zimage.c $(OP)\
- $(gschar_h) $(gscspace_h) $(gscssub_h) $(gsimage_h) $(gsmatrix_h) $(gsstruct_h)\
+ $(gscspace_h) $(gscssub_h) $(gsimage_h) $(gsmatrix_h) $(gsstruct_h)\
$(gxiparam_h)\
$(estack_h) $(ialloc_h) $(ifilter_h) $(igstate_h) $(iimage_h) $(ilevel_h)\
$(store_h) $(stream_h)
@@ -474,7 +488,7 @@ INT6=$(PSOBJ)iutil.$(OBJ) $(GLOBJ)sa85d.$(OBJ) $(GLOBJ)scantab.$(OBJ)
INT7=$(PSOBJ)sfilter1.$(OBJ) $(GLOBJ)sstring.$(OBJ) $(GLOBJ)stream.$(OBJ)
Z1=$(PSOBJ)zarith.$(OBJ) $(PSOBJ)zarray.$(OBJ) $(PSOBJ)zcontrol.$(OBJ)
Z2=$(PSOBJ)zdict.$(OBJ) $(PSOBJ)zfile.$(OBJ) $(PSOBJ)zfileio.$(OBJ)
-Z3=$(PSOBJ)zfilter.$(OBJ) $(PSOBJ)zfname.$(OBJ) $(PSOBJ)zfproc.$(OBJ)
+Z3=$(PSOBJ)zfilter.$(OBJ) $(PSOBJ)zfproc.$(OBJ)
Z4=$(PSOBJ)zgeneric.$(OBJ) $(PSOBJ)ziodev.$(OBJ) $(PSOBJ)zmath.$(OBJ)
Z5=$(PSOBJ)zmisc.$(OBJ) $(PSOBJ)zpacked.$(OBJ) $(PSOBJ)zrelbit.$(OBJ)
Z6=$(PSOBJ)zstack.$(OBJ) $(PSOBJ)zstring.$(OBJ) $(PSOBJ)zsysvm.$(OBJ)
@@ -598,7 +612,8 @@ $(PSD)path1.dev : $(INT_MAK) $(ECHOGS_XE) $(path1_) $(GLD)path1lib.dev
$(ADDMOD) $(PSD)path1 -oper zpath1
$(PSOBJ)zpath1.$(OBJ) : $(PSSRC)zpath1.c $(OP) $(memory__h)\
- $(ialloc_h) $(estack_h) $(gspath_h) $(gsstruct_h) $(igstate_h) $(store_h)
+ $(ialloc_h) $(estack_h) $(gspath_h) $(gsstruct_h) $(igstate_h)\
+ $(oparc_h) $(store_h)
$(PSCC) $(PSO_)zpath1.$(OBJ) $(C_) $(PSSRC)zpath1.c
# ================ Level-independent PostScript options ================ #
@@ -678,17 +693,17 @@ $(PSOBJ)seexec.$(OBJ) : $(PSSRC)seexec.c $(AK) $(stdio__h)\
$(PSOBJ)zchar1.$(OBJ) : $(PSSRC)zchar1.c $(OP) $(memory__h)\
$(gspaint_h) $(gspath_h) $(gsrect_h) $(gsstruct_h)\
- $(gxchar_h) $(gxdevice_h) $(gxfixed_h) $(gxmatrix_h)\
+ $(gxdevice_h) $(gxfixed_h) $(gxmatrix_h)\
$(gxfont_h) $(gxfont1_h) $(gxtype1_h) $(gzstate_h)\
$(estack_h) $(ialloc_h) $(ichar_h) $(ichar1_h) $(icharout_h)\
$(idict_h) $(ifont_h) $(igstate_h) $(iname_h) $(store_h)
$(PSCC) $(PSO_)zchar1.$(OBJ) $(C_) $(PSSRC)zchar1.c
$(PSOBJ)zfont1.$(OBJ) : $(PSSRC)zfont1.c $(OP)\
- $(gsmatrix_h) $(gxdevice_h) $(gschar_h)\
+ $(gsmatrix_h) $(gxdevice_h)\
$(gxfixed_h) $(gxfont_h) $(gxfont1_h)\
- $(bfont_h) $(files_h) $(ialloc_h) $(idict_h) $(idparam_h) $(ifont1_h)\
- $(igstate_h) $(store_h) $(stream_h)
+ $(bfont_h) $(ialloc_h) $(icharout_h) $(idict_h) $(idparam_h)\
+ $(ifont1_h) $(iname_h) $(store_h)
$(PSCC) $(PSO_)zfont1.$(OBJ) $(C_) $(PSSRC)zfont1.c
$(PSOBJ)zmisc1.$(OBJ) : $(PSSRC)zmisc1.c $(OP) $(memory__h)\
@@ -723,13 +738,12 @@ $(PSD)type2.dev : $(INT_MAK) $(ECHOGS_XE) $(type2_)\
$(PSOBJ)zchar32.$(OBJ) : $(PSSRC)zchar32.c $(OP)\
$(gsccode_h) $(gsmatrix_h) $(gsutil_h)\
- $(gxchar_h) $(gxfcache_h) $(gxfixed_h) $(gxfont_h)\
+ $(gxfcache_h) $(gxfixed_h) $(gxfont_h)\
$(ifont_h) $(igstate_h) $(store_h)
$(PSCC) $(PSO_)zchar32.$(OBJ) $(C_) $(PSSRC)zchar32.c
$(PSOBJ)zfont32.$(OBJ) : $(PSSRC)zfont32.c $(OP)\
- $(gsccode_h) $(gsmatrix_h) $(gsutil_h)\
- $(gxchar_h) $(gxfixed_h) $(gxfont_h)\
+ $(gsccode_h) $(gsmatrix_h) $(gsutil_h) $(gxfont_h)\
$(bfont_h) $(store_h)
$(PSCC) $(PSO_)zfont32.$(OBJ) $(C_) $(PSSRC)zfont32.c
@@ -744,7 +758,7 @@ $(PSD)type32.dev : $(INT_MAK) $(ECHOGS_XE) $(type32_)
# Native TrueType support
$(PSD)ttfont.dev : $(INT_MAK) $(ECHOGS_XE) $(PSD)type42.dev
$(SETMOD) $(PSD)ttfont -include $(PSD)type42
- $(ADDMOD) $(PSD)ttfont -ps gs_mro_e gs_wan_e gs_ttf
+ $(ADDMOD) $(PSD)ttfont -ps gs_mro_e gs_mgl_e gs_wan_e gs_ttf
# Type 42 (embedded TrueType) support
type42read_=$(PSOBJ)zchar42.$(OBJ) $(PSOBJ)zcharout.$(OBJ) $(PSOBJ)zfont42.$(OBJ)
@@ -756,15 +770,15 @@ $(PSD)type42.dev : $(INT_MAK) $(ECHOGS_XE) $(type42read_) $(GLD)ttflib.dev
$(PSOBJ)zchar42.$(OBJ) : $(PSSRC)zchar42.c $(OP)\
$(gsmatrix_h) $(gspaint_h) $(gspath_h)\
- $(gxfixed_h) $(gxchar_h) $(gxfont_h) $(gxfont42_h)\
- $(gxistate_h) $(gxpath_h) $(gzstate_h)\
+ $(gxfixed_h) $(gxfont_h) $(gxfont42_h)\
+ $(gxistate_h) $(gxpath_h) $(gxtext_h) $(gzstate_h)\
$(dstack_h) $(estack_h) $(ichar_h) $(icharout_h)\
$(ifont_h) $(igstate_h) $(store_h)
$(PSCC) $(PSO_)zchar42.$(OBJ) $(C_) $(PSSRC)zchar42.c
$(PSOBJ)zfont42.$(OBJ) : $(PSSRC)zfont42.c $(OP) $(memory__h)\
$(gsccode_h) $(gsmatrix_h) $(gxfont_h) $(gxfont42_h)\
- $(bfont_h) $(idict_h) $(idparam_h) $(store_h)
+ $(bfont_h) $(icharout_h) $(idict_h) $(idparam_h) $(iname_h) $(store_h)
$(PSCC) $(PSO_)zfont42.$(OBJ) $(C_) $(PSSRC)zfont42.c
# ======================== Precompilation options ======================== #
@@ -967,6 +981,8 @@ $(PSD)psl2int.dev : $(INT_MAK) $(ECHOGS_XE) $(psl2int_)\
$(ADDMOD) $(PSD)psl2int -oper zmisc2
$(ADDMOD) $(PSD)psl2int -ps gs_lev2 gs_res
+ivmem2_h=$(PSSRC)ivmem2.h
+
$(PSOBJ)iutil2.$(OBJ) : $(PSSRC)iutil2.c $(GH) $(memory__h) $(string__h)\
$(gsparam_h) $(gsutil_h)\
$(errors_h) $(idict_h) $(imemory_h) $(iutil_h) $(iutil2_h) $(opcheck_h)
@@ -997,7 +1013,7 @@ $(PSD)usparam.dev : $(INT_MAK) $(ECHOGS_XE) $(usparam_)
$(PSOBJ)zusparam.$(OBJ) : $(PSSRC)zusparam.c $(OP) $(memory__h) $(string__h)\
$(gscdefs_h) $(gsfont_h) $(gsstruct_h) $(gsutil_h) $(gxht_h)\
$(ialloc_h) $(icontext_h) $(idict_h) $(idparam_h) $(iparam_h)\
- $(iname_h) $(iutil2_h)\
+ $(iname_h) $(iutil2_h) $(ivmem2_h)\
$(dstack_h) $(estack_h) $(store_h)
$(PSCC) $(PSO_)zusparam.$(OBJ) $(C_) $(PSSRC)zusparam.c
@@ -1033,7 +1049,7 @@ $(PSOBJ)zht2.$(OBJ) : $(PSSRC)zht2.c $(OP)\
$(PSCC) $(PSO_)zht2.$(OBJ) $(C_) $(PSSRC)zht2.c
$(PSOBJ)zimage2.$(OBJ) : $(PSSRC)zimage2.c $(OP) $(math__h) $(memory__h)\
- $(gschar_h) $(gscolor_h) $(gscolor2_h) $(gscspace_h) $(gsimage_h) $(gsmatrix_h)\
+ $(gscolor_h) $(gscolor2_h) $(gscspace_h) $(gsimage_h) $(gsmatrix_h)\
$(gxfixed_h)\
$(idict_h) $(idparam_h) $(iimage_h) $(iimage2_h) $(ilevel_h) $(igstate_h)
$(PSCC) $(PSO_)zimage2.$(OBJ) $(C_) $(PSSRC)zimage2.c
@@ -1047,7 +1063,8 @@ $(PSD)pagedev.dev : $(INT_MAK) $(ECHOGS_XE) $(pagedev_)
$(ADDMOD) $(PSD)pagedev -ps gs_setpd
$(PSOBJ)zdevice2.$(OBJ) : $(PSSRC)zdevice2.c $(OP) $(math__h) $(memory__h)\
- $(dstack_h) $(estack_h) $(idict_h) $(idparam_h) $(igstate_h) $(iname_h) $(store_h)\
+ $(dstack_h) $(estack_h)\
+ $(idict_h) $(idparam_h) $(igstate_h) $(iname_h) $(iutil_h) $(store_h)\
$(gxdevice_h) $(gsstate_h)
$(PSCC) $(PSO_)zdevice2.$(OBJ) $(C_) $(PSSRC)zdevice2.c
@@ -1084,7 +1101,8 @@ $(PSD)fdecode.dev : $(INT_MAK) $(ECHOGS_XE) $(fdecode_)\
$(PSOBJ)zfdecode.$(OBJ) : $(PSSRC)zfdecode.c $(OP) $(memory__h)\
$(gsparam_h) $(gsstruct_h)\
- $(ialloc_h) $(idict_h) $(idparam_h) $(ifilter_h) $(ilevel_h) $(iparam_h)\
+ $(ialloc_h) $(idict_h) $(idparam_h) $(ifilter_h) $(ifilter2_h) $(ifrpred_h)\
+ $(ilevel_h) $(iparam_h)\
$(sa85x_h) $(scf_h) $(scfx_h) $(sfilter_h) $(slzwx_h) $(spdiffx_h) $(spngpx_h)\
$(store_h) $(stream_h) $(strimpl_h)
$(PSCC) $(PSO_)zfdecode.$(OBJ) $(C_) $(PSSRC)zfdecode.c
@@ -1099,7 +1117,9 @@ $(PSD)filter.dev : $(INT_MAK) $(ECHOGS_XE) $(PSD)fdecode.dev $(filter_)\
$(ADDMOD) $(PSD)filter -oper zfilter2
$(PSOBJ)zfilter2.$(OBJ) : $(PSSRC)zfilter2.c $(OP) $(memory__h)\
- $(gsstruct_h) $(ialloc_h) $(idict_h) $(idparam_h) $(ifilter_h) $(store_h)\
+ $(gsstruct_h)\
+ $(ialloc_h) $(idict_h) $(idparam_h) $(ifilter_h) $(ifilter2_h) $(ifwpred_h)\
+ $(store_h)\
$(sfilter_h) $(scfx_h) $(slzwx_h) $(spdiffx_h) $(spngpx_h) $(strimpl_h)
$(PSCC) $(PSO_)zfilter2.$(OBJ) $(C_) $(PSSRC)zfilter2.c
@@ -1141,7 +1161,7 @@ $(PSD)nobtoken.dev : $(INT_MAK) $(ECHOGS_XE) $(nobtoken_)
$(SETMOD) $(PSD)nobtoken $(nobtoken_)
$(PSOBJ)inobtokn.$(OBJ) : $(PSSRC)inobtokn.c $(GH)\
- $(stream_h) $(errors_h) $(iscan_h)
+ $(stream_h) $(errors_h) $(iscan_h) $(iscanbin_h)
$(PSCC) $(PSO_)inobtokn.$(OBJ) $(C_) $(PSSRC)inobtokn.c
btoken_=$(PSOBJ)iscanbin.$(OBJ) $(PSOBJ)zbseq.$(OBJ)
@@ -1153,7 +1173,7 @@ $(PSD)btoken.dev : $(INT_MAK) $(ECHOGS_XE) $(btoken_)
$(PSOBJ)iscanbin.$(OBJ) : $(PSSRC)iscanbin.c $(GH)\
$(math__h) $(memory__h) $(errors_h)\
$(gsutil_h) $(ialloc_h) $(ibnum_h) $(iddict_h) $(iname_h)\
- $(iscan_h) $(iutil_h) $(ivmspace_h)\
+ $(iscan_h) $(iscanbin_h) $(iutil_h) $(ivmspace_h)\
$(btoken_h) $(dstack_h) $(ostack_h)\
$(sfilter_h) $(store_h) $(stream_h) $(strimpl_h)
$(PSCC) $(PSO_)iscanbin.$(OBJ) $(C_) $(PSSRC)iscanbin.c
@@ -1170,7 +1190,7 @@ $(PSD)upath.dev : $(INT_MAK) $(ECHOGS_XE) $(upath_)
$(ADDMOD) $(PSD)upath -oper zupath_l2
$(PSOBJ)zupath.$(OBJ) : $(PSSRC)zupath.c $(OP)\
- $(dstack_h) $(store_h)\
+ $(dstack_h) $(oparc_h) $(store_h)\
$(ibnum_h) $(idict_h) $(igstate_h) $(iname_h) $(iutil_h) $(stream_h)\
$(gscoord_h) $(gsmatrix_h) $(gspaint_h) $(gspath_h) $(gsstate_h)\
$(gxfixed_h) $(gxdevice_h) $(gzpath_h) $(gzstate_h)
@@ -1201,10 +1221,8 @@ $(PSOBJ)ibnum.$(OBJ) : $(PSSRC)ibnum.c $(GH) $(math__h) $(memory__h)\
$(PSCC) $(PSO_)ibnum.$(OBJ) $(C_) $(PSSRC)ibnum.c
$(PSOBJ)zcharx.$(OBJ) : $(PSSRC)zcharx.c $(OP)\
- $(gschar_h) $(gsmatrix_h) $(gspath_h) $(gsstruct_h)\
- $(gxchar_h) $(gxfixed_h) $(gxfont_h)\
- $(ialloc_h) $(ichar_h) $(estack_h) $(ifont_h) $(iname_h) $(igstate_h)\
- $(store_h) $(stream_h) $(ibnum_h)
+ $(gsmatrix_h) $(gstext_h) $(gxfixed_h) $(gxfont_h)\
+ $(ialloc_h) $(ibnum_h) $(ichar_h) $(iname_h) $(igstate_h)
$(PSCC) $(PSO_)zcharx.$(OBJ) $(C_) $(PSSRC)zcharx.c
$(PSOBJ)zdps1.$(OBJ) : $(PSSRC)zdps1.c $(OP)\
@@ -1213,7 +1231,7 @@ $(PSOBJ)zdps1.$(OBJ) : $(PSSRC)zdps1.c $(OP)\
$(PSCC) $(PSO_)zdps1.$(OBJ) $(C_) $(PSSRC)zdps1.c
$(PSOBJ)zvmem2.$(OBJ) : $(PSSRC)zvmem2.c $(OP)\
- $(estack_h) $(ialloc_h) $(ivmspace_h) $(store_h)
+ $(estack_h) $(ialloc_h) $(ivmspace_h) $(store_h) $(ivmem2_h)
$(PSCC) $(PSO_)zvmem2.$(OBJ) $(C_) $(PSSRC)zvmem2.c
# -------- Composite (PostScript Type 0) font support -------- #
@@ -1230,8 +1248,8 @@ $(PSD)psf0read.dev : $(INT_MAK) $(ECHOGS_XE) $(psf0read_)
$(ADDMOD) $(PSD)psf0read -oper zcfont zfcmap zfont0
$(PSOBJ)zcfont.$(OBJ) : $(PSSRC)zcfont.c $(OP)\
- $(gschar_h) $(gsmatrix_h)\
- $(gxchar_h) $(gxfixed_h) $(gxfont_h)\
+ $(gsmatrix_h)\
+ $(gxfixed_h) $(gxfont_h) $(gxtext_h)\
$(ichar_h) $(estack_h) $(ifont_h) $(igstate_h) $(store_h)
$(PSCC) $(PSO_)zcfont.$(OBJ) $(C_) $(PSSRC)zcfont.c
@@ -1242,7 +1260,7 @@ $(PSOBJ)zfcmap.$(OBJ) : $(PSSRC)zfcmap.c $(OP)\
$(PSCC) $(PSO_)zfcmap.$(OBJ) $(C_) $(PSSRC)zfcmap.c
$(PSOBJ)zfont0.$(OBJ) : $(PSSRC)zfont0.c $(OP)\
- $(gschar_h) $(gsstruct_h)\
+ $(gsstruct_h)\
$(gxdevice_h) $(gxfcmap_h) $(gxfixed_h) $(gxfont_h) $(gxfont0_h) $(gxmatrix_h)\
$(gzstate_h)\
$(bfont_h) $(ialloc_h) $(iddict_h) $(idparam_h) $(igstate_h) $(iname_h)\
@@ -1404,7 +1422,7 @@ $(PSD)fzlib.dev : $(INT_MAK) $(ECHOGS_XE) $(fzlib_)\
$(ADDMOD) $(PSD)fzlib -oper zfzlib
$(PSOBJ)zfzlib.$(OBJ) : $(PSSRC)zfzlib.c $(OP)\
- $(idict_h) $(ifilter_h)\
+ $(idict_h) $(ifilter_h) $(ifrpred_h) $(ifwpred_h)\
$(spdiffx_h) $(spngpx_h) $(strimpl_h) $(szlibx_h)
$(PSCC) $(PSO_)zfzlib.$(OBJ) $(C_) $(PSSRC)zfzlib.c
@@ -1420,7 +1438,8 @@ $(PSD)dps.dev : $(INT_MAK) $(ECHOGS_XE) $(GLD)dpslib.dev $(PSD)psl2.dev $(dps_)
$(PSOBJ)zdps.$(OBJ) : $(PSSRC)zdps.c $(OP)\
$(gsdps_h) $(gsimage_h) $(gsiparm2_h) $(gsstate_h)\
$(gxfixed_h) $(gxpath_h)\
- $(btoken_h) $(idparam_h) $(iddict_h) $(igstate_h) $(iname_h) $(store_h)
+ $(btoken_h)\
+ $(idparam_h) $(iddict_h) $(igstate_h) $(iimage2_h) $(iname_h) $(store_h)
$(PSCC) $(PSO_)zdps.$(OBJ) $(C_) $(PSSRC)zdps.c
$(PSOBJ)zcontext.$(OBJ) : $(PSSRC)zcontext.c $(OP) $(gp_h) $(memory__h)\
@@ -1443,7 +1462,7 @@ $(PSOBJ)zdpnext.$(OBJ) : $(PSSRC)zdpnext.c $(math__h) $(OP)\
$(gscoord_h) $(gscspace_h) $(gsdpnext_h)\
$(gsiparam_h) $(gsiparm2_h) $(gsmatrix_h) $(gspath2_h)\
$(gxcvalue_h) $(gxdevice_h) $(gxsample_h)\
- $(ialloc_h) $(igstate_h) $(iimage_h) $(store_h)
+ $(ialloc_h) $(igstate_h) $(iimage_h) $(iimage2_h) $(store_h)
$(PSCC) $(PSO_)zdpnext.$(OBJ) $(C_) $(PSSRC)zdpnext.c
# ==================== PostScript LanguageLevel 3 ===================== #
@@ -1484,6 +1503,16 @@ $(PSOBJ)zfunc3.$(OBJ) : $(PSSRC)zfunc3.c $(memory__h) $(OP)\
$(store_h) $(stream_h)
$(PSCC) $(PSO_)zfunc3.$(OBJ) $(C_) $(PSSRC)zfunc3.c
+# Note: FunctionType 4 functions are currently used only by PDF:
+# they are not included in PostScript LanguageLevel 3.
+
+$(PSOBJ)zfunc4.$(OBJ) : $(PSSRC)zfunc4.c $(memory__h) $(OP)\
+ $(gsfunc_h)\
+ $(files_h)\
+ $(ialloc_h) $(idict_h) $(idparam_h) $(ifunc_h) $(istkparm_h) $(istruct_h)\
+ $(opextern_h) $(store_h) $(stream_h)
+ $(PSCC) $(PSO_)zfunc4.$(OBJ) $(C_) $(PSSRC)zfunc4.c
+
$(PSOBJ)zimage3.$(OBJ) : $(PSSRC)zimage3.c $(OP) $(memory__h)\
$(gscolor2_h) $(gsiparm3_h) $(gsiparm4_h) $(gscspace_h) $(gxiparam_h)\
$(idparam_h) $(idict_h) $(igstate_h) $(iimage_h) $(iimage2_h)
@@ -1534,34 +1563,36 @@ $(PSD)trapping.dev : $(INT_MAK) $(ECHOGS_XE) $(GLD)traplib.dev $(PSD)trapread.de
# ================================ PDF ================================ #
-# We need most of the Level 2 interpreter to do PDF, but not all of it.
-# In fact, we don't even need all of a Level 1 interpreter.
+# We need nearly all of the PostScript LanguageLevel 3 interpreter for PDF,
+# but not all of it. In fact, we don't even need all of a Level 1 interpreter.
# Because of the way the PDF encodings are defined, they must get loaded
# before we install the Level 2 resource machinery.
# On the other hand, the PDF .ps files must get loaded after
# level2dict is defined.
-$(PSD)pdfmin.dev : $(INT_MAK) $(ECHOGS_XE)\
- $(PSD)psbase.dev $(PSD)color.dev $(PSD)compfont.dev $(GLD)dps2lib.dev $(PSD)dps2read.dev\
- $(PSD)fdecode.dev $(PSD)type1.dev $(PSD)pdffonts.dev $(GLD)psl2lib.dev $(PSD)psl2read.dev $(PSD)pdfread.dev
- $(SETMOD) $(PSD)pdfmin -include $(PSD)psbase $(PSD)color $(PSD)compfont $(GLD)dps2lib
- $(ADDMOD) $(PSD)pdfmin -include $(PSD)dps2read $(PSD)fdecode $(PSD)type1 $(PSD)pdffonts
- $(ADDMOD) $(PSD)pdfmin -include $(GLD)psl2lib $(PSD)psl2read $(PSD)pdfread
- $(ADDMOD) $(PSD)pdfmin -emulator PDF
-
$(PSD)pdf.dev : $(INT_MAK) $(ECHOGS_XE)\
- $(PSD)pdfmin.dev $(PSD)cff.dev $(PSD)cidfont.dev $(PSD)cie.dev $(PSD)cmapread.dev $(PSD)dctd.dev\
+ $(PSD)psbase.dev $(PSD)color.dev $(PSD)compfont.dev $(GLD)dps2lib.dev $(PSD)dps2read.dev\
+ $(PSD)fdecode.dev $(PSD)type1.dev $(PSD)pdffonts.dev $(GLD)psl2lib.dev $(PSD)psl2read.dev $(PSD)pdfread.dev\
+ $(PSD)cff.dev $(PSD)cidfont.dev $(PSD)cie.dev $(PSD)cmapread.dev $(PSD)dctd.dev\
$(PSD)func.dev $(PSD)ttfont.dev $(PSD)type2.dev
- $(SETMOD) $(PSD)pdf -include $(PSD)pdfmin $(PSD)cff $(PSD)cidfont $(PSD)cie
+ $(SETMOD) $(PSD)pdf -include $(PSD)psbase $(PSD)color $(PSD)compfont $(GLD)dps2lib
+ $(ADDMOD) $(PSD)pdf -include $(PSD)dps2read $(PSD)fdecode $(PSD)type1 $(PSD)pdffonts
+ $(ADDMOD) $(PSD)pdf -include $(GLD)psl2lib $(PSD)psl2read $(PSD)pdfread
+ $(ADDMOD) $(PSD)pdf -include $(PSD)cff $(PSD)cidfont $(PSD)cie
$(ADDMOD) $(PSD)pdf -include $(PSD)cmapread $(PSD)dctd $(PSD)func $(PSD)ttfont $(PSD)type2
+ $(ADDMOD) $(PSD)pdf -functiontype 4
+ $(ADDMOD) $(PSD)pdf -emulator PDF
# Reader only
$(PSD)pdffonts.dev : $(INT_MAK) $(ECHOGS_XE)
$(SETMOD) $(PSD)pdffonts -ps gs_mex_e gs_mro_e gs_pdf_e gs_wan_e
-$(PSD)pdfread.dev : $(INT_MAK) $(ECHOGS_XE) $(dpsnext_) $(PSD)fzlib.dev
+$(PSD)pdfread.dev : $(INT_MAK) $(ECHOGS_XE)\
+ $(dpsnext_) $(PSD)fzlib.dev $(PSOBJ)zfunc4.$(OBJ)
$(SETMOD) $(PSD)pdfread -include $(PSD)fzlib
+ $(ADDMOD) $(PSD)pdfread -obj $(PSOBJ)zfunc4.$(OBJ)
+ $(ADDMOD) $(PSD)pdfread -oper zfunc4
$(ADDMOD) $(PSD)pdfread -ps pdf_ops gs_l2img
$(ADDMOD) $(PSD)pdfread -ps pdf_base pdf_draw pdf_font pdf_main pdf_sec
@@ -1596,7 +1627,7 @@ $(PSOBJ)imainarg.$(OBJ) : $(PSSRC)imainarg.c $(GH)\
$(PSOBJ)imain.$(OBJ) : $(PSSRC)imain.c $(GH) $(memory__h) $(string__h)\
$(gp_h) $(gslib_h) $(gsmatrix_h) $(gsutil_h) $(gxdevice_h)\
$(dstack_h) $(errors_h) $(estack_h) $(files_h)\
- $(ialloc_h) $(idebug_h) $(idict_h) $(iname_h) $(interp_h)\
+ $(ialloc_h) $(idebug_h) $(idict_h) $(iinit_h) $(iname_h) $(interp_h)\
$(isave_h) $(iscan_h) $(ivmspace_h)\
$(main_h) $(oper_h) $(ostack_h)\
$(sfilter_h) $(store_h) $(stream_h) $(strimpl_h)
diff --git a/gs/src/interp.c b/gs/src/interp.c
index 136948950..015832bf0 100644
--- a/gs/src/interp.c
+++ b/gs/src/interp.c
@@ -71,11 +71,6 @@ public_st_dict_stack();
public_st_exec_stack();
public_st_op_stack();
-/* Imported operator procedures */
-extern int zop_add(P1(os_ptr));
-extern int zop_def(P1(i_ctx_t *));
-extern int zop_sub(P1(os_ptr));
-
/* Other imported procedures */
extern int ztokenexec_continue(P1(i_ctx_t *));
@@ -94,12 +89,7 @@ int (*gs_interp_reschedule_proc)(P1(i_ctx_t **)) = no_reschedule;
* The procedure to call for time-slicing.
* This is a no-op unless the context machinery has been installed.
*/
-int
-no_time_slice_proc(i_ctx_t **pi_ctx_p)
-{
- return 0;
-}
-int (*gs_interp_time_slice_proc)(P1(i_ctx_t **)) = no_time_slice_proc;
+int (*gs_interp_time_slice_proc)(P1(i_ctx_t **)) = 0;
/*
* The number of interpreter "ticks" between calls on the time_slice_proc.
@@ -146,7 +136,7 @@ private int estack_underflow(P1(i_ctx_t *));
private int interp(P3(i_ctx_t **, const ref *, ref *));
private int interp_exit(P1(i_ctx_t *));
private void set_gc_signal(P3(i_ctx_t *, int *, int));
-private int copy_stack(P2(const ref_stack_t *, ref *));
+private int copy_stack(P3(i_ctx_t *, const ref_stack_t *, ref *));
private int oparray_pop(P1(i_ctx_t *));
private int oparray_cleanup(P1(i_ctx_t *));
@@ -181,11 +171,12 @@ const int gs_interp_max_op_num_args = MIN_BLOCK_OSTACK; /* for iinit.c */
#endif
/*
* The minimum block size for extending the execution stack is the largest
- * size of a contiguous block surrounding an e-stack mark, currently ???.
- * At least, that's what the minimum value would be if we supported
- * multi-block estacks, which we currently don't.
+ * size of a contiguous block surrounding an e-stack mark. (At least,
+ * that's what the minimum value would be if we supported multi-block
+ * estacks, which we currently don't.) Currently, the largest such block is
+ * the one created for text processing, which is 8 (snumpush) slots.
*/
-#define MIN_BLOCK_ESTACK MAX_ESTACK
+#define MIN_BLOCK_ESTACK 8
/*
* Define the initial maximum size of the dictionary stack (MaxDictStack
@@ -284,26 +275,18 @@ const op_def interp_op_defs[] = {
/* Initialize the interpreter. */
int
-gs_interp_init(i_ctx_t **pi_ctx_p, const ref *psystem_dict)
+gs_interp_init(i_ctx_t **pi_ctx_p, const ref *psystem_dict,
+ gs_dual_memory_t *dmem)
{
/* Create and initialize a context state. */
gs_context_state_t *pcst = 0;
- int code = context_state_alloc(&pcst, &gs_imemory);
+ int code = context_state_alloc(&pcst, psystem_dict, dmem);
- if (code >= 0) {
- /*
- * We have to initialize the dictionary stack early,
- * for far-off references to systemdict.
- */
- pcst->dict_stack.system_dict = *psystem_dict;
- pcst->dict_stack.stack.extension_size = 0;
- pcst->dict_stack.min_size = 0;
+ if (code >= 0)
code = context_state_load(pcst);
- }
-
- *pi_ctx_p = pcst;
if (code < 0)
lprintf1("Fatal error %d in gs_interp_init!", code);
+ *pi_ctx_p = pcst;
return code;
}
/*
@@ -311,8 +294,10 @@ gs_interp_init(i_ctx_t **pi_ctx_p, const ref *psystem_dict)
* We export this for creating new contexts.
*/
int
-gs_interp_alloc_stacks(gs_ref_memory_t * smem, gs_context_state_t * pcst)
+gs_interp_alloc_stacks(gs_ref_memory_t *mem, gs_context_state_t * pcst)
{
+ gs_ref_memory_t *smem =
+ (gs_ref_memory_t *)gs_memory_stable((gs_memory_t *)mem);
ref stk;
#define REFS_SIZE_OSTACK OS_REFS_SIZE(MAX_OSTACK)
@@ -326,7 +311,8 @@ gs_interp_alloc_stacks(gs_ref_memory_t * smem, gs_context_state_t * pcst)
ref_stack_t *pos = &pcst->op_stack.stack;
r_set_size(&stk, REFS_SIZE_OSTACK);
- ref_stack_init(pos, &stk, OS_GUARD_UNDER, OS_GUARD_OVER, NULL, smem);
+ ref_stack_init(pos, &stk, OS_GUARD_UNDER, OS_GUARD_OVER, NULL,
+ smem, NULL);
ref_stack_set_error_codes(pos, e_stackunderflow, e_stackoverflow);
ref_stack_set_max_count(pos, MAX_OSTACK);
stk.value.refs += REFS_SIZE_OSTACK;
@@ -339,7 +325,7 @@ gs_interp_alloc_stacks(gs_ref_memory_t * smem, gs_context_state_t * pcst)
r_set_size(&stk, REFS_SIZE_ESTACK);
make_oper(&euop, 0, estack_underflow);
ref_stack_init(pes, &stk, ES_GUARD_UNDER, ES_GUARD_OVER, &euop,
- smem);
+ smem, NULL);
ref_stack_set_error_codes(pes, e_ExecStackUnderflow,
e_execstackoverflow);
/**************** E-STACK EXPANSION IS NYI. ****************/
@@ -352,7 +338,7 @@ gs_interp_alloc_stacks(gs_ref_memory_t * smem, gs_context_state_t * pcst)
ref_stack_t *pds = &pcst->dict_stack.stack;
r_set_size(&stk, REFS_SIZE_DSTACK);
- ref_stack_init(pds, &stk, 0, 0, NULL, smem);
+ ref_stack_init(pds, &stk, 0, 0, NULL, smem, NULL);
ref_stack_set_error_codes(pds, e_dictstackunderflow,
e_dictstackoverflow);
ref_stack_set_max_count(pds, MAX_DSTACK);
@@ -412,6 +398,24 @@ gs_interp_make_oper(ref * opref, op_proc_t proc, int idx)
}
/*
+ * Call the garbage collector, updating the context pointer properly.
+ */
+private int
+interp_reclaim(i_ctx_t **pi_ctx_p, int space)
+{
+ i_ctx_t *i_ctx_p = *pi_ctx_p;
+ gs_gc_root_t ctx_root;
+ int code;
+
+ gs_register_struct_root(imemory_system, &ctx_root,
+ (void **)pi_ctx_p, "interp_reclaim(pi_ctx_p)");
+ code = (*idmemory->reclaim)(idmemory, space);
+ i_ctx_p = *pi_ctx_p; /* may have moved */
+ gs_unregister_root(imemory_system, &ctx_root, "interp_reclaim(pi_ctx_p)");
+ return code;
+}
+
+/*
* Invoke the interpreter. If execution completes normally, return 0.
* If an error occurs, the action depends on user_errors as follows:
* user_errors < 0: always return an error code.
@@ -465,11 +469,9 @@ again:
/* Make sure that doref will get relocated properly if */
/* a garbage collection happens with epref == &doref. */
gs_register_ref_root(imemory_system, &epref_root,
- (void **)&epref,
- "gs_call_interpret(epref)");
- idmemory->reclaim_data = i_ctx_p;
- code = (*idmemory->reclaim) (idmemory, -1);
- *pi_ctx_p = i_ctx_p = idmemory->reclaim_data;
+ (void **)&epref, "gs_call_interpret(epref)");
+ code = interp_reclaim(pi_ctx_p, -1);
+ i_ctx_p = *pi_ctx_p;
gs_unregister_root(imemory_system, &epref_root,
"gs_call_interpret(epref)");
if (code < 0)
@@ -504,12 +506,11 @@ again:
goto again;
case e_VMreclaim:
/* Do the GC and continue. */
- idmemory->reclaim_data = i_ctx_p;
- code = (*idmemory->reclaim) (idmemory,
- (osp->value.intval == 2 ?
- avm_global : avm_local));
+ code = interp_reclaim(pi_ctx_p,
+ (osp->value.intval == 2 ?
+ avm_global : avm_local));
+ i_ctx_p = *pi_ctx_p;
/****** What if code < 0? ******/
- *pi_ctx_p = i_ctx_p = idmemory->reclaim_data;
make_oper(&doref, 0, zpop);
epref = &doref;
goto again;
@@ -533,7 +534,7 @@ again:
if ((ccode = ref_stack_extend(&o_stack, 1)) < 0)
return ccode;
}
- ccode = copy_stack(&d_stack, &saref);
+ ccode = copy_stack(i_ctx_p, &d_stack, &saref);
if (ccode < 0)
return ccode;
ref_stack_pop_to(&d_stack, min_dstack_size);
@@ -557,15 +558,30 @@ again:
if ((ccode = ref_stack_extend(&o_stack, 1)) < 0)
return ccode;
}
- ccode = copy_stack(&e_stack, &saref);
+ ccode = copy_stack(i_ctx_p, &e_stack, &saref);
if (ccode < 0)
return ccode;
{
uint count = ref_stack_count(&e_stack);
long limit = ref_stack_max_count(&e_stack) - 10;
- if (count > limit)
+ if (count > limit) {
+ /*
+ * If there is an e-stack mark within MIN_BLOCK_ESTACK of
+ * the new top, cut the stack back to remove the mark.
+ */
+ int i;
+
+ for (i = 0; i < MIN_BLOCK_ESTACK; ++i) {
+ const ref *ep = ref_stack_index(&e_stack, limit - i);
+
+ if (r_has_type_attrs(ep, t_null, a_executable)) {
+ limit -= i + 1;
+ break;
+ }
+ }
pop_estack(i_ctx_p, count - limit);
+ }
}
*++osp = saref;
break;
@@ -581,7 +597,7 @@ again:
epref = &doref;
goto again;
}
- ccode = copy_stack(&o_stack, &saref);
+ ccode = copy_stack(i_ctx_p, &o_stack, &saref);
if (ccode < 0)
return ccode;
ref_stack_clear(&o_stack);
@@ -625,19 +641,26 @@ set_gc_signal(i_ctx_t *i_ctx_p, int *psignal, int value)
for (i = 0; i < countof(idmemory->spaces_indexed); i++) {
gs_ref_memory_t *mem = idmemory->spaces_indexed[i];
+ gs_ref_memory_t *mem_stable;
- if (mem != 0) {
+ if (mem == 0)
+ continue;
+ for (;; mem = mem_stable) {
+ mem_stable = (gs_ref_memory_t *)
+ gs_memory_stable((gs_memory_t *)mem);
gs_memory_gc_status(mem, &stat);
stat.psignal = psignal;
stat.signal_value = value;
gs_memory_set_gc_status(mem, &stat);
+ if (mem_stable == mem)
+ break;
}
}
}
/* Copy the contents of an overflowed stack into a (local) array. */
private int
-copy_stack(const ref_stack_t * pstack, ref * arr)
+copy_stack(i_ctx_t *i_ctx_p, const ref_stack_t * pstack, ref * arr)
{
uint size = ref_stack_count(pstack);
uint save_space = ialloc_space(idmemory);
@@ -646,7 +669,8 @@ copy_stack(const ref_stack_t * pstack, ref * arr)
ialloc_set_space(idmemory, avm_local);
code = ialloc_ref_array(arr, a_all, size, "copy_stack");
if (code >= 0)
- code = ref_stack_store(pstack, arr, size, 0, 1, true, "copy_stack");
+ code = ref_stack_store(pstack, arr, size, 0, 1, true, idmemory,
+ "copy_stack");
ialloc_set_space(idmemory, save_space);
return code;
}
@@ -705,7 +729,18 @@ interp(i_ctx_t **pi_ctx_p /* context for execution, updated if resched */,
* time.
*/
register const ref_packed *iref_packed = (const ref_packed *)pref;
-#define IREF ((const ref *)iref_packed)
+ /*
+ * To make matters worse, some versions of gcc/egcs have a bug that
+ * leads them to assume that if iref_packed is EVER cast to a ref *,
+ * it is ALWAYS ref-aligned. We detect this in stdpre.h and provide
+ * the following workaround:
+ */
+#ifdef ALIGNMENT_ALIASING_BUG
+ const ref *iref_temp;
+# define IREF (iref_temp = (const ref *)iref_packed, iref_temp)
+#else
+# define IREF ((const ref *)iref_packed)
+#endif
#define SET_IREF(rp) (iref_packed = (const ref_packed *)(rp))
register int icount = 0; /* # of consecutive tokens at iref */
register os_ptr iosp = osp; /* private copy of osp */
@@ -1568,14 +1603,15 @@ res:
esp = iesp;
/* If ticks_left <= -100, we need to GC now. */
if (ticks_left <= -100) { /* We need to garbage collect now. */
- idmemory->reclaim_data = i_ctx_p;
- code = (*idmemory->reclaim) (idmemory, -1);
- *pi_ctx_p = i_ctx_p = idmemory->reclaim_data;
- } else {
+ *pi_ctx_p = i_ctx_p;
+ code = interp_reclaim(pi_ctx_p, -1);
+ i_ctx_p = *pi_ctx_p;
+ } else if (gs_interp_time_slice_proc) {
*pi_ctx_p = i_ctx_p;
code = (*gs_interp_time_slice_proc)(pi_ctx_p);
i_ctx_p = *pi_ctx_p;
- }
+ } else
+ code = 0;
ticks_left = gs_interp_time_slice_ticks;
goto sched;
diff --git a/gs/src/interp.h b/gs/src/interp.h
index 03bc94ffb..2d70161c3 100644
--- a/gs/src/interp.h
+++ b/gs/src/interp.h
@@ -62,7 +62,8 @@ int gs_errorname(P3(i_ctx_t *, int, ref *));
int gs_errorinfo_put_string(P2(i_ctx_t *, const char *));
/* Initialize the interpreter. */
-int gs_interp_init(P2(i_ctx_t **pi_ctx_p, const ref *psystem_dict));
+int gs_interp_init(P3(i_ctx_t **pi_ctx_p, const ref *psystem_dict,
+ gs_dual_memory_t *dmem));
#ifndef gs_context_state_t_DEFINED
# define gs_context_state_t_DEFINED
@@ -86,4 +87,8 @@ void gs_interp_free_stacks(P2(gs_ref_memory_t * smem,
/* Reset the interpreter. */
void gs_interp_reset(P1(i_ctx_t *i_ctx_p));
+/* Define the top-level interface to the interpreter. */
+int gs_interpret(P5(i_ctx_t **pi_ctx_p, ref * pref, int user_errors,
+ int *pexit_code, ref * perror_object));
+
#endif /* interp_INCLUDED */
diff --git a/gs/src/iparam.c b/gs/src/iparam.c
index 24f11aa17..1c45fb652 100644
--- a/gs/src/iparam.c
+++ b/gs/src/iparam.c
@@ -53,7 +53,7 @@ ref_param_key(const iparam_list * plist, gs_param_name pkey, ref * pkref)
/* Fill in a gs_param_key_t from a name or int ref. */
private int
-ref_to_key(const ref * pref, gs_param_key_t * key)
+ref_to_key(const ref * pref, gs_param_key_t * key, iparam_list *plist)
{
if (r_has_type(pref, t_name)) {
ref nref;
@@ -69,7 +69,7 @@ ref_to_key(const ref * pref, gs_param_key_t * key)
sprintf(istr, "%ld", pref->value.intval);
len = strlen(istr);
/* GC will take care of freeing this: */
- buf = ialloc_string(len, "ref_to_key");
+ buf = gs_alloc_string(plist->memory, len, "ref_to_key");
if (!buf)
return_error(e_VMerror);
key->data = buf;
@@ -81,6 +81,11 @@ ref_to_key(const ref * pref, gs_param_key_t * key)
/* ================ Writing parameters to refs ================ */
+/* Forward references */
+private int array_new_indexed_plist_write(P4(dict_param_list *plist,
+ ref *parray, const ref *pwanted,
+ gs_ref_memory_t *imem));
+
/* ---------------- Generic writing procedures ---------------- */
private param_proc_begin_xmit_collection(ref_param_begin_write_collection);
@@ -97,31 +102,35 @@ private const gs_param_list_procs ref_write_procs =
NULL, /* request */
ref_param_requested
};
-private int ref_array_param_requested(P5(const gs_param_list *, gs_param_name,
+private int ref_array_param_requested(P5(const iparam_list *, gs_param_name,
ref *, uint, client_name_t));
private int ref_param_write(P3(iparam_list *, gs_param_name, const ref *));
-private int ref_param_write_string_value(P2(ref *, const gs_param_string *));
+private int ref_param_write_string_value(P3(ref *, const gs_param_string *,
+ gs_ref_memory_t *));
private int ref_param_write_name_value(P2(ref *, const gs_param_string *));
private int
-ref_param_make_int(ref * pe, const void *pvalue, uint i)
+ref_param_make_int(ref *pe, const void *pvalue, uint i, gs_ref_memory_t *imem)
{
- make_int_new(pe, ((const gs_param_int_array *)pvalue)->data[i]);
+ make_tav(pe, t_integer, imemory_new_mask(imem), intval,
+ ((const gs_param_int_array *)pvalue)->data[i]);
return 0;
}
private int
-ref_param_make_float(ref * pe, const void *pvalue, uint i)
+ref_param_make_float(ref *pe, const void *pvalue, uint i, gs_ref_memory_t *imem)
{
- make_real_new(pe, ((const gs_param_float_array *)pvalue)->data[i]);
+ make_tav(pe, t_real, imemory_new_mask(imem), realval,
+ ((const gs_param_float_array *)pvalue)->data[i]);
return 0;
}
private int
-ref_param_make_string(ref * pe, const void *pvalue, uint i)
+ref_param_make_string(ref *pe, const void *pvalue, uint i, gs_ref_memory_t *imem)
{
return ref_param_write_string_value(pe,
- &((const gs_param_string_array *)pvalue)->data[i]);
+ &((const gs_param_string_array *)pvalue)->data[i],
+ imem);
}
private int
-ref_param_make_name(ref * pe, const void *pvalue, uint i)
+ref_param_make_name(ref * pe, const void *pvalue, uint i, gs_ref_memory_t *imem)
{
return ref_param_write_name_value(pe,
&((const gs_param_string_array *)pvalue)->data[i]);
@@ -129,7 +138,8 @@ ref_param_make_name(ref * pe, const void *pvalue, uint i)
private int
ref_param_write_typed_array(gs_param_list * plist, gs_param_name pkey,
void *pvalue, uint count,
- int (*make) (P3(ref *, const void *, uint)))
+ int (*make)(P4(ref *, const void *, uint,
+ gs_ref_memory_t *)))
{
iparam_list *const iplist = (iparam_list *) plist;
ref value;
@@ -137,11 +147,11 @@ ref_param_write_typed_array(gs_param_list * plist, gs_param_name pkey,
ref *pe;
int code;
- if ((code = ref_array_param_requested(plist, pkey, &value, count,
+ if ((code = ref_array_param_requested(iplist, pkey, &value, count,
"ref_param_write_typed_array")) <= 0)
return code;
for (i = 0, pe = value.value.refs; i < count; ++i, ++pe)
- if ((code = (*make) (pe, pvalue, i)) < 0)
+ if ((code = (*make) (pe, pvalue, i, iplist->ref_memory)) < 0)
return code;
return ref_param_write(iplist, pkey, &value);
}
@@ -150,9 +160,11 @@ ref_param_begin_write_collection(gs_param_list * plist, gs_param_name pkey,
gs_param_dict * pvalue,
gs_param_collection_type_t coll_type)
{
- dict_param_list *dlist =
- (dict_param_list *) ialloc_bytes(size_of(dict_param_list),
- "ref_param_begin_write_collection");
+ iparam_list *const iplist = (iparam_list *) plist;
+ gs_ref_memory_t *imem = iplist->ref_memory;
+ dict_param_list *dlist = (dict_param_list *)
+ gs_alloc_bytes(plist->memory, size_of(dict_param_list),
+ "ref_param_begin_write_collection");
int code;
if (dlist == 0)
@@ -160,21 +172,21 @@ ref_param_begin_write_collection(gs_param_list * plist, gs_param_name pkey,
if (coll_type != gs_param_collection_array) {
ref dref;
- code = dict_create(pvalue->size, &dref);
+ code = dict_alloc(imem, pvalue->size, &dref);
if (code >= 0) {
- code = dict_param_list_write(dlist, &dref, NULL);
+ code = dict_param_list_write(dlist, &dref, NULL, imem);
dlist->int_keys = coll_type == gs_param_collection_dict_int_keys;
}
} else {
ref aref;
- code = ialloc_ref_array(&aref, a_all, pvalue->size,
- "ref_param_begin_write_collection");
+ code = gs_alloc_ref_array(imem, &aref, a_all, pvalue->size,
+ "ref_param_begin_write_collection");
if (code >= 0)
- code = array_indexed_param_list_write(dlist, &aref, NULL);
+ code = array_new_indexed_plist_write(dlist, &aref, NULL, imem);
}
if (code < 0)
- ifree_object(dlist, "ref_param_begin_write_collection");
+ gs_free_object(plist->memory, dlist, "ref_param_begin_write_collection");
else
pvalue->list = (gs_param_list *) dlist;
return code;
@@ -187,7 +199,7 @@ ref_param_end_write_collection(gs_param_list * plist, gs_param_name pkey,
int code = ref_param_write(iplist, pkey,
&((dict_param_list *) pvalue->list)->dict);
- ifree_object(pvalue->list, "ref_param_end_write_collection");
+ gs_free_object(plist->memory, pvalue->list, "ref_param_end_write_collection");
return code;
}
private int
@@ -217,7 +229,8 @@ ref_param_write_typed(gs_param_list * plist, gs_param_name pkey,
case gs_param_type_string:
if (!ref_param_requested(plist, pkey))
return 0;
- code = ref_param_write_string_value(&value, &pvalue->value.s);
+ code = ref_param_write_string_value(&value, &pvalue->value.s,
+ iplist->ref_memory);
break;
case gs_param_type_name:
if (!ref_param_requested(plist, pkey))
@@ -272,14 +285,14 @@ ref_param_requested(const gs_param_list * plist, gs_param_name pkey)
/* Check whether an array parameter is wanted, and allocate it if so. */
/* Return <0 on error, 0 if not wanted, 1 if wanted. */
private int
-ref_array_param_requested(const gs_param_list * plist, gs_param_name pkey,
- ref * pvalue, uint size, client_name_t cname)
+ref_array_param_requested(const iparam_list *iplist, gs_param_name pkey,
+ ref *pvalue, uint size, client_name_t cname)
{
int code;
- if (!ref_param_requested(plist, pkey))
+ if (!ref_param_requested((const gs_param_list *)iplist, pkey))
return 0;
- code = ialloc_ref_array(pvalue, a_all, size, cname);
+ code = gs_alloc_ref_array(iplist->ref_memory, pvalue, a_all, size, cname);
return (code < 0 ? code : 1);
}
@@ -287,7 +300,8 @@ ref_array_param_requested(const gs_param_list * plist, gs_param_name pkey,
/* Prepare to write a string value. */
private int
-ref_param_write_string_value(ref * pref, const gs_param_string * pvalue)
+ref_param_write_string_value(ref * pref, const gs_param_string * pvalue,
+ gs_ref_memory_t *imem)
{
const byte *pdata = pvalue->data;
uint n = pvalue->size;
@@ -295,12 +309,13 @@ ref_param_write_string_value(ref * pref, const gs_param_string * pvalue)
if (pvalue->persistent)
make_const_string(pref, a_readonly | avm_foreign, n, pdata);
else {
- byte *pstr = ialloc_string(n, "ref_param_write_string");
+ byte *pstr = gs_alloc_string((gs_memory_t *)imem, n,
+ "ref_param_write_string");
if (pstr == 0)
return_error(e_VMerror);
memcpy(pstr, pdata, n);
- make_string(pref, a_readonly | icurrent_space, n, pstr);
+ make_string(pref, a_readonly | imemory_space(imem), n, pstr);
}
return 0;
}
@@ -332,10 +347,12 @@ ref_param_write(iparam_list * plist, gs_param_name pkey, const ref * pvalue)
/* Initialize for writing parameters. */
private void
-ref_param_write_init(iparam_list * plist, const ref * pwanted)
+ref_param_write_init(iparam_list * plist, const ref * pwanted,
+ gs_ref_memory_t *imem)
{
plist->procs = &ref_write_procs;
- plist->memory = imemory;
+ plist->memory = (gs_memory_t *)imem;
+ plist->ref_memory = imem;
if (pwanted == 0)
make_null(&plist->u.w.wanted);
else
@@ -385,17 +402,17 @@ stack_param_enumerate(iparam_list * plist, gs_param_enumerator_t * penum,
return 1;
} while (index += 2, !r_has_type(stack_element, t_name));
*type = r_type(stack_element);
- code = ref_to_key(stack_element, key);
+ code = ref_to_key(stack_element, key, plist);
penum->intval = index;
return code;
}
int
stack_param_list_write(stack_param_list * plist, ref_stack_t * pstack,
- const ref * pwanted)
+ const ref * pwanted, gs_ref_memory_t *imem)
{
plist->u.w.write = stack_param_write;
- ref_param_write_init((iparam_list *) plist, pwanted);
+ ref_param_write_init((iparam_list *) plist, pwanted, imem);
plist->enumerate = stack_param_enumerate;
plist->pstack = pstack;
plist->skip = 0;
@@ -428,28 +445,30 @@ dict_param_enumerate(iparam_list * plist, gs_param_enumerator_t * penum,
if (index < 0)
return 1;
*type = r_type(&elt[1]);
- code = ref_to_key(&elt[1], key);
+ code = ref_to_key(&elt[1], key, plist);
penum->intval = index;
return code;
}
int
-dict_param_list_write(dict_param_list * plist, ref * pdict, const ref * pwanted)
+dict_param_list_write(dict_param_list *plist, ref *pdict, const ref *pwanted,
+ gs_ref_memory_t *imem)
{
check_dict_write(*pdict);
plist->u.w.write = dict_param_write;
plist->enumerate = dict_param_enumerate;
- ref_param_write_init((iparam_list *) plist, pwanted);
+ ref_param_write_init((iparam_list *) plist, pwanted, imem);
plist->dict = *pdict;
return 0;
}
/* Implementation for getting parameters to an indexed array. */
+/* Note that this is now internal, since it only handles "new" arrays. */
private int
-array_indexed_param_write(iparam_list * plist, const ref * pkey,
+array_new_indexed_param_write(iparam_list * iplist, const ref * pkey,
const ref * pvalue)
{
- const ref *const arr = &((dict_param_list *) plist)->dict;
+ const ref *const arr = &((dict_param_list *)iplist)->dict;
ref *eltp;
if (!r_has_type(pkey, t_integer))
@@ -457,17 +476,19 @@ array_indexed_param_write(iparam_list * plist, const ref * pkey,
check_int_ltu(*pkey, r_size(arr));
store_check_dest(arr, pvalue);
eltp = arr->value.refs + pkey->value.intval;
- ref_assign_old(arr, eltp, pvalue, "array_indexed_param_write");
+ /* ref_assign_new(eltp, pvalue); */
+ ref_assign(eltp, pvalue);
+ r_set_attrs(eltp, imemory_new_mask(iplist->ref_memory));
return 0;
}
-int
-array_indexed_param_list_write(dict_param_list * plist, ref * parray,
- const ref * pwanted)
+private int
+array_new_indexed_plist_write(dict_param_list * plist, ref * parray,
+ const ref * pwanted, gs_ref_memory_t *imem)
{
check_array(*parray);
check_write(*parray);
- plist->u.w.write = array_indexed_param_write;
- ref_param_write_init((iparam_list *) plist, pwanted);
+ plist->u.w.write = array_new_indexed_param_write;
+ ref_param_write_init((iparam_list *) plist, pwanted, imem);
plist->dict = *parray;
plist->int_keys = true;
return 0;
@@ -527,8 +548,8 @@ ref_param_read_int_array(gs_param_list * plist, gs_param_name pkey,
if (code != 0)
return code;
size = r_size(loc.pvalue);
- piv = (int *)ialloc_byte_array(size, sizeof(int),
- "ref_param_read_int_array");
+ piv = (int *)gs_alloc_byte_array(plist->memory, size, sizeof(int),
+ "ref_param_read_int_array");
if (piv == 0)
return_error(e_VMerror);
@@ -549,7 +570,7 @@ ref_param_read_int_array(gs_param_list * plist, gs_param_name pkey,
piv[i] = (int)elt.value.intval;
}
if (code < 0) {
- ifree_object(piv, "ref_param_read_int_array");
+ gs_free_object(plist->memory, piv, "ref_param_read_int_array");
return (*loc.presult = code);
}
pvalue->data = piv;
@@ -572,8 +593,8 @@ ref_param_read_float_array(gs_param_list * plist, gs_param_name pkey,
if (code != 0)
return code;
size = r_size(loc.pvalue);
- pfv = (float *)ialloc_byte_array(size, sizeof(float),
- "ref_param_read_float_array");
+ pfv = (float *)gs_alloc_byte_array(plist->memory, size, sizeof(float),
+ "ref_param_read_float_array");
if (pfv == 0)
return_error(e_VMerror);
@@ -584,7 +605,7 @@ ref_param_read_float_array(gs_param_list * plist, gs_param_name pkey,
code = float_param(&elt, pfv + i);
}
if (code < 0) {
- ifree_object(pfv, "ref_read_float_array_param");
+ gs_free_object(plist->memory, pfv, "ref_read_float_array_param");
return (*loc.presult = code);
}
pvalue->data = pfv;
@@ -607,9 +628,9 @@ ref_param_read_string_array(gs_param_list * plist, gs_param_name pkey,
if (code != 0)
return code;
size = r_size(loc.pvalue);
- psv =
- (gs_param_string *) ialloc_byte_array(size, sizeof(gs_param_string),
- "ref_param_read_string_array");
+ psv = (gs_param_string *)
+ gs_alloc_byte_array(plist->memory, size, sizeof(gs_param_string),
+ "ref_param_read_string_array");
if (psv == 0)
return_error(e_VMerror);
aref = *loc.pvalue;
@@ -628,7 +649,7 @@ ref_param_read_string_array(gs_param_list * plist, gs_param_name pkey,
}
}
if (code < 0) {
- ifree_object(psv, "ref_param_read_string_array");
+ gs_free_object(plist->memory, psv, "ref_param_read_string_array");
return (*loc.presult = code);
}
pvalue->data = psv;
@@ -650,23 +671,25 @@ ref_param_begin_read_collection(gs_param_list * plist, gs_param_name pkey,
if (code != 0)
return code;
dlist = (dict_param_list *)
- ialloc_bytes(size_of(dict_param_list),
- "ref_param_begin_read_collection");
+ gs_alloc_bytes(plist->memory, size_of(dict_param_list),
+ "ref_param_begin_read_collection");
if (dlist == 0)
return_error(e_VMerror);
if (r_has_type(loc.pvalue, t_dictionary)) {
- code = dict_param_list_read(dlist, loc.pvalue, NULL, false);
+ code = dict_param_list_read(dlist, loc.pvalue, NULL, false,
+ iplist->ref_memory);
dlist->int_keys = int_keys;
if (code >= 0)
pvalue->size = dict_length(loc.pvalue);
} else if (int_keys && r_is_array(loc.pvalue)) {
- code = array_indexed_param_list_read(dlist, loc.pvalue, NULL, false);
+ code = array_indexed_param_list_read(dlist, loc.pvalue, NULL, false,
+ iplist->ref_memory);
if (code >= 0)
pvalue->size = r_size(loc.pvalue);
} else
code = gs_note_error(e_typecheck);
if (code < 0) {
- ifree_object(dlist, "ref_param_begin_write_collection");
+ gs_free_object(plist->memory, dlist, "ref_param_begin_write_collection");
return iparam_note_error(loc, code);
}
pvalue->list = (gs_param_list *) dlist;
@@ -677,7 +700,8 @@ ref_param_end_read_collection(gs_param_list * plist, gs_param_name pkey,
gs_param_dict * pvalue)
{
iparam_list_release((dict_param_list *) pvalue->list);
- ifree_object(pvalue->list, "ref_param_end_read_collection");
+ gs_free_object(plist->memory, pvalue->list,
+ "ref_param_end_read_collection");
return 0;
}
private int
@@ -901,18 +925,20 @@ empty_param_read(iparam_list * plist, const ref * pkey, iparam_loc * ploc)
/* Initialize for reading parameters. */
private int
ref_param_read_init(iparam_list * plist, uint count, const ref * ppolicies,
- bool require_all)
+ bool require_all, gs_ref_memory_t *imem)
{
plist->procs = &ref_read_procs;
- plist->memory = imemory;
+ plist->memory = (gs_memory_t *)imem;
+ plist->ref_memory = imem;
if (ppolicies == 0)
make_null(&plist->u.r.policies);
else
plist->u.r.policies = *ppolicies;
plist->u.r.require_all = require_all;
plist->count = count;
- plist->results =
- (int *)ialloc_byte_array(count, sizeof(int), "ref_param_read_init");
+ plist->results = (int *)
+ gs_alloc_byte_array(plist->memory, count, sizeof(int),
+ "ref_param_read_init");
if (plist->results == 0)
return_error(e_VMerror);
@@ -938,7 +964,8 @@ array_indexed_param_read(iparam_list * plist, const ref * pkey, iparam_loc * plo
}
int
array_indexed_param_list_read(dict_param_list * plist, const ref * parray,
- const ref * ppolicies, bool require_all)
+ const ref * ppolicies, bool require_all,
+ gs_ref_memory_t *ref_memory)
{
iparam_list *const iplist = (iparam_list *) plist;
int code;
@@ -947,7 +974,7 @@ array_indexed_param_list_read(dict_param_list * plist, const ref * parray,
plist->u.r.read = array_indexed_param_read;
plist->dict = *parray;
code = ref_param_read_init(iplist, r_size(parray), ppolicies,
- require_all);
+ require_all, ref_memory);
plist->int_keys = true;
return code;
}
@@ -985,7 +1012,7 @@ array_param_enumerate(iparam_list * plist, gs_param_enumerator_t * penum,
index += 2;
if (r_has_type(ptr, t_name)) {
- int code = ref_to_key(ptr, key);
+ int code = ref_to_key(ptr, key, plist);
*type = r_type(ptr);
penum->intval = index;
@@ -997,7 +1024,8 @@ array_param_enumerate(iparam_list * plist, gs_param_enumerator_t * penum,
int
array_param_list_read(array_param_list * plist, ref * bot, uint count,
- const ref * ppolicies, bool require_all)
+ const ref * ppolicies, bool require_all,
+ gs_ref_memory_t *imem)
{
iparam_list *const iplist = (iparam_list *) plist;
@@ -1007,7 +1035,7 @@ array_param_list_read(array_param_list * plist, ref * bot, uint count,
plist->enumerate = array_param_enumerate;
plist->bot = bot;
plist->top = bot + count;
- return ref_param_read_init(iplist, count, ppolicies, require_all);
+ return ref_param_read_init(iplist, count, ppolicies, require_all, imem);
}
/* Implementation for putting parameters from a stack. */
@@ -1035,7 +1063,8 @@ stack_param_read(iparam_list * plist, const ref * pkey, iparam_loc * ploc)
}
int
stack_param_list_read(stack_param_list * plist, ref_stack_t * pstack,
- uint skip, const ref * ppolicies, bool require_all)
+ uint skip, const ref * ppolicies, bool require_all,
+ gs_ref_memory_t *imem)
{
iparam_list *const iplist = (iparam_list *) plist;
uint count = ref_stack_counttomark(pstack);
@@ -1049,7 +1078,7 @@ stack_param_list_read(stack_param_list * plist, ref_stack_t * pstack,
plist->enumerate = stack_param_enumerate;
plist->pstack = pstack;
plist->skip = skip;
- return ref_param_read_init(iplist, count >> 1, ppolicies, require_all);
+ return ref_param_read_init(iplist, count >> 1, ppolicies, require_all, imem);
}
/* Implementation for putting parameters from a dictionary. */
@@ -1068,7 +1097,8 @@ dict_param_read(iparam_list * plist, const ref * pkey, iparam_loc * ploc)
}
int
dict_param_list_read(dict_param_list * plist, const ref * pdict,
- const ref * ppolicies, bool require_all)
+ const ref * ppolicies, bool require_all,
+ gs_ref_memory_t *imem)
{
iparam_list *const iplist = (iparam_list *) plist;
uint count;
@@ -1083,5 +1113,5 @@ dict_param_list_read(dict_param_list * plist, const ref * pdict,
count = dict_max_index(pdict) + 1;
}
plist->enumerate = dict_param_enumerate;
- return ref_param_read_init(iplist, count, ppolicies, require_all);
+ return ref_param_read_init(iplist, count, ppolicies, require_all, imem);
}
diff --git a/gs/src/iparam.h b/gs/src/iparam.h
index 60ba3dfe0..68039e156 100644
--- a/gs/src/iparam.h
+++ b/gs/src/iparam.h
@@ -44,22 +44,23 @@ typedef struct iparam_loc_s {
} iparam_loc;
#define iparam_list_common\
- gs_param_list_common;\
- union {\
- struct { /* reading */\
- int (*read)(P3(iparam_list *, const ref *, iparam_loc *));\
- ref policies; /* policy dictionary or null */\
- bool require_all; /* if true, require all params to be known */\
- } r;\
- struct { /* writing */\
- int (*write)(P3(iparam_list *, const ref *, const ref *));\
- ref wanted; /* desired keys or null */\
- } w;\
- } u;\
- int (*enumerate)(P4(iparam_list *, gs_param_enumerator_t *, gs_param_key_t *, ref_type *));\
- int *results; /* (only used when reading, 0 when writing) */\
- uint count; /* # of key/value pairs */\
- bool int_keys /* if true, keys are integers */
+ gs_param_list_common;\
+ gs_ref_memory_t *ref_memory; /* a properly typed copy of memory */\
+ union {\
+ struct { /* reading */\
+ int (*read)(P3(iparam_list *, const ref *, iparam_loc *));\
+ ref policies; /* policy dictionary or null */\
+ bool require_all; /* if true, require all params to be known */\
+ } r;\
+ struct { /* writing */\
+ int (*write)(P3(iparam_list *, const ref *, const ref *));\
+ ref wanted; /* desired keys or null */\
+ } w;\
+ } u;\
+ int (*enumerate)(P4(iparam_list *, gs_param_enumerator_t *, gs_param_key_t *, ref_type *));\
+ int *results; /* (only used when reading, 0 when writing) */\
+ uint count; /* # of key/value pairs */\
+ bool int_keys /* if true, keys are integers */
typedef struct iparam_list_s iparam_list;
struct iparam_list_s {
iparam_list_common;
@@ -91,22 +92,22 @@ typedef struct stack_param_list_s {
* If the bool parameter is true, if there are any unqueried parameters,
* the commit procedure will return an e_undefined error.
*/
-int dict_param_list_read(P4(dict_param_list *, const ref * /*t_dictionary */ ,
- const ref *, bool));
-int dict_param_list_write(P3(dict_param_list *, ref * /*t_dictionary */ ,
- const ref *));
-int array_indexed_param_list_read(P4(dict_param_list *, const ref * /*t_*array */ ,
- const ref *, bool));
-int array_indexed_param_list_write(P3(dict_param_list *, ref * /*t_*array */ ,
- const ref *));
-int array_param_list_read(P5(array_param_list *, ref *, uint,
- const ref *, bool));
-int stack_param_list_read(P5(stack_param_list *, ref_stack_t *, uint,
- const ref *, bool));
-int stack_param_list_write(P3(stack_param_list *, ref_stack_t *,
- const ref *));
+int dict_param_list_read(P5(dict_param_list *, const ref * /*t_dictionary */ ,
+ const ref *, bool, gs_ref_memory_t *));
+int dict_param_list_write(P4(dict_param_list *, ref * /*t_dictionary */ ,
+ const ref *, gs_ref_memory_t *));
+int array_indexed_param_list_read(P5(dict_param_list *, const ref * /*t_*array */ ,
+ const ref *, bool, gs_ref_memory_t *));
+int array_indexed_param_list_write(P4(dict_param_list *, ref * /*t_*array */ ,
+ const ref *, gs_ref_memory_t *));
+int array_param_list_read(P6(array_param_list *, ref *, uint,
+ const ref *, bool, gs_ref_memory_t *));
+int stack_param_list_read(P6(stack_param_list *, ref_stack_t *, uint,
+ const ref *, bool, gs_ref_memory_t *));
+int stack_param_list_write(P4(stack_param_list *, ref_stack_t *,
+ const ref *, gs_ref_memory_t *));
#define iparam_list_release(plist)\
- ifree_object((plist)->results, "iparam_list_release")
+ gs_free_object((plist)->memory, (plist)->results, "iparam_list_release")
#endif /* iparam_INCLUDED */
diff --git a/gs/src/iparray.h b/gs/src/iparray.h
index 44cb57df2..17ea0597d 100644
--- a/gs/src/iparray.h
+++ b/gs/src/iparray.h
@@ -18,6 +18,7 @@
/* Packed array constructor for Ghostscript */
+/* Requires ipacked.h, istack.h */
#ifndef iparray_INCLUDED
# define iparray_INCLUDED
@@ -31,6 +32,7 @@
/* Procedures implemented in zpacked.c */
/* Make a packed array from the top N elements of a stack. */
-int make_packed_array(P4(ref *, ref_stack_t *, uint, client_name_t));
+int make_packed_array(P5(ref *, ref_stack_t *, uint, gs_dual_memory_t *,
+ client_name_t));
#endif /* iparray_INCLUDED */
diff --git a/gs/src/ipcolor.h b/gs/src/ipcolor.h
index 0a21b4eda..fdf118d61 100644
--- a/gs/src/ipcolor.h
+++ b/gs/src/ipcolor.h
@@ -36,6 +36,7 @@ typedef struct int_pattern_s {
gs_private_st_ref_struct(st_int_pattern, int_pattern, "int_pattern")
/* Create an interpreter pattern structure. */
-int int_pattern_alloc(P2(int_pattern **ppdata, const ref *op));
+int int_pattern_alloc(P3(int_pattern **ppdata, const ref *op,
+ gs_memory_t *mem));
#endif /* ipcolor_INCLUDED */
diff --git a/gs/src/ireclaim.c b/gs/src/ireclaim.c
index b20b5ec47..0847ca24c 100644
--- a/gs/src/ireclaim.c
+++ b/gs/src/ireclaim.c
@@ -55,8 +55,10 @@ ireclaim(gs_dual_memory_t * dmem, int space)
bool global;
gs_ref_memory_t *mem;
- if (space < 0) { /* Determine which allocator got the VMerror. */
+ if (space < 0) {
+ /* Determine which allocator got the VMerror. */
gs_memory_status_t stats;
+ ulong allocated;
int i;
mem = dmem->space_global; /* just in case */
@@ -64,11 +66,19 @@ ireclaim(gs_dual_memory_t * dmem, int space)
mem = dmem->spaces_indexed[i];
if (mem == 0)
continue;
- if (mem->gc_status.requested > 0)
+ if (mem->gc_status.requested > 0 ||
+ ((gs_ref_memory_t *)mem->stable_memory)->gc_status.requested > 0
+ )
break;
}
gs_memory_status((gs_memory_t *) mem, &stats);
- if (stats.allocated >= mem->gc_status.max_vm) { /* We can't satisfy this request within max_vm. */
+ allocated = stats.allocated;
+ if (mem->stable_memory != (gs_memory_t *)mem) {
+ gs_memory_status(mem->stable_memory, &stats);
+ allocated += stats.allocated;
+ }
+ if (allocated >= mem->gc_status.max_vm) {
+ /* We can't satisfy this request within max_vm. */
return_error(e_VMerror);
}
} else {
@@ -77,62 +87,75 @@ ireclaim(gs_dual_memory_t * dmem, int space)
if_debug3('0', "[0]GC called, space=%d, requestor=%d, requested=%ld\n",
space, mem->space, (long)mem->gc_status.requested);
global = mem->space != avm_local;
+ /* Since dmem may move, reset the request now. */
+ ialloc_reset_requested(dmem);
gs_vmreclaim(dmem, global);
ialloc_set_limit(mem);
- ialloc_reset_requested(dmem);
return 0;
}
/* Interpreter entry to garbage collector. */
private void
-gs_vmreclaim(gs_dual_memory_t * dmem, bool global)
+gs_vmreclaim(gs_dual_memory_t *dmem, bool global)
{
- i_ctx_t *i_ctx_p = dmem->reclaim_data;
+ /* HACK: we know the gs_dual_memory_t is embedded in a context state. */
+ i_ctx_t *i_ctx_p =
+ (i_ctx_t *)((char *)dmem - offset_of(i_ctx_t, memory));
gs_ref_memory_t *lmem = dmem->space_local;
- gs_ref_memory_t *gmem = dmem->space_global;
- gs_ref_memory_t *smem = dmem->space_system;
int code = context_state_store(i_ctx_p);
+ gs_ref_memory_t *memories[5];
+ gs_ref_memory_t *mem;
+ int nmem, i;
+
+ memories[0] = dmem->space_system;
+ memories[1] = mem = dmem->space_global;
+ nmem = 2;
+ if (lmem != dmem->space_global)
+ memories[nmem++] = lmem;
+ for (i = nmem; --i >= 0;) {
+ mem = memories[i];
+ if (mem->stable_memory != (gs_memory_t *)mem)
+ memories[nmem++] = (gs_ref_memory_t *)mem->stable_memory;
+ }
-/****** ABORT IF code < 0 ******/
- alloc_close_chunk(lmem);
- if (gmem != lmem)
- alloc_close_chunk(gmem);
- alloc_close_chunk(smem);
+ /****** ABORT IF code < 0 ******/
+ for (i = nmem; --i >= 0; )
+ alloc_close_chunk(memories[i]);
/* Prune the file list so it won't retain potentially collectible */
/* files. */
- {
- int i;
-
- for (i = (global ? i_vm_system : i_vm_local);
- i < countof(dmem->spaces_indexed);
- ++i
- ) {
- gs_ref_memory_t *mem = dmem->spaces_indexed[i];
-
- if (mem == 0 || (i > 0 && mem == dmem->spaces_indexed[i - 1]))
- continue;
- for (;; mem = &mem->saved->state) {
- ialloc_gc_prepare(mem);
- if (mem->saved == 0)
- break;
- }
+ for (i = (global ? i_vm_system : i_vm_local);
+ i < countof(dmem->spaces_indexed);
+ ++i
+ ) {
+ gs_ref_memory_t *mem = dmem->spaces_indexed[i];
+
+ if (mem == 0 || (i > 0 && mem == dmem->spaces_indexed[i - 1]))
+ continue;
+ if (mem->stable_memory != (gs_memory_t *)mem)
+ ialloc_gc_prepare((gs_ref_memory_t *)mem->stable_memory);
+ for (;; mem = &mem->saved->state) {
+ ialloc_gc_prepare(mem);
+ if (mem->saved == 0)
+ break;
}
}
/* Do the actual collection. */
{
+ void *ctxp = i_ctx_p;
gs_gc_root_t context_root;
gs_register_struct_root((gs_memory_t *)lmem, &context_root,
- (void **)&dmem->reclaim_data, "reclaim_data");
+ &ctxp, "i_ctx_p root");
GS_RECLAIM(&dmem->spaces, global);
- gs_unregister_root((gs_memory_t *)lmem, &context_root, "reclaim_data");
+ gs_unregister_root((gs_memory_t *)lmem, &context_root, "i_ctx_p root");
+ i_ctx_p = ctxp;
+ dmem = &i_ctx_p->memory;
}
- i_ctx_p = dmem->reclaim_data;
/* Update caches not handled by context_state_load. */
@@ -142,11 +165,6 @@ gs_vmreclaim(gs_dual_memory_t * dmem, bool global)
code = context_state_load(i_ctx_p);
/****** ABORT IF code < 0 ******/
- /*
- * context_state_load overwrites gs_memory (*dmem): put back the
- * relocated context pointer.
- */
- dmem->reclaim_data = i_ctx_p;
/* Update the cached value pointers in names. */
@@ -154,10 +172,8 @@ gs_vmreclaim(gs_dual_memory_t * dmem, bool global)
/* Reopen the active chunks. */
- alloc_open_chunk(smem);
- if (gmem != lmem)
- alloc_open_chunk(gmem);
- alloc_open_chunk(lmem);
+ for (i = 0; i < nmem; ++i)
+ alloc_open_chunk(memories[i]);
}
/* ------ Initialization procedure ------ */
diff --git a/gs/src/isave.c b/gs/src/isave.c
index 686e5ac42..10507b2f2 100644
--- a/gs/src/isave.c
+++ b/gs/src/isave.c
@@ -166,8 +166,8 @@ struct alloc_change_s {
alloc_change_t *next;
ref_packed *where;
ref contents;
-#define ac_offset_static (-2) /* static object */
-#define ac_offset_ref (-1) /* dynamic ref */
+#define AC_OFFSET_STATIC (-2) /* static object */
+#define AC_OFFSET_REF (-1) /* dynamic ref */
short offset; /* if >= 0, offset within struct */
};
@@ -196,9 +196,9 @@ private RELOC_PTRS_WITH(change_reloc_ptrs, alloc_change_t *ptr)
{
RELOC_VAR(ptr->next);
switch (ptr->offset) {
- case ac_offset_static:
+ case AC_OFFSET_STATIC:
break;
- case ac_offset_ref:
+ case AC_OFFSET_REF:
RELOC_REF_PTR_VAR(ptr->where);
break;
default:
@@ -259,28 +259,44 @@ private void save_set_new_changes(P2(gs_ref_memory_t *, bool));
void
alloc_save_init(gs_dual_memory_t * dmem)
{
- dmem->save_level = 0;
alloc_set_not_in_save(dmem);
}
/* Record that we are in a save. */
+private void
+alloc_set_masks(gs_dual_memory_t *dmem, uint new_mask, uint test_mask)
+{
+ int i;
+ gs_ref_memory_t *mem;
+
+ dmem->new_mask = new_mask;
+ dmem->test_mask = test_mask;
+ for (i = 0; i < countof(dmem->spaces.memories.indexed); ++i)
+ if ((mem = dmem->spaces.memories.indexed[i]) != 0) {
+ mem->new_mask = new_mask, mem->test_mask = test_mask;
+ if (mem->stable_memory != (gs_memory_t *)mem) {
+ mem = (gs_ref_memory_t *)mem->stable_memory;
+ mem->new_mask = new_mask, mem->test_mask = test_mask;
+ }
+ }
+}
void
alloc_set_in_save(gs_dual_memory_t *dmem)
{
- dmem->test_mask = dmem->new_mask = l_new;
+ alloc_set_masks(dmem, l_new, l_new);
}
/* Record that we are not in a save. */
void
alloc_set_not_in_save(gs_dual_memory_t *dmem)
{
- dmem->test_mask = ~0;
- dmem->new_mask = 0;
+ alloc_set_masks(dmem, 0, ~0);
}
/* Save the state. */
-private alloc_save_t *alloc_save_space(P2(gs_ref_memory_t *,
- gs_dual_memory_t *));
+private alloc_save_t *alloc_save_space(P3(gs_ref_memory_t *mem,
+ gs_dual_memory_t *dmem,
+ ulong sid));
private void
alloc_free_save(gs_ref_memory_t *mem, alloc_save_t *save, const char *scn,
const char *icn)
@@ -297,11 +313,11 @@ alloc_save_state(gs_dual_memory_t * dmem, void *cdata)
gs_ref_memory_t *gmem = dmem->space_global;
ulong sid = gs_next_ids(2);
bool global =
- dmem->save_level == 0 && gmem != lmem &&
+ lmem->save_level == 0 && gmem != lmem &&
gmem->num_contexts == 1;
alloc_save_t *gsave =
- (global ? alloc_save_space(gmem, dmem) : (alloc_save_t *) 0);
- alloc_save_t *lsave = alloc_save_space(lmem, dmem);
+ (global ? alloc_save_space(gmem, dmem, sid + 1) : (alloc_save_t *) 0);
+ alloc_save_t *lsave = alloc_save_space(lmem, dmem, sid);
if (lsave == 0 || (global &&gsave == 0)) {
if (lsave != 0)
@@ -313,7 +329,6 @@ alloc_save_state(gs_dual_memory_t * dmem, void *cdata)
return 0;
}
if (gsave != 0) {
- gsave->id = sid + 1;
gsave->client_data = 0;
print_save("save", gmem->space, gsave);
/* Restore names when we do the local restore. */
@@ -326,19 +341,20 @@ alloc_save_state(gs_dual_memory_t * dmem, void *cdata)
/* Reset the l_new attribute in all slots. The only slots that */
/* can have the attribute set are the ones on the changes chain, */
/* and ones in objects allocated since the last save. */
- if (dmem->save_level != 0) {
+ if (lmem->save_level > 1) {
long scanned = save_set_new(&lsave->state, false);
if ((lsave->state.total_scanned += scanned) > max_repeated_scan) {
/* Do a second, invisible save. */
alloc_save_t *rsave;
- rsave = alloc_save_space(lmem, dmem);
+ rsave = alloc_save_space(lmem, dmem, 0L);
if (rsave != 0) {
- rsave->id = sid;
rsave->client_data = cdata;
+ rsave->id = lsave->id;
print_save("save", lmem->space, rsave);
lsave->id = 0; /* mark as invisible */
+ rsave->state.save_level--; /* ditto */
lsave->client_data = 0;
/* Inherit the allocated space count -- */
/* we need this for triggering a GC. */
@@ -349,13 +365,12 @@ alloc_save_state(gs_dual_memory_t * dmem, void *cdata)
}
}
}
- dmem->save_level++;
alloc_set_in_save(dmem);
return sid;
}
/* Save the state of one space (global or local). */
private alloc_save_t *
-alloc_save_space(gs_ref_memory_t * mem, gs_dual_memory_t * dmem)
+alloc_save_space(gs_ref_memory_t * mem, gs_dual_memory_t * dmem, ulong sid)
{
gs_ref_memory_t save_mem;
alloc_save_t *save;
@@ -403,40 +418,40 @@ alloc_save_space(gs_ref_memory_t * mem, gs_dual_memory_t * dmem)
return 0;
}
save->state = save_mem;
- save->dmem = dmem;
+ save->spaces = dmem->spaces;
save->restore_names = (name_memory() == (gs_memory_t *) mem);
save->is_current = (dmem->current == mem);
+ save->id = sid;
mem->saved = save;
if_debug2('u', "[u%u]file_save 0x%lx\n",
mem->space, (ulong) mem->streams);
mem->streams = 0;
mem->total_scanned = 0;
+ if (sid)
+ mem->save_level++;
return save;
}
/* Record a state change that must be undone for restore, */
/* and mark it as having been saved. */
int
-alloc_save_change(gs_dual_memory_t * dmem, const ref * pcont,
+alloc_save_change_in(gs_ref_memory_t *mem, const ref * pcont,
ref_packed * where, client_name_t cname)
{
- gs_ref_memory_t *mem;
register alloc_change_t *cp;
- if (dmem->save_level == 0)
+ if (mem->new_mask == 0)
return 0; /* no saving */
- mem = (pcont == NULL ? dmem->space_local :
- dmem->spaces_indexed[r_space(pcont) >> r_space_shift]);
- cp = gs_alloc_struct((gs_memory_t *) mem, alloc_change_t,
+ cp = gs_alloc_struct((gs_memory_t *)mem, alloc_change_t,
&st_alloc_change, "alloc_save_change");
if (cp == 0)
return -1;
cp->next = mem->changes;
cp->where = where;
if (pcont == NULL)
- cp->offset = ac_offset_static;
+ cp->offset = AC_OFFSET_STATIC;
else if (r_is_array(pcont) || r_has_type(pcont, t_dictionary))
- cp->offset = ac_offset_ref;
+ cp->offset = AC_OFFSET_REF;
else if (r_is_struct(pcont))
cp->offset = (byte *) where - (byte *) pcont->value.pstruct;
else {
@@ -445,7 +460,7 @@ alloc_save_change(gs_dual_memory_t * dmem, const ref * pcont,
gs_abort();
}
if (r_is_packed(where))
- *(ref_packed *) & cp->contents = *where;
+ *(ref_packed *)&cp->contents = *where;
else {
ref_assign_inline(&cp->contents, (ref *) where);
r_set_attrs((ref *) where, l_new);
@@ -459,12 +474,15 @@ alloc_save_change(gs_dual_memory_t * dmem, const ref * pcont,
#endif
return 0;
}
-
-/* Return the current save level */
int
-alloc_save_level(const gs_dual_memory_t * dmem)
+alloc_save_change(gs_dual_memory_t * dmem, const ref * pcont,
+ ref_packed * where, client_name_t cname)
{
- return dmem->save_level;
+ gs_ref_memory_t *mem =
+ (pcont == NULL ? dmem->space_local :
+ dmem->spaces_indexed[r_space(pcont) >> r_space_shift]);
+
+ return alloc_save_change_in(mem, pcont, where, cname);
}
/* Return (the id of) the innermost externally visible save object, */
@@ -488,13 +506,11 @@ alloc_save_current(const gs_dual_memory_t * dmem)
bool
alloc_is_since_save(const void *vptr, const alloc_save_t * save)
{
-#define ptr ((const char *)vptr)
-
/* A reference postdates a save iff it is in a chunk allocated */
/* since the save (including the carried-over inner chunk). */
- const gs_dual_memory_t *dmem = save->dmem;
- register const gs_ref_memory_t *mem = dmem->space_local;
+ const char *const ptr = (const char *)vptr;
+ register const gs_ref_memory_t *mem = save->space_local;
if_debug2('U', "[U]is_since_save 0x%lx, 0x%lx:\n",
(ulong) ptr, (ulong) save);
@@ -530,9 +546,9 @@ alloc_is_since_save(const void *vptr, const alloc_save_t * save)
* outermost save), we also have to check the global save.
* Global saves can't be nested, which makes things easy.
*/
- if (dmem->save_level == 1 &&
- (mem = dmem->space_global) != dmem->space_local &&
- dmem->space_global->num_contexts == 1
+ if (mem->save_level == 1 &&
+ (mem = save->space_global) != save->space_local &&
+ save->space_global->num_contexts == 1
) {
const chunk_t *cp;
@@ -553,14 +569,14 @@ alloc_is_since_save(const void *vptr, const alloc_save_t * save)
bool
alloc_name_is_since_save(const ref * pnref, const alloc_save_t * save)
{
- const name *pname;
+ const name_string_t *pnstr;
if (!save->restore_names)
return false;
- pname = pnref->value.pname;
- if (pname->foreign_string)
+ pnstr = names_string_inline(the_gs_name_table, pnref);
+ if (pnstr->foreign_string)
return false;
- return alloc_is_since_save(pname->string_bytes, save);
+ return alloc_is_since_save(pnstr->string_bytes, save);
}
bool
alloc_name_index_is_since_save(uint nidx, const alloc_save_t * save)
@@ -613,13 +629,15 @@ alloc_save_client_data(const alloc_save_t * save)
* and global VM) or if we created extra save levels to reduce scanning.
*/
private void restore_finalize(P1(gs_ref_memory_t *));
-private void restore_space(P1(gs_ref_memory_t *));
+private void restore_space(P2(gs_ref_memory_t *, gs_dual_memory_t *));
bool
-alloc_restore_state_step(alloc_save_t * save)
+alloc_restore_step_in(gs_dual_memory_t *dmem, alloc_save_t * save)
{
- gs_dual_memory_t *dmem = save->dmem;
- gs_ref_memory_t *mem = dmem->space_local;
+ /* Get save->space_* now, because the save object will be freed. */
+ gs_ref_memory_t *lmem = save->space_local;
+ gs_ref_memory_t *gmem = save->space_global;
+ gs_ref_memory_t *mem = lmem;
alloc_save_t *sprev;
/* Do one (externally visible) step of restoring the state. */
@@ -630,21 +648,20 @@ alloc_restore_state_step(alloc_save_t * save)
sid = sprev->id;
restore_finalize(mem); /* finalize objects */
restore_resources(sprev, mem); /* release other resources */
- restore_space(mem); /* release memory */
- if (sid != 0) {
- dmem->save_level--;
+ restore_space(mem, dmem); /* release memory */
+ if (sid != 0)
break;
- }
}
while (sprev != save);
- if (dmem->save_level == 0) { /* This is the outermost save, which might also */
+ if (mem->save_level == 0) {
+ /* This is the outermost save, which might also */
/* need to restore global VM. */
- mem = dmem->space_global;
- if (mem != dmem->space_local && mem->saved != 0) {
+ mem = gmem;
+ if (mem != lmem && mem->saved != 0) {
restore_finalize(mem);
restore_resources(mem->saved, mem);
- restore_space(mem);
+ restore_space(mem, dmem);
}
alloc_set_not_in_save(dmem);
} else { /* Set the l_new attribute in all slots that are now new. */
@@ -656,7 +673,7 @@ alloc_restore_state_step(alloc_save_t * save)
/* Restore the memory of one space, by undoing changes and freeing */
/* memory allocated since the save. */
private void
-restore_space(gs_ref_memory_t * mem)
+restore_space(gs_ref_memory_t * mem, gs_dual_memory_t *dmem)
{
alloc_save_t *save = mem->saved;
alloc_save_t saved;
@@ -699,8 +716,6 @@ restore_space(gs_ref_memory_t * mem)
/* Make the allocator current if it was current before the save. */
if (saved.is_current) {
- gs_dual_memory_t *dmem = saved.dmem;
-
dmem->current = mem;
dmem->current_space = mem->space;
}
@@ -711,41 +726,52 @@ restore_space(gs_ref_memory_t * mem)
void
alloc_restore_all(gs_dual_memory_t * dmem)
{
+ /*
+ * Save the memory pointers, since freeing space_local will also
+ * free dmem itself.
+ */
+ gs_ref_memory_t *lmem = dmem->space_local;
+ gs_ref_memory_t *gmem = dmem->space_global;
+ gs_ref_memory_t *smem = dmem->space_system;
+ gs_ref_memory_t *mem;
+
/* Restore to a state outside any saves. */
- while (dmem->save_level != 0)
- discard(alloc_restore_state_step(dmem->space_local->saved));
+ while (lmem->save_level != 0)
+ discard(alloc_restore_step_in(dmem, lmem->saved));
/* Finalize memory. */
- restore_finalize(dmem->space_local);
- {
- gs_ref_memory_t *mem = dmem->space_global;
-
- if (mem != dmem->space_local && mem->num_contexts == 1)
+ restore_finalize(lmem);
+ if ((mem = (gs_ref_memory_t *)lmem) != lmem)
+ restore_finalize(mem);
+ if (gmem != lmem && gmem->num_contexts == 1) {
+ restore_finalize(gmem);
+ if ((mem = (gs_ref_memory_t *)gmem) != gmem)
restore_finalize(mem);
}
- restore_finalize(dmem->space_system);
+ restore_finalize(smem);
/* Release resources other than memory, using fake */
/* save and memory objects. */
{
alloc_save_t empty_save;
- empty_save.dmem = dmem;
+ empty_save.spaces = dmem->spaces;
empty_save.restore_names = false; /* don't bother to release */
restore_resources(&empty_save, NULL);
}
/* Finally, release memory. */
- restore_free(dmem->space_local);
- {
- gs_ref_memory_t *mem = dmem->space_global;
-
- if (mem != dmem->space_local) {
- if (!--(mem->num_contexts))
+ restore_free(lmem);
+ if ((mem = (gs_ref_memory_t *)lmem) != lmem)
+ restore_free(mem);
+ if (gmem != lmem) {
+ if (!--(gmem->num_contexts)) {
+ restore_free(gmem);
+ if ((mem = (gs_ref_memory_t *)gmem) != gmem)
restore_free(mem);
}
}
- restore_free(dmem->space_system);
+ restore_free(smem);
}
@@ -811,10 +837,9 @@ private void file_forget_save(P1(gs_ref_memory_t *));
private void combine_space(P1(gs_ref_memory_t *));
private void forget_changes(P1(gs_ref_memory_t *));
void
-alloc_forget_save(alloc_save_t * save)
+alloc_forget_save_in(gs_dual_memory_t *dmem, alloc_save_t * save)
{
- gs_dual_memory_t *dmem = save->dmem;
- gs_ref_memory_t *mem = dmem->space_local;
+ gs_ref_memory_t *mem = save->space_local;
alloc_save_t *sprev;
print_save("forget_save", mem->space, save);
@@ -823,8 +848,8 @@ alloc_forget_save(alloc_save_t * save)
do {
sprev = mem->saved;
if (sprev->id != 0)
- dmem->save_level--;
- if (dmem->save_level != 0) {
+ mem->save_level--;
+ if (mem->save_level != 0) {
alloc_change_t *chp = mem->changes;
save_set_new(&sprev->state, true);
@@ -845,8 +870,8 @@ alloc_forget_save(alloc_save_t * save)
combine_space(mem); /* combine memory */
/* This is the outermost save, which might also */
/* need to combine global VM. */
- mem = dmem->space_global;
- if (mem != dmem->space_local && mem->saved != 0) {
+ mem = save->space_global;
+ if (mem != save->space_local && mem->saved != 0) {
forget_changes(mem);
save_set_new(mem, false);
file_forget_save(mem);
@@ -887,7 +912,7 @@ combine_space(gs_ref_memory_t * mem)
{
obj_header_t *hp = (obj_header_t *) outer->cbot;
- hp->o_large = 0;
+ hp->o_alone = 0;
hp->o_size = (char *)(cp->chead + 1)
- (char *)(hp + 1);
hp->o_type = &st_bytes;
@@ -998,11 +1023,18 @@ save_set_new(gs_ref_memory_t * mem, bool to_new)
SCAN_CHUNK_OBJECTS(cp)
DO_ALL
- if_debug3('U', "[U]set_new scan(0x%lx(%lu), %d)\n",
+ if_debug3('U', "[U]set_new scan(0x%lx(%u), %d)\n",
(ulong) pre, size, to_new);
- if (pre->o_type == &st_refs) { /* These are refs, scan them. */
+ if (pre->o_type == &st_refs) {
+ /* These are refs, scan them. */
ref_packed *prp = (ref_packed *) (pre + 1);
ref_packed *next = (ref_packed *) ((char *)prp + size);
+#ifdef ALIGNMENT_ALIASING_BUG
+ ref *rpref;
+# define RP_REF(rp) (rpref = (ref *)rp, rpref)
+#else
+# define RP_REF(rp) ((ref *)rp)
+#endif
if_debug2('U', "[U]refs 0x%lx to 0x%lx\n",
(ulong) prp, (ulong) next);
@@ -1016,7 +1048,7 @@ save_set_new(gs_ref_memory_t * mem, bool to_new)
if (r_is_packed(prp))
prp++;
else {
- ((ref *) prp)->tas.type_attrs |= l_new;
+ RP_REF(prp)->tas.type_attrs |= l_new;
prp += packed_per_ref;
if (prp >= next)
break;
@@ -1026,12 +1058,13 @@ save_set_new(gs_ref_memory_t * mem, bool to_new)
if (r_is_packed(prp))
prp++;
else {
- ((ref *) prp)->tas.type_attrs &= ~l_new;
+ RP_REF(prp)->tas.type_attrs &= ~l_new;
prp += packed_per_ref;
if (prp >= next)
break;
}
}
+#undef RP_REF
} else
scanned += sizeof(obj_header_t);
END_OBJECTS_SCAN
diff --git a/gs/src/isave.h b/gs/src/isave.h
index 95d75bb83..ec3add9cc 100644
--- a/gs/src/isave.h
+++ b/gs/src/isave.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1995, 1997, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1991, 1995, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -22,6 +22,8 @@
#ifndef isave_INCLUDED
# define isave_INCLUDED
+#include "idosave.h"
+
/*
* According to the PostScript language definition, save objects are simple,
* not composite. Consequently, we cannot use their natural representation,
@@ -54,9 +56,6 @@ ulong alloc_save_state(P2(gs_dual_memory_t *, void *));
/* Get the client pointer passed to alloc_saved_state. */
void *alloc_save_client_data(P1(const alloc_save_t *));
-/* Return the current level of save nesting. */
-int alloc_save_level(P1(const gs_dual_memory_t *));
-
/* Return (the id of) the innermost externally visible save object. */
ulong alloc_save_current_id(P1(const gs_dual_memory_t *));
alloc_save_t *alloc_save_current(P1(const gs_dual_memory_t *));
@@ -80,7 +79,9 @@ bool alloc_any_names_since_save(P1(const alloc_save_t *));
* Assume the caller obtained the argument by calling alloc_find_save;
* if this is the case, the operation cannot fail.
*/
-bool alloc_restore_state_step(P1(alloc_save_t *));
+bool alloc_restore_step_in(P2(gs_dual_memory_t *, alloc_save_t *));
+/* Backward compatibility */
+#define alloc_restore_state_step(save) alloc_restore_step_in(idmemory, save)
/*
* Forget a save -- like committing a transaction (restore is like
@@ -88,11 +89,15 @@ bool alloc_restore_state_step(P1(alloc_save_t *));
* by calling alloc_find_save. Note that forgetting a save does not
* require checking pointers for recency.
*/
-void alloc_forget_save(P1(alloc_save_t *));
+void alloc_forget_save_in(P2(gs_dual_memory_t *, alloc_save_t *));
+/* Backward compatibility */
+#define alloc_forget_save(save) alloc_forget_save_in(idmemory, save)
/* Release all memory -- like doing a restore "past the bottom". */
void alloc_restore_all(P1(gs_dual_memory_t *));
+/* ------ Internals ------ */
+
/*
* If we are in a save, we want to save the old contents if l_new is
* not set; if we are not in a save, we never want to save old contents.
@@ -101,22 +106,7 @@ void alloc_restore_all(P1(gs_dual_memory_t *));
* cannot be 0; this is the test_mask in a gs_dual_memory_t. Similarly,
* we want to set the l_new bit in newly allocated objects iff we are in
* a save; this is the new_mask in a gs_dual_memory_t.
- *
- * We have to pass the pointer to the containing object to alloc_save_change
- * for two reasons:
- *
- * - We need to know which VM the containing object is in, so we can
- * know on which chain of saved changes to put the new change.
- *
- * - We need to know whether the object is an array of refs (which
- * includes dictionaries) or a struct, so we can properly trace and
- * relocate the pointer to it from the change record during garbage
- * collection.
*/
-int alloc_save_change(P4(gs_dual_memory_t *, const ref * pcont,
- ref_packed * ptr, client_name_t cname));
-
-/* ------ Internals ------ */
/* Record that we are in a save. */
void alloc_set_in_save(P1(gs_dual_memory_t *));
diff --git a/gs/src/iscan.c b/gs/src/iscan.c
index 478b4f14f..f3d139251 100644
--- a/gs/src/iscan.c
+++ b/gs/src/iscan.c
@@ -37,6 +37,7 @@
#include "ostack.h" /* for accumulating proc bodies; */
/* must precede iscan.h */
#include "iscan.h" /* defines interface */
+#include "iscanbin.h"
#include "iscannum.h"
#include "istream.h"
#include "istruct.h" /* for RELOC_REF_VAR */
@@ -48,13 +49,6 @@
#define recognize_btokens()\
(ref_binary_object_format.value.intval != 0 && level2_enabled)
-/*
- * Procedure for binary tokens. Only called if recognize_btokens() is true;
- * returns e_unregistered if Level 2 features are not included. Returns 0
- * or scan_BOS on success, <0 on failure.
- */
-int scan_binary_token(P4(i_ctx_t *, stream *, ref *, scanner_state *));
-
#ifdef DEBUG
/* Dummy comment processing procedure for testing. */
private int
@@ -87,11 +81,14 @@ int (*scan_comment_proc) (P2(const byte *, uint)) = NULL;
/* ------ Dynamic strings ------ */
/* Begin collecting a dynamically allocated string. */
-#define dynamic_init(pda, mem)\
- ((pda)->is_dynamic = false,\
- (pda)->limit = (pda)->buf + da_buf_size,\
- (pda)->next = (pda)->base = (pda)->buf,\
- (pda)->memory = (mem))
+inline private void
+dynamic_init(da_ptr pda, gs_memory_t *mem)
+{
+ pda->is_dynamic = false;
+ pda->limit = pda->buf + da_buf_size;
+ pda->next = pda->base = pda->buf;
+ pda->memory = mem;
+}
/* Free a dynamic string. */
private void
@@ -167,7 +164,7 @@ dynamic_save(da_ptr pda)
/* Finish collecting a dynamic string. */
private int
-dynamic_make_string(ref * pref, da_ptr pda, byte * next)
+dynamic_make_string(i_ctx_t *i_ctx_p, ref * pref, da_ptr pda, byte * next)
{
uint size = (pda->next = next) - pda->base;
int code = dynamic_resize(pda, size);
@@ -183,36 +180,38 @@ dynamic_make_string(ref * pref, da_ptr pda, byte * next)
/* ------ Main scanner ------ */
/* GC procedures */
-#define ssptr ((scanner_state *)vptr)
#define ssarray ssptr->s_ss.binary.bin_array
private
CLEAR_MARKS_PROC(scanner_clear_marks)
{
+ scanner_state *const ssptr = vptr;
+
r_clear_attrs(&ssarray, l_mark);
}
private
-ENUM_PTRS_BEGIN(scanner_enum_ptrs) return 0;
-
+ENUM_PTRS_WITH(scanner_enum_ptrs, scanner_state *ssptr) return 0;
case 0:
-if (ssptr->s_scan_type == scanning_none ||
- !ssptr->s_da.is_dynamic
-)
- ENUM_RETURN(0);
-ssptr->s_da.str.data = ssptr->s_da.base;
-ssptr->s_da.str.size = da_size(&ssptr->s_da);
-ENUM_RETURN_STRING_PTR(scanner_state, s_da.str);
+ if (ssptr->s_scan_type == scanning_none ||
+ !ssptr->s_da.is_dynamic
+ )
+ ENUM_RETURN(0);
+ return ENUM_STRING2(ssptr->s_da.base, da_size(&ssptr->s_da));
case 1:
-if (ssptr->s_scan_type != scanning_binary)
- return 0;
-ENUM_RETURN_REF(&ssarray);
+ if (ssptr->s_scan_type != scanning_binary)
+ return 0;
+ ENUM_RETURN_REF(&ssarray);
ENUM_PTRS_END
-private RELOC_PTRS_BEGIN(scanner_reloc_ptrs)
+private RELOC_PTRS_WITH(scanner_reloc_ptrs, scanner_state *ssptr)
{
if (ssptr->s_scan_type != scanning_none && ssptr->s_da.is_dynamic) {
- RELOC_STRING_VAR(ssptr->s_da.str);
- ssptr->s_da.limit = ssptr->s_da.str.data + ssptr->s_da.str.size;
- ssptr->s_da.next = ssptr->s_da.str.data + (ssptr->s_da.next - ssptr->s_da.base);
- ssptr->s_da.base = ssptr->s_da.str.data;
+ gs_string sda;
+
+ sda.data = ssptr->s_da.base;
+ sda.size = da_size(&ssptr->s_da);
+ RELOC_STRING_VAR(sda);
+ ssptr->s_da.limit = sda.data + sda.size;
+ ssptr->s_da.next = sda.data + (ssptr->s_da.next - ssptr->s_da.base);
+ ssptr->s_da.base = sda.data;
}
if (ssptr->s_scan_type == scanning_binary) {
RELOC_REF_VAR(ssarray);
@@ -220,7 +219,6 @@ private RELOC_PTRS_BEGIN(scanner_reloc_ptrs)
}
}
RELOC_PTRS_END
-#undef ssptr
/* Structure type */
public_st_scanner_state();
@@ -548,7 +546,7 @@ scan_token(i_ctx_t *i_ctx_p, stream * s, ref * pref, scanner_state * pstate)
case EOFC:
;
}
- retcode = dynamic_make_string(myref, &da, da.next);
+ retcode = dynamic_make_string(i_ctx_p, myref, &da, da.next);
if (retcode < 0) { /* VMerror */
sputback(s); /* rescan ) */
scan_type = scanning_string;
@@ -603,8 +601,8 @@ scan_token(i_ctx_t *i_ctx_p, stream * s, ref * pref, scanner_state * pstate)
make_empty_array(myref, 0);
ref_stack_pop(&o_stack, size);
} else if (ref_array_packing.value.boolval) {
- retcode = make_packed_array(myref, &o_stack,
- size, "scanner(packed)");
+ retcode = make_packed_array(myref, &o_stack, size,
+ idmemory, "scanner(packed)");
if (retcode < 0) { /* must be VMerror */
osp++;
scan_putback();
@@ -622,8 +620,8 @@ scan_token(i_ctx_t *i_ctx_p, stream * s, ref * pref, scanner_state * pstate)
scan_type = scanning_none;
goto pause_ret;
}
- retcode = ref_stack_store(&o_stack, myref,
- size, 0, 1, false, "scanner");
+ retcode = ref_stack_store(&o_stack, myref, size, 0, 1,
+ false, idmemory, "scanner");
if (retcode < 0) {
ifree_ref_array(myref, "scanner(proc)");
sreturn(retcode);
@@ -791,13 +789,13 @@ scan_token(i_ctx_t *i_ctx_p, stream * s, ref * pref, scanner_state * pstate)
case '9':
case '.':
sign = 0;
- nr: /*
- * Skip a leading sign, if any, by conditionally passing
- * sptr + 1 rather than sptr. Also, if the last character
- * in the buffer is a CR, we must stop the scan 1 character
- * early, to be sure that we can test for CR+LF within the
- * buffer, by passing endptr rather than endptr + 1.
- */
+ nr: /*
+ * Skip a leading sign, if any, by conditionally passing
+ * sptr + 1 rather than sptr. Also, if the last character
+ * in the buffer is a CR, we must stop the scan 1 character
+ * early, to be sure that we can test for CR+LF within the
+ * buffer, by passing endptr rather than endptr + 1.
+ */
retcode = scan_number(sptr + (sign & 1),
endptr /*(*endptr == char_CR ? endptr : endptr + 1) */ ,
sign, myref, &newptr);
@@ -806,6 +804,7 @@ scan_token(i_ctx_t *i_ctx_p, stream * s, ref * pref, scanner_state * pstate)
if (*sptr == char_CR && sptr[1] == char_EOL)
sptr++;
retcode = 0;
+ ref_mark_new(myref);
break;
}
name_type = 0;
@@ -1009,9 +1008,10 @@ scan_token(i_ctx_t *i_ctx_p, stream * s, ref * pref, scanner_state * pstate)
scan_sign(sign, base);
retcode = scan_number(base, daptr, sign, myref, &newptr);
- if (retcode == 1)
+ if (retcode == 1) {
+ ref_mark_new(myref);
retcode = 0;
- else if (retcode != e_syntaxerror) {
+ } else if (retcode != e_syntaxerror) {
dynamic_free(&da);
if (name_type == 2)
sreturn(e_syntaxerror);
@@ -1036,7 +1036,7 @@ scan_token(i_ctx_t *i_ctx_p, stream * s, ref * pref, scanner_state * pstate)
}
} else {
retcode = name_ref(da.base, (uint) (daptr - da.base),
- myref, 1);
+ myref, !s->foreign);
}
/* Done scanning. Check for preceding /'s. */
if (retcode < 0) {
diff --git a/gs/src/iscan.h b/gs/src/iscan.h
index 98e06c14b..908eef2c2 100644
--- a/gs/src/iscan.h
+++ b/gs/src/iscan.h
@@ -46,7 +46,6 @@ typedef struct scanner_state_s scanner_state;
#define max_dsc_line max_comment_line /* backward compatibility */
#define da_buf_size (max_comment_line + 2)
typedef struct dynamic_area_s {
- gs_string str; /* for GC */
byte *base;
byte *next;
byte *limit;
diff --git a/gs/src/iscanbin.c b/gs/src/iscanbin.c
index 4140c0d8f..6448d102b 100644
--- a/gs/src/iscanbin.c
+++ b/gs/src/iscanbin.c
@@ -32,6 +32,7 @@
#include "ostack.h" /* must precede iscan.h */
#include "iname.h"
#include "iscan.h" /* for scan_Refill */
+#include "iscanbin.h"
#include "iutil.h"
#include "ivmspace.h"
#include "store.h"
@@ -132,7 +133,7 @@ typedef enum {
private int scan_bin_num_array_continue(P4(i_ctx_t *, stream *, ref *, scanner_state *));
private int scan_bin_string_continue(P4(i_ctx_t *, stream *, ref *, scanner_state *));
private int scan_bos_continue(P4(i_ctx_t *, stream *, ref *, scanner_state *));
-private byte *scan_bos_resize(P3(scanner_state *, uint, uint));
+private byte *scan_bos_resize(P4(i_ctx_t *, scanner_state *, uint, uint));
private int scan_bos_string_continue(P4(i_ctx_t *, stream *, ref *, scanner_state *));
/* Scan a binary token. Called from the main scanner */
@@ -475,7 +476,7 @@ scan_bos_continue(i_ctx_t *i_ctx_p, register stream * s, ref * pref,
byte *sbase;
if (pstate->s_da.is_dynamic)
- sbase = scan_bos_resize(pstate, str_size,
+ sbase = scan_bos_resize(i_ctx_p, pstate, str_size,
index);
else
sbase = ialloc_string(str_size,
@@ -560,7 +561,8 @@ scan_bos_continue(i_ctx_t *i_ctx_p, register stream * s, ref * pref,
/* Reallocate the strings for a binary object sequence, */
/* adjusting all the pointers to them from objects. */
private byte *
-scan_bos_resize(scanner_state * pstate, uint new_size, uint index)
+scan_bos_resize(i_ctx_t *i_ctx_p, scanner_state * pstate, uint new_size,
+ uint index)
{
scan_binary_state *const pbs = &pstate->s_ss.binary;
uint old_size = da_size(&pstate->s_da);
diff --git a/gs/src/iscanbin.h b/gs/src/iscanbin.h
new file mode 100644
index 000000000..b2e856dd7
--- /dev/null
+++ b/gs/src/iscanbin.h
@@ -0,0 +1,37 @@
+/* Copyright (C) 1999 Aladdin Enterprises. All rights reserved.
+
+ This file is part of Aladdin Ghostscript.
+
+ Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
+ or distributor accepts any responsibility for the consequences of using it,
+ or for whether it serves any particular purpose or works at all, unless he
+ or she says so in writing. Refer to the Aladdin Ghostscript Free Public
+ License (the "License") for full details.
+
+ Every copy of Aladdin Ghostscript must include a copy of the License,
+ normally in a plain ASCII text file named PUBLIC. The License grants you
+ the right to copy, modify and redistribute Aladdin Ghostscript, but only
+ under certain conditions described in the License. Among other things, the
+ License requires that the copyright notice and this notice be preserved on
+ all copies.
+ */
+
+
+/* Interface to binary token scanner */
+
+#ifndef iscanbin_INCLUDED
+# define iscanbin_INCLUDED
+
+/*
+ * Scan a binary token. The main scanner calls this iff recognize_btokens()
+ * is true. Return e_unregistered if Level 2 features are not included.
+ * Return 0 or scan_BOS on success, <0 on failure.
+ *
+ * This header file exists only because there are two implementations of
+ * this procedure: a dummy one for Level 1 systems, and the real one.
+ * The interface is entirely internal to the scanner.
+ */
+int scan_binary_token(P4(i_ctx_t *i_ctx_p, stream *s, ref *pref,
+ scanner_state *pstate));
+
+#endif /* iscanbin_INCLUDED */
diff --git a/gs/src/iscannum.c b/gs/src/iscannum.c
index da74ee5d7..8654b081d 100644
--- a/gs/src/iscannum.c
+++ b/gs/src/iscannum.c
@@ -182,12 +182,12 @@ scan_number(const byte * str, const byte * end, int sign,
return_error(e_limitcheck);
}
}
- make_int_new(pref, uval);
+ make_int(pref, uval);
return code;
}
}
iret:
- make_int_new(pref, (sign < 0 ? -ival : ival));
+ make_int(pref, (sign < 0 ? -ival : ival));
return code;
/* Accumulate a long in lval. */
@@ -234,7 +234,7 @@ i2l:
return_error(e_syntaxerror);
}
lret:
- make_int_new(pref, (sign < 0 ? -lval : lval));
+ make_int(pref, (sign < 0 ? -lval : lval));
return code;
/* Accumulate a double in dval. */
@@ -285,7 +285,7 @@ i2r:
if (!(c == 'e' || c == 'E' || exp10 < -NUM_POWERS_10)) { /* Check for trailing garbage */
if (c != EOFC)
*psp = sp, code = 1;
- make_real_new(pref, ival * neg_powers_10[-exp10]);
+ make_real(pref, ival * neg_powers_10[-exp10]);
return code;
}
dval = ival;
@@ -387,6 +387,6 @@ fe:
return_error(e_limitcheck);
}
rret:
- make_real_new(pref, dval);
+ make_real(pref, dval);
return code;
}
diff --git a/gs/src/iscannum.h b/gs/src/iscannum.h
index 03d967153..f4ce1e1c1 100644
--- a/gs/src/iscannum.h
+++ b/gs/src/iscannum.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1994, 1995 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1994, 1995, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -22,8 +22,11 @@
#ifndef iscannum_INCLUDED
# define iscannum_INCLUDED
-/* Scan a number. If the number consumes the entire string, return 0; */
-/* if not, set *psp to the first character beyond the number and return 1. */
+/*
+ * Scan a number. If the number consumes the entire string, return 0;
+ * if not, set *psp to the first character beyond the number and return 1.
+ * Note that scan_number does not mark the result ref as "new".
+ */
int scan_number(P5(const byte * sp, const byte * end, int sign, ref * pref,
const byte ** psp));
diff --git a/gs/src/isstate.h b/gs/src/isstate.h
index af2e57cee..bf3465832 100644
--- a/gs/src/isstate.h
+++ b/gs/src/isstate.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1995 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1993, 1995, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -23,10 +23,10 @@
# define isstate_INCLUDED
/* Saved state of allocator and other things as needed. */
- /*typedef struct alloc_save_s alloc_save_t; *//* in isave.h */
+/*typedef struct alloc_save_s alloc_save_t; *//* in isave.h */
struct alloc_save_s {
gs_ref_memory_t state; /* must be first for subclassing */
- gs_dual_memory_t *dmem;
+ vm_spaces spaces;
bool restore_names;
bool is_current;
ulong id;
diff --git a/gs/src/istack.c b/gs/src/istack.c
index faccff6b8..9f7caa14d 100644
--- a/gs/src/istack.c
+++ b/gs/src/istack.c
@@ -25,47 +25,32 @@
#include "errors.h"
#include "ialloc.h"
#include "istack.h"
+#include "istkparm.h"
#include "istruct.h" /* for RELOC_REF_VAR */
#include "iutil.h"
#include "ivmspace.h" /* for local/global test */
#include "store.h"
-/*
- * Define the structure for stack parameters set at initialization.
- */
-/*typedef struct ref_stack_params_s ref_stack_params_t;*/ /* in istack.h */
-struct ref_stack_params_s {
- uint bot_guard; /* # of guard elements below bot */
- uint top_guard; /* # of guard elements above top */
- uint block_size; /* size of each block */
- uint data_size; /* # of data slots in each block */
- ref guard_value; /* t__invalid or t_operator, */
- /* bottom guard value */
- int underflow_error; /* error code for underflow */
- int overflow_error; /* error code for overflow */
- bool allow_expansion; /* if false, don't expand */
-};
-gs_private_st_simple(st_ref_stack_params, ref_stack_params_t,
- "ref_stack_params_t");
-
/* Forward references */
private void init_block(P3(ref_stack_t *pstack, const ref *pblock_array,
uint used));
private int ref_stack_push_block(P3(ref_stack_t *pstack, uint keep, uint add));
-/* GC procedures */
-#define sptr ((ref_stack_t *)vptr)
+/* GC descriptors and procedures */
+private_st_ref_stack_params();
private
CLEAR_MARKS_PROC(ref_stack_clear_marks)
{
+ ref_stack_t *const sptr = vptr;
+
r_clear_attrs(&sptr->current, l_mark);
}
private
-ENUM_PTRS_BEGIN(ref_stack_enum_ptrs) return 0;
+ENUM_PTRS_WITH(ref_stack_enum_ptrs, ref_stack_t *sptr) return 0;
case 0: ENUM_RETURN_REF(&sptr->current);
case 1: return ENUM_OBJ(sptr->params);
ENUM_PTRS_END
-private RELOC_PTRS_BEGIN(ref_stack_reloc_ptrs)
+private RELOC_PTRS_WITH(ref_stack_reloc_ptrs, ref_stack_t *sptr)
{
/* Note that the relocation must be a multiple of sizeof(ref_packed) */
/* * align_packed_per_ref, but it need not be a multiple of */
@@ -92,19 +77,20 @@ public_st_ref_stack();
int
ref_stack_init(ref_stack_t *pstack, const ref *pblock_array,
uint bot_guard, uint top_guard, const ref *pguard_value,
- gs_ref_memory_t *mem)
+ gs_ref_memory_t *mem, ref_stack_params_t *params)
{
- ref_stack_params_t *params =
- gs_alloc_struct((gs_memory_t *)mem, ref_stack_params_t,
- &st_ref_stack_params,
- "ref_stack_alloc(stack.params)");
uint size = r_size(pblock_array);
uint avail = size - (stack_block_refs + bot_guard + top_guard);
ref_stack_block *pblock = (ref_stack_block *)pblock_array->value.refs;
s_ptr body = (s_ptr)(pblock + 1);
- if (params == 0)
- return_error(-1); /* avoid binding in any error codes */
+ if (params == 0) {
+ params = gs_alloc_struct((gs_memory_t *)mem, ref_stack_params_t,
+ &st_ref_stack_params,
+ "ref_stack_alloc(stack.params)");
+ if (params == 0)
+ return_error(-1); /* avoid binding in any error codes */
+ }
pstack->bot = body + bot_guard;
pstack->p = pstack->bot - 1;
@@ -133,7 +119,7 @@ ref_stack_init(ref_stack_t *pstack, const ref *pblock_array,
params->overflow_error = -1;
params->allow_expansion = true;
init_block(pstack, pblock_array, 0);
- refset_null(pstack->bot, avail);
+ refset_null_new(pstack->bot, avail, 0);
make_empty_array(&pblock->next, 0);
return 0;
}
@@ -185,7 +171,7 @@ ref_stack_set_margin(ref_stack_t *pstack, uint margin)
uint data_size = params->data_size;
if (margin <= pstack->margin) {
- refset_null(pstack->top + 1, pstack->margin - margin);
+ refset_null_new(pstack->top + 1, pstack->margin - margin, 0);
} else {
if (margin > data_size >> 1)
return_error(e_rangecheck);
@@ -306,9 +292,11 @@ ref_stack_store_check(const ref_stack_t *pstack, ref *parray, uint count,
* no check, 0 for old, 1 for new. May return e_rangecheck or
* e_invalidaccess.
*/
+#undef idmemory /****** NOTA BENE ******/
int
ref_stack_store(const ref_stack_t *pstack, ref *parray, uint count,
- uint skip, int age, bool check, client_name_t cname)
+ uint skip, int age, bool check, gs_dual_memory_t *idmemory,
+ client_name_t cname)
{
uint left, pass;
ref *to;
@@ -427,7 +415,7 @@ ref_stack_pop_block(ref_stack_t *pstack)
memmove(bot + moved, bot, count * sizeof(ref));
left = used - moved;
memcpy(bot, body + left, moved * sizeof(ref));
- refset_null(body + left, moved);
+ refset_null_new(body + left, moved, 0);
r_dec_size(&pnext->used, moved);
pstack->p = pstack->top;
pstack->extension_used -= moved;
@@ -542,9 +530,9 @@ ref_stack_push_block(ref_stack_t *pstack, uint keep, uint add)
body += params->bot_guard;
memcpy(body, pstack->bot + move, keep * sizeof(ref));
/* Clear the elements above the top of the new block. */
- refset_null(body + keep, params->data_size - keep);
+ refset_null_new(body + keep, params->data_size - keep, 0);
/* Clear the elements above the top of the old block. */
- refset_null(pstack->bot + move, keep);
+ refset_null_new(pstack->bot + move, keep, 0);
pnext->next = pstack->current;
pcur->used.value.refs = pstack->bot;
r_set_size(&pcur->used, move);
@@ -586,7 +574,7 @@ ref_stack_cleanup(ref_stack_t *pstack)
ref_stack_block *pblock =
(ref_stack_block *) pstack->current.value.refs;
- refset_null(pstack->p + 1, pstack->top - pstack->p);
+ refset_null_new(pstack->p + 1, pstack->top - pstack->p, 0);
pblock->used = pstack->current; /* set attrs */
pblock->used.value.refs = pstack->bot;
r_set_size(&pblock->used, pstack->p + 1 - pstack->bot);
@@ -646,7 +634,7 @@ init_block(ref_stack_t *pstack, const ref *psb, uint used)
ref *top = brefs + r_size(psb);
int top_guard = params->top_guard;
- refset_null(top - top_guard, top_guard);
+ refset_null_new(top - top_guard, top_guard, 0);
} {
ref_stack_block *const pblock = (ref_stack_block *) brefs;
diff --git a/gs/src/istack.h b/gs/src/istack.h
index 20900df1b..459ee3846 100644
--- a/gs/src/istack.h
+++ b/gs/src/istack.h
@@ -63,11 +63,12 @@ typedef struct ref_stack_block_s {
/*
* Initialize a stack. Note that this allocates the stack parameter
- * structure.
+ * structure iff params is not NULL.
*/
-int ref_stack_init(P6(ref_stack_t *pstack, const ref *pblock_array,
+int ref_stack_init(P7(ref_stack_t *pstack, const ref *pblock_array,
uint bot_guard, uint top_guard,
- const ref *pguard_value, gs_ref_memory_t *mem));
+ const ref *pguard_value, gs_ref_memory_t *mem,
+ ref_stack_params_t *params));
/* Set whether a stack is allowed to expand. The initial value is true. */
void ref_stack_allow_expansion(P2(ref_stack_t *pstack, bool expand));
@@ -123,8 +124,13 @@ int ref_stack_store_check(P4(const ref_stack_t *pstack, ref *parray,
* no check, 0 for old, 1 for new. May return e_rangecheck or
* e_invalidaccess.
*/
-int ref_stack_store(P7(const ref_stack_t *pstack, ref *parray, uint count,
- uint skip, int age, bool check, client_name_t cname));
+#ifndef gs_dual_memory_DEFINED
+# define gs_dual_memory_DEFINED
+typedef struct gs_dual_memory_s gs_dual_memory_t;
+#endif
+int ref_stack_store(P8(const ref_stack_t *pstack, ref *parray, uint count,
+ uint skip, int age, bool check,
+ gs_dual_memory_t *idmem, client_name_t cname));
/*
* Pop the top N elements off a stack.
diff --git a/gs/src/istkparm.h b/gs/src/istkparm.h
new file mode 100644
index 000000000..3ca9362d7
--- /dev/null
+++ b/gs/src/istkparm.h
@@ -0,0 +1,44 @@
+/* Copyright (C) 1999 Aladdin Enterprises. All rights reserved.
+
+ This file is part of Aladdin Ghostscript.
+
+ Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
+ or distributor accepts any responsibility for the consequences of using it,
+ or for whether it serves any particular purpose or works at all, unless he
+ or she says so in writing. Refer to the Aladdin Ghostscript Free Public
+ License (the "License") for full details.
+
+ Every copy of Aladdin Ghostscript must include a copy of the License,
+ normally in a plain ASCII text file named PUBLIC. The License grants you
+ the right to copy, modify and redistribute Aladdin Ghostscript, but only
+ under certain conditions described in the License. Among other things, the
+ License requires that the copyright notice and this notice be preserved on
+ all copies.
+ */
+
+
+/* Parameter structure for expandable stacks of refs */
+
+#ifndef istkparm_INCLUDED
+# define istkparm_INCLUDED
+
+/*
+ * Define the structure for stack parameters set at initialization.
+ */
+/*typedef struct ref_stack_params_s ref_stack_params_t;*/ /* in istack.h */
+struct ref_stack_params_s {
+ uint bot_guard; /* # of guard elements below bot */
+ uint top_guard; /* # of guard elements above top */
+ uint block_size; /* size of each block */
+ uint data_size; /* # of data slots in each block */
+ ref guard_value; /* t__invalid or t_operator, */
+ /* bottom guard value */
+ int underflow_error; /* error code for underflow */
+ int overflow_error; /* error code for overflow */
+ bool allow_expansion; /* if false, don't expand */
+};
+#define private_st_ref_stack_params() /* in istack.c */\
+ gs_private_st_simple(st_ref_stack_params, ref_stack_params_t,\
+ "ref_stack_params_t")
+
+#endif /* istkparm_INCLUDED */
diff --git a/gs/src/istream.h b/gs/src/istream.h
index 192c23850..e71acffa9 100644
--- a/gs/src/istream.h
+++ b/gs/src/istream.h
@@ -17,15 +17,16 @@
*/
-/* Requires scommon.h, ostack.h */
+/* Requires scommon.h */
#ifndef istream_INCLUDED
# define istream_INCLUDED
/* Procedures exported by zfproc.c */
+
/* for zfilter.c - procedure stream initialization */
-int sread_proc(P2(ref *, stream **));
-int swrite_proc(P2(ref *, stream **));
+int sread_proc(P3(ref *, stream **, gs_ref_memory_t *));
+int swrite_proc(P3(ref *, stream **, gs_ref_memory_t *));
/* for interp.c, zfileio.c, zpaint.c - handle a procedure */
/* callback or an interrupt */
diff --git a/gs/src/istruct.h b/gs/src/istruct.h
index 3904e1944..c4a6af198 100644
--- a/gs/src/istruct.h
+++ b/gs/src/istruct.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1994, 1997, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1994, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -60,8 +60,8 @@ typedef struct gc_procs_with_refs_s {
* those macros to be consistent which these, which are better, but it's
* not worth the trouble.)
*/
-#define ENUM_RETURN_REF(ptr)\
- return (*pep = (const void *)(ptr), ptr_ref_type)
+#define ENUM_RETURN_REF(rptr)\
+ return (pep->ptr = (const void *)(rptr), ptr_ref_type)
#define ENUM_RETURN_REF_MEMBER(typ, memb)\
ENUM_RETURN_REF(&((typ *)vptr)->memb)
#define RELOC_REF_PTR_VAR(ptrvar)\
diff --git a/gs/src/iutil.c b/gs/src/iutil.c
index b3eb26064..0f2d84d06 100644
--- a/gs/src/iutil.c
+++ b/gs/src/iutil.c
@@ -38,6 +38,13 @@
#include "oper.h"
#include "store.h"
+/*
+ * By design choice, none of the procedures in this file take a context
+ * pointer (i_ctx_p). Since a number of them require a gs_dual_memory_t
+ * for store checking or save bookkeeping, we need to #undef idmemory.
+ */
+#undef idmemory
+
/* ------ Object utilities ------ */
/* Define the table of ref type properties. */
@@ -48,7 +55,7 @@ const byte ref_type_properties[] = {
/* Copy refs from one place to another. */
int
refcpy_to_old(ref * aref, uint index, const ref * from,
- uint size, client_name_t cname)
+ uint size, gs_dual_memory_t *idmemory, client_name_t cname)
{
ref *to = aref->value.refs + index;
int code = refs_check_space(from, size, r_space(aref));
@@ -65,7 +72,8 @@ refcpy_to_old(ref * aref, uint index, const ref * from,
return 0;
}
void
-refcpy_to_new(ref * to, const ref * from, uint size)
+refcpy_to_new(ref * to, const ref * from, uint size,
+ gs_dual_memory_t *idmemory)
{
while (size--)
ref_assign_new(to, from), to++, from++;
@@ -73,10 +81,10 @@ refcpy_to_new(ref * to, const ref * from, uint size)
/* Fill a new object with nulls. */
void
-refset_null(ref * to, uint size)
+refset_null_new(ref * to, uint size, uint new_mask)
{
- while (size--)
- make_null_new(to), to++;
+ for (; size--; ++to)
+ make_ta(to, t_null, new_mask);
}
/* Compare two objects for equality. */
@@ -219,8 +227,11 @@ obj_string_data(const ref *op, const byte **pchars, uint *plen)
* if OK, 1 if the destination wasn't large enough, e_invalidaccess if the
* object's contents weren't readable. If the return value is 0 or 1,
* *prlen contains the amount of data returned. start_pos is the starting
- * output position -- the first start_pos bytes of output are discarded, and
- * *prlen reflects the remaining amount of output.
+ * output position -- the first start_pos bytes of output are discarded.
+ *
+ * The mem argument is only used for getting the type of structures,
+ * not for allocating; if it is NULL and full_print != 0, structures will
+ * print as --(struct)--.
*
* This rather complex API is needed so that a client can call obj_cvp
* repeatedly to print on a stream, which may require suspending at any
@@ -229,7 +240,7 @@ obj_string_data(const ref *op, const byte **pchars, uint *plen)
private void ensure_dot(P1(char *));
int
obj_cvp(const ref * op, byte * str, uint len, uint * prlen,
- int full_print, uint start_pos)
+ int full_print, uint start_pos, gs_memory_t *mem)
{
char buf[50]; /* big enough for any float, double, or struct name */
const byte *data = (const byte *)buf;
@@ -272,7 +283,7 @@ obj_cvp(const ref * op, byte * str, uint len, uint * prlen,
}
case t_operator:
case t_oparray:
- code = obj_cvp(op, (byte *)buf + 2, sizeof(buf) - 4, &size, 0, 0);
+ code = obj_cvp(op, (byte *)buf + 2, sizeof(buf) - 4, &size, 0, 0, mem);
if (code < 0)
return code;
buf[0] = buf[1] = buf[size + 2] = buf[size + 3] = '-';
@@ -286,10 +297,10 @@ obj_cvp(const ref * op, byte * str, uint len, uint * prlen,
goto nl;
}
if (start_pos > 0)
- return obj_cvp(op, str, len, prlen, 0, start_pos - 1);
+ return obj_cvp(op, str, len, prlen, 0, start_pos - 1, mem);
if (len < 1)
return_error(e_rangecheck);
- code = obj_cvp(op, str + 1, len - 1, prlen, 0, 0);
+ code = obj_cvp(op, str + 1, len - 1, prlen, 0, 0, mem);
if (code < 0)
return code;
str[0] = '/';
@@ -378,9 +389,13 @@ obj_cvp(const ref * op, byte * str, uint len, uint * prlen,
data = (const byte *)"-foreign-struct-";
goto rs;
}
+ if (!mem) {
+ data = (const byte *)"-(struct)-";
+ goto rs;
+ }
data = (const byte *)
gs_struct_type_name_string(
- gs_object_type(imemory,
+ gs_object_type(mem,
(const obj_header_t *)op->value.pstruct));
size = strlen((const char *)data);
if (size > 4 && !memcmp(data + size - 4, "type", 4))
@@ -501,7 +516,7 @@ int
obj_cvs(const ref * op, byte * str, uint len, uint * prlen,
const byte ** pchars)
{
- int code = obj_cvp(op, str, len, prlen, 0, 0);
+ int code = obj_cvp(op, str, len, prlen, 0, 0, NULL);
if (code != 1 && pchars) {
*pchars = str;
@@ -829,7 +844,8 @@ read_matrix(const ref * op, gs_matrix * pmat)
/* Write a matrix operand. */
/* Return 0 if OK, error code if not. */
int
-write_matrix(ref * op, const gs_matrix * pmat)
+write_matrix_in(ref * op, const gs_matrix * pmat, gs_dual_memory_t *idmemory,
+ gs_ref_memory_t *imem)
{
ref *aptr;
const float *pel;
@@ -841,8 +857,12 @@ write_matrix(ref * op, const gs_matrix * pmat)
aptr = op->value.refs;
pel = (const float *)pmat;
for (i = 5; i >= 0; i--, aptr++, pel++) {
- ref_save(op, aptr, "write_matrix");
- make_real_new(aptr, *pel);
+ if (idmemory) {
+ ref_save(op, aptr, "write_matrix");
+ make_real_new(aptr, *pel);
+ } else {
+ make_tav(aptr, t_real, imemory_new_mask(imem), realval, *pel);
+ }
}
return 0;
}
diff --git a/gs/src/iutil.h b/gs/src/iutil.h
index e214ca807..2a0a0c9c2 100644
--- a/gs/src/iutil.h
+++ b/gs/src/iutil.h
@@ -26,12 +26,17 @@
/* Copy refs from one place to another. */
/* (If we are copying to the stack, we can just use memcpy.) */
-void refcpy_to_new(P3(ref * to, const ref * from, uint size));
-int refcpy_to_old(P5(ref * aref, uint index, const ref * from, uint size,
- client_name_t cname));
+void refcpy_to_new(P4(ref * to, const ref * from, uint size,
+ gs_dual_memory_t *dmem));
+int refcpy_to_old(P6(ref * aref, uint index, const ref * from, uint size,
+ gs_dual_memory_t *dmem, client_name_t cname));
-/* Fill an array with nulls. */
-void refset_null(P2(ref * to, uint size));
+/*
+ * Fill an array with nulls.
+ * For backward compatibility, we define the procedure with a new name.
+ */
+void refset_null_new(P3(ref * to, uint size, uint new_mask));
+#define refset_null(to, size) refset_null_new(to, size, ialloc_new_mask)
/* Compare two objects for equality. */
bool obj_eq(P2(const ref *, const ref *));
@@ -54,10 +59,14 @@ int obj_string_data(P3(const ref *op, const byte **pchars, uint *plen));
* object's contents weren't readable. If the return value is 0 or 1,
* *prlen contains the amount of data returned. start_pos is the starting
* output position -- the first start_pos bytes of output are discarded.
+ *
+ * The mem argument is only used for getting the type of structures,
+ * not for allocating; if it is NULL and full_print != 0, structures will
+ * print as --(struct)--.
*/
#define CVP_MAX_STRING 200 /* strings are truncated here if full_print = 1 */
-int obj_cvp(P6(const ref * op, byte *str, uint len, uint * prlen,
- int full_print, uint start_pos));
+int obj_cvp(P7(const ref * op, byte *str, uint len, uint * prlen,
+ int full_print, uint start_pos, gs_memory_t *mem));
/*
* Create a printable representation of an object, a la cvs and =. Return 0
@@ -131,6 +140,13 @@ typedef struct gs_matrix_s gs_matrix;
int read_matrix(P2(const ref *, gs_matrix *));
/* Write a matrix operand. */
-int write_matrix(P2(ref *, const gs_matrix *));
+/* If dmem is NULL, the array is guaranteed newly allocated in imem. */
+/* If dmem is not NULL, imem is ignored. */
+int write_matrix_in(P4(ref *op, const gs_matrix *pmat, gs_dual_memory_t *dmem,
+ gs_ref_memory_t *imem));
+#define write_matrix_new(op, pmat, imem)\
+ write_matrix_in(op, pmat, NULL, imem)
+#define write_matrix(op, pmat)\
+ write_matrix_in(op, pmat, idmemory, NULL)
#endif /* iutil_INCLUDED */
diff --git a/gs/src/ivmem2.h b/gs/src/ivmem2.h
new file mode 100644
index 000000000..9fe8750ec
--- /dev/null
+++ b/gs/src/ivmem2.h
@@ -0,0 +1,29 @@
+/* Copyright (C) 1999 Aladdin Enterprises. All rights reserved.
+
+ This file is part of Aladdin Ghostscript.
+
+ Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
+ or distributor accepts any responsibility for the consequences of using it,
+ or for whether it serves any particular purpose or works at all, unless he
+ or she says so in writing. Refer to the Aladdin Ghostscript Free Public
+ License (the "License") for full details.
+
+ Every copy of Aladdin Ghostscript must include a copy of the License,
+ normally in a plain ASCII text file named PUBLIC. The License grants you
+ the right to copy, modify and redistribute Aladdin Ghostscript, but only
+ under certain conditions described in the License. Among other things, the
+ License requires that the copyright notice and this notice be preserved on
+ all copies.
+ */
+
+
+/* VM control user parameter procedures */
+
+#ifndef ivmem2_INCLUDED
+# define ivmem2_INCLUDED
+
+/* Exported by zvmem2.c for zusparam.c */
+int set_vm_reclaim(P2(i_ctx_t *, long));
+int set_vm_threshold(P2(i_ctx_t *, long));
+
+#endif /* ivmem2_INCLUDED */
diff --git a/gs/src/lib.mak b/gs/src/lib.mak
index 643b8663b..f832a3ae7 100644
--- a/gs/src/lib.mak
+++ b/gs/src/lib.mak
@@ -29,7 +29,8 @@ GLOBJ=$(GLOBJDIR)$(D)
GLO_=$(O_)$(GLOBJ)
GLI_=$(GLSRCDIR) $(II)$(GLGENDIR)
GLF_=
-GLCC=$(CC_) $(I_)$(GLI_)$(_I) $(GLF_)
+GLCCFLAGS=$(I_)$(GLI_)$(_I) $(GLF_)
+GLCC=$(CC_) $(GLCCFLAGS)
GLJCC=$(CC_) $(I_)$(GLI_) $(II)$(JI_)$(_I) $(JCF_) $(GLF_)
GLZCC=$(CC_) $(I_)$(GLI_) $(II)$(ZI_)$(_I) $(ZCF_) $(GLF_)
GLCCLEAF=$(CC_LEAF) $(I_)$(GLI_)$(_I) $(GLF_)
@@ -121,6 +122,7 @@ gx_h=$(GLSRC)gx.h $(stdio__h) $(gdebug_h)\
gxsync_h=$(GLSRC)gxsync.h $(gpsync_h) $(gsmemory_h)
# Out of order
gsmemlok_h=$(GLSRC)gsmemlok.h $(gsmemory_h) $(gxsync_h)
+gsnotify_h=$(GLSRC)gsnotify.h $(gsstype_h)
gsstruct_h=$(GLSRC)gsstruct.h $(gsstype_h)
GX=$(AK) $(gx_h)
@@ -158,22 +160,6 @@ $(GLOBJ)gsalloc.$(OBJ) : $(GLSRC)gsalloc.c $(GXERR) $(memory__h) $(string__h)\
$(stream_h)
$(GLCC) $(GLO_)gsalloc.$(OBJ) $(C_) $(GLSRC)gsalloc.c
-### Bitmap processing
-
-$(GLOBJ)gsbitops.$(OBJ) : $(GLSRC)gsbitops.c $(AK) $(memory__h) $(stdio__h)\
- $(gdebug_h) $(gsbittab_h) $(gserror_h) $(gserrors_h) $(gstypes_h)\
- $(gxbitops_h)
- $(GLCC) $(GLO_)gsbitops.$(OBJ) $(C_) $(GLSRC)gsbitops.c
-
-$(GLOBJ)gsbittab.$(OBJ) : $(GLSRC)gsbittab.c $(AK) $(stdpre_h) $(gsbittab_h)
- $(GLCC) $(GLO_)gsbittab.$(OBJ) $(C_) $(GLSRC)gsbittab.c
-
-# gsflip is not part of the standard configuration: it's rather large,
-# and no standard facility requires it.
-$(GLOBJ)gsflip.$(OBJ) : $(GLSRC)gsflip.c $(GXERR)\
- $(gsbitops_h) $(gsbittab_h) $(gsflip_h)
- $(GLCCLEAF) $(GLO_)gsflip.$(OBJ) $(C_) $(GLSRC)gsflip.c
-
$(GLOBJ)gsmalloc.$(OBJ) : $(GLSRC)gsmalloc.c $(malloc__h)\
$(gdebug_h)\
$(gserror_h) $(gserrors_h)\
@@ -194,6 +180,22 @@ $(GLOBJ)gsnogc.$(OBJ) : $(GLSRC)gsnogc.c $(GX)\
$(gsmdebug_h) $(gsnogc_h) $(gsstruct_h) $(gxalloc_h)
$(GLCC) $(GLO_)gsnogc.$(OBJ) $(C_) $(GLSRC)gsnogc.c
+### Bitmap processing
+
+$(GLOBJ)gsbitops.$(OBJ) : $(GLSRC)gsbitops.c $(AK) $(memory__h) $(stdio__h)\
+ $(gdebug_h) $(gsbittab_h) $(gserror_h) $(gserrors_h) $(gstypes_h)\
+ $(gxbitops_h)
+ $(GLCC) $(GLO_)gsbitops.$(OBJ) $(C_) $(GLSRC)gsbitops.c
+
+$(GLOBJ)gsbittab.$(OBJ) : $(GLSRC)gsbittab.c $(AK) $(stdpre_h) $(gsbittab_h)
+ $(GLCC) $(GLO_)gsbittab.$(OBJ) $(C_) $(GLSRC)gsbittab.c
+
+# gsflip is not part of the standard configuration: it's rather large,
+# and no standard facility requires it.
+$(GLOBJ)gsflip.$(OBJ) : $(GLSRC)gsflip.c $(GXERR)\
+ $(gsbitops_h) $(gsbittab_h) $(gsflip_h)
+ $(GLCCLEAF) $(GLO_)gsflip.$(OBJ) $(C_) $(GLSRC)gsflip.c
+
### Multi-threading
# These are required in the standard configuration, because gsmalloc.c
@@ -222,9 +224,13 @@ $(GLOBJ)gsfemu.$(OBJ) : $(GLSRC)gsfemu.c $(AK) $(std_h)
$(GLOBJ)gsmisc.$(OBJ) : $(GLSRC)gsmisc.c $(GXERR) $(gconfigv_h)\
$(ctype__h) $(malloc__h) $(math__h) $(memory__h) $(string__h)\
- $(gpcheck_h) $(gxfarith_h) $(gxfixed_h)
+ $(gpcheck_h) $(gserror_h) $(gxfarith_h) $(gxfixed_h)
$(GLCC) $(GLO_)gsmisc.$(OBJ) $(C_) $(GLSRC)gsmisc.c
+$(GLOBJ)gsnotify.$(OBJ) : $(GLSRC)gsnotify.c $(GXERR)\
+ $(gsnotify_h) $(gsstruct_h)
+ $(GLCC) $(GLO_)gsnotify.$(OBJ) $(C_) $(GLSRC)gsnotify.c
+
$(GLOBJ)gsutil.$(OBJ) : $(GLSRC)gsutil.c $(AK) $(memory__h) $(string__h)\
$(gconfigv_h)\
$(gsmemory_h) $(gsrect_h) $(gstypes_h) $(gsuid_h) $(gsutil_h)
@@ -246,6 +252,7 @@ gscpm_h=$(GLSRC)gscpm.h
gscsepnm_h=$(GLSRC)gscsepnm.h
gsdevice_h=$(GLSRC)gsdevice.h
gsfcmap_h=$(GLSRC)gsfcmap.h $(gsccode_h)
+gsfname_h=$(GLSRC)gsfname.h
gsfont_h=$(GLSRC)gsfont.h
gshsb_h=$(GLSRC)gshsb.h
gsht_h=$(GLSRC)gsht.h
@@ -263,7 +270,7 @@ gspcolor_h=$(GLSRC)gspcolor.h $(gsccolor_h) $(gsrefct_h) $(gsuid_h)
gspenum_h=$(GLSRC)gspenum.h
gsptype1_h=$(GLSRC)gsptype1.h $(gspcolor_h) $(gxbitmap_h)
gsropt_h=$(GLSRC)gsropt.h
-gstext_h=$(GLSRC)gstext.h $(gsccode_h) $(gsrefct_h)
+gstext_h=$(GLSRC)gstext.h $(gsccode_h) $(gscpm_h)
gsxfont_h=$(GLSRC)gsxfont.h
# Out of order
gschar_h=$(GLSRC)gschar.h $(gsccode_h) $(gscpm_h)
@@ -304,13 +311,13 @@ gxline_h=$(GLSRC)gxline.h $(gslparam_h) $(gsmatrix_h)
gxlum_h=$(GLSRC)gxlum.h
gxmatrix_h=$(GLSRC)gxmatrix.h $(gsmatrix_h)
gxmclip_h=$(GLSRC)gxmclip.h $(gxclip_h)
-gxp1fill_h=$(GLSRC)gxp1fill.h
+gxp1impl_h=$(GLSRC)gxp1impl.h
gxpaint_h=$(GLSRC)gxpaint.h
gxpath_h=$(GLSRC)gxpath.h $(gscpm_h) $(gslparam_h) $(gspenum_h) $(gsrect_h)
gxpcache_h=$(GLSRC)gxpcache.h
gxsample_h=$(GLSRC)gxsample.h
gxstate_h=$(GLSRC)gxstate.h
-gxtext_h=$(GLSRC)gxtext.h $(gstext_h)
+gxtext_h=$(GLSRC)gxtext.h $(gsrefct_h) $(gstext_h)
gxtmap_h=$(GLSRC)gxtmap.h
gxxfont_h=$(GLSRC)gxxfont.h $(gsccode_h) $(gsmatrix_h) $(gsuid_h) $(gsxfont_h)
# The following are out of order because they include other files.
@@ -327,7 +334,7 @@ gxdevcli_h=$(GLSRC)gxdevcli.h $(std_h)\
$(gxbitmap_h) $(gxcindex_h) $(gxcvalue_h) $(gxfixed_h)\
$(gxtext_h)
gxdevice_h=$(GLSRC)gxdevice.h $(stdio__h)\
- $(gsmalloc_h) $(gsparam_h) $(gxdevcli_h)
+ $(gsfname_h) $(gsmalloc_h) $(gsparam_h) $(gxdevcli_h)
gxdht_h=$(GLSRC)gxdht.h $(gscsepnm_h) $(gsrefct_h) $(gxarith_h) $(gxhttype_h)
gxdither_h=$(GLSRC)gxdither.h $(gxfrac_h)
gxclip2_h=$(GLSRC)gxclip2.h $(gxmclip_h)
@@ -336,7 +343,7 @@ gxctable_h=$(GLSRC)gxctable.h $(gxfixed_h) $(gxfrac_h)
gxfcache_h=$(GLSRC)gxfcache.h $(gsuid_h) $(gsxfont_h)\
$(gxbcache_h) $(gxftype_h)
gxfont_h=$(GLSRC)gxfont.h\
- $(gsccode_h) $(gsfont_h) $(gsuid_h) $(gsstype_h) $(gxftype_h)
+ $(gsccode_h) $(gsfont_h) $(gsnotify_h) $(gsstype_h) $(gsuid_h) $(gxftype_h)
gxiparam_h=$(GLSRC)gxiparam.h $(gxdevcli_h)
gscie_h=$(GLSRC)gscie.h $(gconfigv_h) $(gsrefct_h) $(gsstype_h) $(gxctable_h)
gscrd_h=$(GLSRC)gscrd.h $(gscie_h)
@@ -355,11 +362,12 @@ gxclist_h=$(GLSRC)gxclist.h $(gscspace_h)\
gxcspace_h=$(GLSRC)gxcspace.h\
$(gscspace_h) $(gsccolor_h) $(gscsel_h) $(gxfrac_h)
gxht_h=$(GLSRC)gxht.h $(gsht1_h) $(gscsepnm_h) $(gsrefct_h) $(gxhttype_h) $(gxtmap_h)
+gxcie_h=$(GLSRC)gxcie.h $(gscie_h)
gxpcolor_h=$(GLSRC)gxpcolor.h\
$(gspcolor_h) $(gxcspace_h) $(gxdevice_h) $(gxdevmem_h) $(gxpcache_h)
gscolor_h=$(GLSRC)gscolor.h $(gxtmap_h)
gsstate_h=$(GLSRC)gsstate.h\
- $(gscolor_h) $(gscsel_h) $(gsdevice_h) $(gsht_h) $(gsline_h)
+ $(gscolor_h) $(gscpm_h) $(gscsel_h) $(gsdevice_h) $(gsht_h) $(gsline_h)
gzacpath_h=$(GLSRC)gzacpath.h
gzcpath_h=$(GLSRC)gzcpath.h $(gxcpath_h)
@@ -388,6 +396,8 @@ sjpeg_h=$(GLSRC)sjpeg.h
slzwx_h=$(GLSRC)slzwx.h
spdiffx_h=$(GLSRC)spdiffx.h
spngpx_h=$(GLSRC)spngpx.h
+spprint_h=$(GLSRC)spprint.h
+spsdf_h=$(GLSRC)spsdf.h $(gsparam_h)
srlx_h=$(GLSRC)srlx.h
sstring_h=$(GLSRC)sstring.h
strimpl_h=$(GLSRC)strimpl.h $(scommon_h) $(gstypes_h) $(gsstruct_h)
@@ -416,7 +426,7 @@ $(GLOBJ)gconfig.$(OBJ) : $(GLSRC)gconf.c $(GX)\
$(GLCC) $(GLO_)gconfig.$(OBJ) $(C_) $(GLGEN)gconfig.c
$(GLOBJ)gscdefs.$(OBJ) : $(GLSRC)gscdef.c\
- $(stdpre_h) $(gscdefs_h) $(gconf_h) $(TOP_MAKEFILES)
+ $(std_h) $(gscdefs_h) $(gconf_h) $(TOP_MAKEFILES)
$(RM_) $(GLGEN)gscdefs.c
$(RM_) $(GLGEN)gconfig.h
$(CP_) $(gconfig_h) $(GLGEN)gconfig.h
@@ -446,6 +456,12 @@ $(GLOBJ)gxccman.$(OBJ) : $(GLSRC)gxccman.c $(GXERR) $(memory__h) $(gpcheck_h)\
$(gxpath_h) $(gxxfont_h) $(gzstate_h)
$(GLCC) $(GLO_)gxccman.$(OBJ) $(C_) $(GLSRC)gxccman.c
+$(GLOBJ)gxchar.$(OBJ) : $(GLSRC)gxchar.c $(GXERR) $(memory__h) $(string__h)\
+ $(gspath_h) $(gsstruct_h)\
+ $(gxfixed_h) $(gxarith_h) $(gxmatrix_h) $(gxcoord_h) $(gxdevice_h) $(gxdevmem_h)\
+ $(gxfont_h) $(gxfont0_h) $(gxchar_h) $(gxfcache_h) $(gzpath_h) $(gzstate_h)
+ $(GLCC) $(GLO_)gxchar.$(OBJ) $(C_) $(GLSRC)gxchar.c
+
$(GLOBJ)gxcht.$(OBJ) : $(GLSRC)gxcht.c $(GXERR) $(memory__h)\
$(gsutil_h)\
$(gxarith_h) $(gxcmap_h) $(gxdcolor_h) $(gxdevice_h) $(gxfixed_h)\
@@ -549,7 +565,7 @@ $(GLOBJ)gxpath.$(OBJ) : $(GLSRC)gxpath.c $(GXERR)\
$(GLCC) $(GLO_)gxpath.$(OBJ) $(C_) $(GLSRC)gxpath.c
$(GLOBJ)gxpath2.$(OBJ) : $(GLSRC)gxpath2.c $(GXERR) $(math__h)\
- $(gsstruct_h) $(gxfixed_h) $(gxarith_h) $(gzpath_h)
+ $(gspath_h) $(gsstruct_h) $(gxfixed_h) $(gxarith_h) $(gzpath_h)
$(GLCC) $(GLO_)gxpath2.$(OBJ) $(C_) $(GLSRC)gxpath2.c
$(GLOBJ)gxpcopy.$(OBJ) : $(GLSRC)gxpcopy.c $(GXERR) $(math__h) $(gconfigv_h)\
@@ -582,10 +598,9 @@ $(GLOBJ)gsalpha.$(OBJ) : $(GLSRC)gsalpha.c $(GX)\
$(gsalpha_h) $(gxdcolor_h) $(gzstate_h)
$(GLCC) $(GLO_)gsalpha.$(OBJ) $(C_) $(GLSRC)gsalpha.c
-$(GLOBJ)gschar.$(OBJ) : $(GLSRC)gschar.c $(GXERR) $(memory__h) $(string__h)\
- $(gspath_h) $(gsstruct_h)\
- $(gxfixed_h) $(gxarith_h) $(gxmatrix_h) $(gxcoord_h) $(gxdevice_h) $(gxdevmem_h)\
- $(gxfont_h) $(gxfont0_h) $(gxchar_h) $(gxfcache_h) $(gzpath_h) $(gzstate_h)
+$(GLOBJ)gschar.$(OBJ) : $(GLSRC)gschar.c $(GXERR)\
+ $(gscoord_h) $(gsmatrix_h) $(gsstruct_h)\
+ $(gxdevice_h) $(gxdevmem_h) $(gxchar_h) $(gxfont_h) $(gzstate_h)
$(GLCC) $(GLO_)gschar.$(OBJ) $(C_) $(GLSRC)gschar.c
$(GLOBJ)gscolor.$(OBJ) : $(GLSRC)gscolor.c $(GXERR)\
@@ -603,7 +618,8 @@ $(GLOBJ)gscparam.$(OBJ) : $(GLSRC)gscparam.c $(GXERR) $(memory__h) $(string__h)\
$(GLCC) $(GLO_)gscparam.$(OBJ) $(C_) $(GLSRC)gscparam.c
$(GLOBJ)gscspace.$(OBJ) : $(GLSRC)gscspace.c $(GXERR) $(memory__h)\
- $(gsccolor_h) $(gsstruct_h) $(gsutil_h) $(gxcspace_h) $(gxistate_h)
+ $(gsccolor_h) $(gsstruct_h) $(gsutil_h)\
+ $(gxcmap_h) $(gxcspace_h) $(gxistate_h)
$(GLCC) $(GLO_)gscspace.$(OBJ) $(C_) $(GLSRC)gscspace.c
$(GLOBJ)gscssub.$(OBJ) : $(GLSRC)gscssub.c $(GXERR)\
@@ -612,21 +628,29 @@ $(GLOBJ)gscssub.$(OBJ) : $(GLSRC)gscssub.c $(GXERR)\
$(GLOBJ)gsdevice.$(OBJ) : $(GLSRC)gsdevice.c $(GXERR)\
$(ctype__h) $(memory__h) $(string__h) $(gp_h)\
- $(gscdefs_h) $(gscoord_h) $(gsmatrix_h) $(gspaint_h) $(gspath_h) $(gsstruct_h)\
- $(gxcmap_h) $(gxdevice_h) $(gxdevmem_h) $(gzstate_h)
+ $(gscdefs_h) $(gscoord_h) $(gsfname_h) $(gsmatrix_h)\
+ $(gspaint_h) $(gspath_h) $(gsstruct_h)\
+ $(gxcmap_h) $(gxdevice_h) $(gxdevmem_h) $(gxiodev_h) $(gzstate_h)
$(GLCC) $(GLO_)gsdevice.$(OBJ) $(C_) $(GLSRC)gsdevice.c
$(GLOBJ)gsdevmem.$(OBJ) : $(GLSRC)gsdevmem.c $(GXERR) $(math__h) $(memory__h)\
- $(gxarith_h) $(gxdevice_h) $(gxdevmem_h)
+ $(gsdevice_h) $(gxarith_h) $(gxdevice_h) $(gxdevmem_h)
$(GLCC) $(GLO_)gsdevmem.$(OBJ) $(C_) $(GLSRC)gsdevmem.c
-$(GLOBJ)gsdparam.$(OBJ) : $(GLSRC)gsdparam.c $(GXERR) $(memory__h) $(string__h)\
- $(gsparam_h) $(gxdevice_h) $(gxfixed_h)
+$(GLOBJ)gsdparam.$(OBJ) : $(GLSRC)gsdparam.c $(GXERR)\
+ $(memory__h) $(string__h)\
+ $(gsdevice_h) $(gsparam_h) $(gxdevice_h) $(gxfixed_h)
$(GLCC) $(GLO_)gsdparam.$(OBJ) $(C_) $(GLSRC)gsdparam.c
+$(GLOBJ)gsfname.$(OBJ) : $(GLSRC)gsfname.c $(memory__h)\
+ $(gserror_h) $(gserrors_h) $(gsfname_h) $(gsmemory_h) $(gstypes_h)\
+ $(gxiodev_h)
+ $(GLCC) $(GLO_)gsfname.$(OBJ) $(C_) $(GLSRC)gsfname.c
+
$(GLOBJ)gsfont.$(OBJ) : $(GLSRC)gsfont.c $(GXERR) $(memory__h)\
- $(gschar_h) $(gsstruct_h)\
+ $(gsstruct_h) $(gsutil_h)\
$(gxdevice_h) $(gxfixed_h) $(gxmatrix_h) $(gxfont_h) $(gxfcache_h)\
+ $(gxpath_h)\
$(gzstate_h)
$(GLCC) $(GLO_)gsfont.$(OBJ) $(C_) $(GLSRC)gsfont.c
@@ -644,7 +668,7 @@ $(GLOBJ)gsimage.$(OBJ) : $(GLSRC)gsimage.c $(GXERR) $(memory__h)\
$(GLCC) $(GLO_)gsimage.$(OBJ) $(C_) $(GLSRC)gsimage.c
$(GLOBJ)gsimpath.$(OBJ) : $(GLSRC)gsimpath.c $(GXERR)\
- $(gsmatrix_h) $(gsstate_h) $(gspath_h)
+ $(gsmatrix_h) $(gspaint_h) $(gspath_h) $(gsstate_h)
$(GLCC) $(GLO_)gsimpath.$(OBJ) $(C_) $(GLSRC)gsimpath.c
$(GLOBJ)gsinit.$(OBJ) : $(GLSRC)gsinit.c $(memory__h) $(stdio__h)\
@@ -694,7 +718,8 @@ $(GLOBJ)gsparams.$(OBJ) : $(GLSRC)gsparams.c $(GXERR) $(memory__h)\
$(GLCC) $(GLO_)gsparams.$(OBJ) $(C_) $(GLSRC)gsparams.c
$(GLOBJ)gspath.$(OBJ) : $(GLSRC)gspath.c $(GXERR)\
- $(gscoord_h) $(gxdevice_h) $(gxdevmem_h) $(gxfixed_h) $(gxmatrix_h)\
+ $(gscoord_h) $(gspath_h)\
+ $(gxdevice_h) $(gxdevmem_h) $(gxfixed_h) $(gxmatrix_h)\
$(gzcpath_h) $(gzpath_h) $(gzstate_h)
$(GLCC) $(GLO_)gspath.$(OBJ) $(C_) $(GLSRC)gspath.c
@@ -705,9 +730,9 @@ $(GLOBJ)gsstate.$(OBJ) : $(GLSRC)gsstate.c $(GXERR) $(memory__h)\
$(gzstate_h) $(gzht_h) $(gzline_h) $(gzpath_h) $(gzcpath_h)
$(GLCC) $(GLO_)gsstate.$(OBJ) $(C_) $(GLSRC)gsstate.c
-$(GLOBJ)gstext.$(OBJ) : $(GLSRC)gstext.c $(std_h) $(gdebug_h)\
+$(GLOBJ)gstext.$(OBJ) : $(GLSRC)gstext.c $(memory__h) $(gdebug_h)\
$(gserror_h) $(gserrors_h) $(gsmemory_h) $(gsstruct_h) $(gstypes_h)\
- $(gxdevcli_h) $(gxpath_h) $(gxtext_h) $(gzstate_h)
+ $(gxdevcli_h) $(gxfont_h) $(gxpath_h) $(gxtext_h) $(gzstate_h)
$(GLCC) $(GLO_)gstext.$(OBJ) $(C_) $(GLSRC)gstext.c
###### Internal devices
@@ -837,40 +862,46 @@ $(GLOBJ)gdevemap.$(OBJ) : $(GLSRC)gdevemap.c $(AK) $(std_h)
###### Create a pseudo-"feature" for the entire graphics library.
+LIB0s=$(GLOBJ)stream.$(OBJ)
LIB1s=$(GLOBJ)gsalloc.$(OBJ) $(GLOBJ)gsalpha.$(OBJ)
LIB2s=$(GLOBJ)gsbitops.$(OBJ) $(GLOBJ)gsbittab.$(OBJ)
+# Note: gschar.c is no longer required for a standard build;
+# we include it only for backward compatibility for library clients.
LIB3s=$(GLOBJ)gschar.$(OBJ) $(GLOBJ)gscolor.$(OBJ) $(GLOBJ)gscoord.$(OBJ)
LIB4s=$(GLOBJ)gscparam.$(OBJ) $(GLOBJ)gscspace.$(OBJ) $(GLOBJ)gscssub.$(OBJ)
LIB5s=$(GLOBJ)gsdevice.$(OBJ) $(GLOBJ)gsdevmem.$(OBJ) $(GLOBJ)gsdparam.$(OBJ)
-LIB6s=$(GLOBJ)gsfont.$(OBJ) $(GLOBJ)gsht.$(OBJ) $(GLOBJ)gshtscr.$(OBJ)
+LIB6s=$(GLOBJ)gsfname.$(OBJ) $(GLOBJ)gsfont.$(OBJ) $(GLOBJ)gsht.$(OBJ) $(GLOBJ)gshtscr.$(OBJ)
LIB7s=$(GLOBJ)gsimage.$(OBJ) $(GLOBJ)gsimpath.$(OBJ) $(GLOBJ)gsinit.$(OBJ)
LIB8s=$(GLOBJ)gsiodev.$(OBJ) $(GLOBJ)gsistate.$(OBJ) $(GLOBJ)gsline.$(OBJ)
LIB9s=$(GLOBJ)gsmalloc.$(OBJ) $(GLOBJ)gsmatrix.$(OBJ) $(GLOBJ)gsmemlok.$(OBJ)
-LIB10s=$(GLOBJ)gsmemory.$(OBJ) $(GLOBJ)gsmemret.$(OBJ) $(GLOBJ)gsmisc.$(OBJ)
+LIB10s=$(GLOBJ)gsmemory.$(OBJ) $(GLOBJ)gsmemret.$(OBJ) $(GLOBJ)gsmisc.$(OBJ) $(GLOBJ)gsnotify.$(OBJ)
LIB11s=$(GLOBJ)gspaint.$(OBJ) $(GLOBJ)gsparam.$(OBJ) $(GLOBJ)gspath.$(OBJ)
LIB12s=$(GLOBJ)gsstate.$(OBJ) $(GLOBJ)gstext.$(OBJ) $(GLOBJ)gsutil.$(OBJ)
-LIB1x=$(GLOBJ)gxacpath.$(OBJ) $(GLOBJ)gxbcache.$(OBJ) $(GLOBJ)gxccache.$(OBJ) $(GLOBJ)gxccman.$(OBJ)
-LIB2x=$(GLOBJ)gxcht.$(OBJ) $(GLOBJ)gxclip.$(OBJ) $(GLOBJ)gxcmap.$(OBJ) $(GLOBJ)gxcpath.$(OBJ)
-LIB3x=$(GLOBJ)gxdcconv.$(OBJ) $(GLOBJ)gxdcolor.$(OBJ) $(GLOBJ)gxdither.$(OBJ) $(GLOBJ)gxfill.$(OBJ)
-LIB4x=$(GLOBJ)gxht.$(OBJ) $(GLOBJ)gxhtbit.$(OBJ) $(GLOBJ)gxidata.$(OBJ) $(GLOBJ)gxifast.$(OBJ)
-LIB5x=$(GLOBJ)gximage.$(OBJ) $(GLOBJ)gximage1.$(OBJ) $(GLOBJ)gximono.$(OBJ)
-LIB6x=$(GLOBJ)gxipixel.$(OBJ) $(GLOBJ)gxpaint.$(OBJ) $(GLOBJ)gxpath.$(OBJ) $(GLOBJ)gxpath2.$(OBJ)
-LIB7x=$(GLOBJ)gxpcopy.$(OBJ) $(GLOBJ)gxpdash.$(OBJ) $(GLOBJ)gxpflat.$(OBJ)
-LIB8x=$(GLOBJ)gxsample.$(OBJ) $(GLOBJ)gxstroke.$(OBJ) $(GLOBJ)gxsync.$(OBJ)
+LIB1x=$(GLOBJ)gxacpath.$(OBJ) $(GLOBJ)gxbcache.$(OBJ) $(GLOBJ)gxccache.$(OBJ)
+LIB2x=$(GLOBJ)gxccman.$(OBJ) $(GLOBJ)gxchar.$(OBJ) $(GLOBJ)gxcht.$(OBJ)
+LIB3x=$(GLOBJ)gxclip.$(OBJ) $(GLOBJ)gxcmap.$(OBJ) $(GLOBJ)gxcpath.$(OBJ)
+LIB4x=$(GLOBJ)gxdcconv.$(OBJ) $(GLOBJ)gxdcolor.$(OBJ) $(GLOBJ)gxdither.$(OBJ)
+LIB5x=$(GLOBJ)gxfill.$(OBJ) $(GLOBJ)gxht.$(OBJ) $(GLOBJ)gxhtbit.$(OBJ)
+LIB6x=$(GLOBJ)gxidata.$(OBJ) $(GLOBJ)gxifast.$(OBJ) $(GLOBJ)gximage.$(OBJ)
+LIB7x=$(GLOBJ)gximage1.$(OBJ) $(GLOBJ)gximono.$(OBJ) $(GLOBJ)gxipixel.$(OBJ)
+LIB8x=$(GLOBJ)gxpaint.$(OBJ) $(GLOBJ)gxpath.$(OBJ) $(GLOBJ)gxpath2.$(OBJ)
+LIB9x=$(GLOBJ)gxpcopy.$(OBJ) $(GLOBJ)gxpdash.$(OBJ) $(GLOBJ)gxpflat.$(OBJ)
+LIB10x=$(GLOBJ)gxsample.$(OBJ) $(GLOBJ)gxstroke.$(OBJ) $(GLOBJ)gxsync.$(OBJ)
LIB1d=$(GLOBJ)gdevabuf.$(OBJ) $(GLOBJ)gdevdbit.$(OBJ) $(GLOBJ)gdevddrw.$(OBJ) $(GLOBJ)gdevdflt.$(OBJ)
LIB2d=$(GLOBJ)gdevdgbr.$(OBJ) $(GLOBJ)gdevnfwd.$(OBJ) $(GLOBJ)gdevmem.$(OBJ) $(GLOBJ)gdevplnx.$(OBJ)
LIB3d=$(GLOBJ)gdevm1.$(OBJ) $(GLOBJ)gdevm2.$(OBJ) $(GLOBJ)gdevm4.$(OBJ) $(GLOBJ)gdevm8.$(OBJ)
LIB4d=$(GLOBJ)gdevm16.$(OBJ) $(GLOBJ)gdevm24.$(OBJ) $(GLOBJ)gdevm32.$(OBJ) $(GLOBJ)gdevmpla.$(OBJ)
-LIBs=$(LIB1s) $(LIB2s) $(LIB3s) $(LIB4s) $(LIB5s) $(LIB6s) $(LIB7s) $(LIB8s)\
- $(LIB9s) $(LIB10s) $(LIB11s) $(LIB12s)
-LIBx=$(LIB1x) $(LIB2x) $(LIB3x) $(LIB4x) $(LIB5x) $(LIB6x) $(LIB7x) $(LIB8x)
+LIBs=$(LIB0s) $(LIB1s) $(LIB2s) $(LIB3s) $(LIB4s) $(LIB5s) $(LIB6s) $(LIB7s)\
+ $(LIB8s) $(LIB9s) $(LIB10s) $(LIB11s) $(LIB12s)
+LIBx=$(LIB1x) $(LIB2x) $(LIB3x) $(LIB4x) $(LIB5x) $(LIB6x) $(LIB7x) $(LIB8x) $(LIB9x) $(LIB10x)
LIBd=$(LIB1d) $(LIB2d) $(LIB3d) $(LIB4d)
LIB_ALL=$(LIBs) $(LIBx) $(LIBd)
# We include some optional library modules in the dependency list,
# but not in the link, to catch compilation problems.
LIB_O=$(GLOBJ)gdevmpla.$(OBJ) $(GLOBJ)gdevmrun.$(OBJ) $(GLOBJ)gshtx.$(OBJ) $(GLOBJ)gsnogc.$(OBJ)
$(GLD)libs.dev : $(LIB_MAK) $(ECHOGS_XE) $(LIBs) $(LIB_O)
- $(SETMOD) $(GLD)libs $(LIB1s)
+ $(SETMOD) $(GLD)libs $(LIB0s)
+ $(ADDMOD) $(GLD)libs $(LIB1s)
$(ADDMOD) $(GLD)libs $(LIB2s)
$(ADDMOD) $(GLD)libs $(LIB3s)
$(ADDMOD) $(GLD)libs $(LIB4s)
@@ -893,6 +924,8 @@ $(GLD)libx.dev : $(LIB_MAK) $(ECHOGS_XE) $(LIBx)
$(ADDMOD) $(GLD)libx $(LIB6x)
$(ADDMOD) $(GLD)libx $(LIB7x)
$(ADDMOD) $(GLD)libx $(LIB8x)
+ $(ADDMOD) $(GLD)libx $(LIB9x)
+ $(ADDMOD) $(GLD)libx $(LIB10x)
$(ADDMOD) $(GLD)libx -imageclass 1_simple 3_mono
$(ADDMOD) $(GLD)libx -imagetype 1 mask1
@@ -1154,7 +1187,7 @@ $(GLOBJ)scantab.$(OBJ) : $(GLSRC)scantab.c $(AK) $(stdpre_h)\
$(GLCC) $(GLO_)scantab.$(OBJ) $(C_) $(GLSRC)scantab.c
$(GLOBJ)sfilter2.$(OBJ) : $(GLSRC)sfilter2.c $(AK) $(memory__h) $(stdio__h)\
- $(sa85x_h) $(scanchar_h) $(sbtx_h) $(strimpl_h)
+ $(gdebug_h) $(sa85x_h) $(scanchar_h) $(sbtx_h) $(strimpl_h)
$(GLCC) $(GLO_)sfilter2.$(OBJ) $(C_) $(GLSRC)sfilter2.c
$(GLOBJ)sstring.$(OBJ) : $(GLSRC)sstring.c $(AK)\
@@ -1162,6 +1195,17 @@ $(GLOBJ)sstring.$(OBJ) : $(GLSRC)sstring.c $(AK)\
$(scanchar_h) $(sstring_h) $(strimpl_h)
$(GLCC) $(GLO_)sstring.$(OBJ) $(C_) $(GLSRC)sstring.c
+$(GLOBJ)spprint.$(OBJ) : $(GLSRC)spprint.c\
+ $(math__h) $(stdio__h) $(string__h)\
+ $(spprint_h) $(stream_h)
+ $(GLCC) $(GLO_)spprint.$(OBJ) $(C_) $(GLSRC)spprint.c
+
+$(GLOBJ)spsdf.$(OBJ) : $(GLSRC)spsdf.c $(stdio__h) $(string__h)\
+ $(gserror_h) $(gserrors_h) $(gsmemory_h) $(gstypes_h)\
+ $(sa85x_h) $(scanchar_h) $(spprint_h) $(spsdf_h)\
+ $(sstring_h) $(stream_h) $(strimpl_h)
+ $(GLCC) $(GLO_)spsdf.$(OBJ) $(C_) $(GLSRC)spsdf.c
+
# ---------------- zlib filters ---------------- #
# These are used by clists and are also available as filters.
@@ -1205,7 +1249,7 @@ $(GLD)page.dev : $(LIB_MAK) $(ECHOGS_XE) $(page_) $(GLD)clist.dev
$(ADDMOD) $(GLD)page -include $(GLD)clist
$(GLOBJ)gdevprn.$(OBJ) : $(GLSRC)gdevprn.c $(ctype__h)\
- $(gdevprn_h) $(gp_h) $(gsdevice_h) $(gsparam_h)\
+ $(gdevprn_h) $(gp_h) $(gsdevice_h) $(gsfname_h) $(gsparam_h)\
$(gxclio_h) $(gxgetbit_h) $(gdevplnx_h)
$(GLCC) $(GLO_)gdevprn.$(OBJ) $(C_) $(GLSRC)gdevprn.c
@@ -1398,7 +1442,7 @@ $(GLOBJ)siinterp.$(OBJ) : $(GLSRC)siinterp.c $(AK)\
$(GLOBJ)siscale.$(OBJ) : $(GLSRC)siscale.c $(AK)\
$(math__h) $(memory__h) $(stdio__h)\
- $(gconfigv_h)\
+ $(gconfigv_h) $(gdebug_h)\
$(siscale_h) $(strimpl_h)
$(GLCC) $(GLO_)siscale.$(OBJ) $(C_) $(GLSRC)siscale.c
@@ -1427,7 +1471,8 @@ $(GLD)noroplib.dev : $(LIB_MAK) $(ECHOGS_XE) $(noroplib_)
$(SETMOD) $(GLD)noroplib $(noroplib_)
$(GLOBJ)gsnorop.$(OBJ) : $(GLSRC)gsnorop.c $(GXERR)\
- $(gdevmrop_h) $(gsrop_h) $(gxdevcli_h)
+ $(gdevmem_h) $(gdevmrop_h) $(gsrop_h)\
+ $(gxdevcli_h) $(gxdevice_h) $(gxdevmem_h)
$(GLCC) $(GLO_)gsnorop.$(OBJ) $(C_) $(GLSRC)gsnorop.c
roplib1_=$(GLOBJ)gdevdrop.$(OBJ)
@@ -1444,7 +1489,7 @@ $(GLOBJ)gdevdrop.$(OBJ) : $(GLSRC)gdevdrop.c $(GXERR) $(memory__h)\
$(gsbittab_h) $(gsropt_h)\
$(gxcindex_h) $(gxdcolor_h) $(gxdevice_h) $(gxdevmem_h) $(gxdevrop_h)\
$(gxgetbit_h)\
- $(gdevmrop_h)
+ $(gdevmem_h) $(gdevmrop_h)
$(GLCC) $(GLO_)gdevdrop.$(OBJ) $(C_) $(GLSRC)gdevdrop.c
$(GLOBJ)gdevmr1.$(OBJ) : $(GLSRC)gdevmr1.c $(GXERR) $(memory__h)\
@@ -1518,13 +1563,13 @@ $(GLD)psf0lib.dev : $(LIB_MAK) $(ECHOGS_XE) $(GLD)cmaplib.dev $(psf0lib_)
$(ADDMOD) $(GLD)psf0lib -include $(GLD)cmaplib
$(GLOBJ)gschar0.$(OBJ) : $(GLSRC)gschar0.c $(GXERR) $(memory__h)\
- $(gsstruct_h) $(gxfixed_h) $(gxdevice_h) $(gxdevmem_h)\
- $(gsfcmap_h) $(gxfont_h) $(gxfont0_h) $(gxchar_h)
+ $(gsfcmap_h) $(gsstruct_h)\
+ $(gxdevice_h) $(gxfixed_h) $(gxfont_h) $(gxfont0_h) $(gxtext_h)
$(GLCC) $(GLO_)gschar0.$(OBJ) $(C_) $(GLSRC)gschar0.c
$(GLOBJ)gsfont0.$(OBJ) : $(GLSRC)gsfont0.c $(GXERR) $(memory__h)\
$(gsmatrix_h) $(gsstruct_h) $(gxfixed_h) $(gxdevmem_h) $(gxfcache_h)\
- $(gxfont_h) $(gxfont0_h) $(gxchar_h) $(gxdevice_h)
+ $(gxfont_h) $(gxfont0_h) $(gxdevice_h)
$(GLCC) $(GLO_)gsfont0.$(OBJ) $(C_) $(GLSRC)gsfont0.c
# ---------------- Pattern color ---------------- #
@@ -1542,7 +1587,7 @@ $(GLOBJ)gspcolor.$(OBJ) : $(GLSRC)gspcolor.c $(GXERR) $(math__h)\
$(gsimage_h) $(gsiparm4_h) $(gspath_h) $(gsrop_h) $(gsstruct_h) $(gsutil_h)\
$(gxarith_h) $(gxcolor2_h) $(gxcoord_h) $(gxclip2_h) $(gxcspace_h)\
$(gxdcolor_h) $(gxdevice_h) $(gxdevmem_h) $(gxfixed_h) $(gxmatrix_h)\
- $(gxp1fill_h) $(gxpath_h) $(gxpcolor_h) $(gzstate_h)
+ $(gxpath_h) $(gxpcolor_h) $(gzstate_h)
$(GLCC) $(GLO_)gspcolor.$(OBJ) $(C_) $(GLSRC)gspcolor.c
$(GLOBJ)gsptype1.$(OBJ) : $(GLSRC)gsptype1.c $(GX) $(math__h)\
@@ -1550,7 +1595,7 @@ $(GLOBJ)gsptype1.$(OBJ) : $(GLSRC)gsptype1.c $(GX) $(math__h)\
$(gsstruct_h) $(gsutil_h)\
$(gxarith_h) $(gxclip2_h) $(gxcolor2_h) $(gxcoord_h) $(gxcspace_h)\
$(gxdcolor_h) $(gxdevice_h) $(gxdevmem_h) $(gxfixed_h) $(gxmatrix_h)\
- $(gxp1fill_h) $(gxpath_h) $(gxpcolor_h) $(gzstate_h)
+ $(gxp1impl_h) $(gxpath_h) $(gxpcolor_h) $(gzstate_h)
$(GLCC) $(GLO_)gsptype1.$(OBJ) $(C_) $(GLSRC)gsptype1.c
$(GLOBJ)gxclip2.$(OBJ) : $(GLSRC)gxclip2.c $(GXERR) $(memory__h)\
@@ -1560,7 +1605,7 @@ $(GLOBJ)gxclip2.$(OBJ) : $(GLSRC)gxclip2.c $(GXERR) $(memory__h)\
$(GLOBJ)gxp1fill.$(OBJ) : $(GLSRC)gxp1fill.c $(GXERR) $(math__h)\
$(gsrop_h) $(gsmatrix_h)\
$(gxcolor2_h) $(gxclip2_h) $(gxcspace_h) $(gxdcolor_h) $(gxdevcli_h)\
- $(gxdevmem_h) $(gxp1fill_h) $(gxpcolor_h)
+ $(gxdevmem_h) $(gxp1impl_h) $(gxpcolor_h)
$(GLCC) $(GLO_)gxp1fill.$(OBJ) $(C_) $(GLSRC)gxp1fill.c
$(GLOBJ)gxpcmap.$(OBJ) : $(GLSRC)gxpcmap.c $(GXERR) $(math__h) $(memory__h)\
@@ -1773,13 +1818,12 @@ $(GLD)cielib.dev : $(LIB_MAK) $(ECHOGS_XE) $(cielib_)
$(ADDMOD) $(GLD)cielib $(cielib2_)
$(GLOBJ)gscie.$(OBJ) : $(GLSRC)gscie.c $(GXERR) $(math__h) $(memory__h)\
- $(gscie_h) $(gscolor2_h) $(gsmatrix_h) $(gsstruct_h)\
- $(gxarith_h) $(gxcmap_h) $(gxcspace_h) $(gxdevice_h) $(gzstate_h)
+ $(gscolor2_h) $(gsmatrix_h) $(gsstruct_h)\
+ $(gxarith_h) $(gxcie_h) $(gxcmap_h) $(gxcspace_h) $(gxdevice_h) $(gzstate_h)
$(GLCC) $(GLO_)gscie.$(OBJ) $(C_) $(GLSRC)gscie.c
$(GLOBJ)gsciemap.$(OBJ) : $(GLSRC)gsciemap.c $(GXERR) $(math__h)\
- $(gscie_h)\
- $(gxarith_h) $(gxcmap_h) $(gxcspace_h) $(gxdevice_h) $(gxistate_h)
+ $(gxarith_h) $(gxcie_h) $(gxcmap_h) $(gxcspace_h) $(gxdevice_h) $(gxistate_h)
$(GLCC) $(GLO_)gsciemap.$(OBJ) $(C_) $(GLSRC)gsciemap.c
$(GLOBJ)gscrd.$(OBJ) : $(GLSRC)gscrd.c $(GXERR)\
@@ -1795,8 +1839,8 @@ $(GLOBJ)gscrdp.$(OBJ) : $(GLSRC)gscrdp.c $(GXERR)\
$(GLCC) $(GLO_)gscrdp.$(OBJ) $(C_) $(GLSRC)gscrdp.c
$(GLOBJ)gscscie.$(OBJ) : $(GLSRC)gscscie.c $(GXERR) $(math__h)\
- $(gscie_h) $(gscolor2_h) $(gsmatrix_h) $(gsstruct_h)\
- $(gxarith_h) $(gxcmap_h) $(gxcspace_h) $(gxdevice_h) $(gzstate_h)
+ $(gscolor2_h) $(gsmatrix_h) $(gsstruct_h)\
+ $(gxarith_h) $(gxcie_h) $(gxcmap_h) $(gxcspace_h) $(gxdevice_h) $(gzstate_h)
$(GLCC) $(GLO_)gscscie.$(OBJ) $(C_) $(GLSRC)gscscie.c
$(GLOBJ)gxctable.$(OBJ) : $(GLSRC)gxctable.c $(GX)\
@@ -2016,6 +2060,18 @@ $(GLOBJ)gp_unifs.$(OBJ) : $(GLSRC)gp_unifs.c $(AK)\
$(GLOBJ)gp_unifn.$(OBJ) : $(GLSRC)gp_unifn.c $(AK) $(gx_h) $(gp_h)
$(GLCC) $(GLO_)gp_unifn.$(OBJ) $(C_) $(GLSRC)gp_unifn.c
+# Pipes. These are actually the same on all platforms that have them.
+
+pipe_=$(GLOBJ)gdevpipe.$(OBJ)
+$(GLD)pipe.dev : $(LIB_MAK) $(ECHOGS_XE) $(pipe_)
+ $(SETMOD) $(GLD)pipe $(pipe_)
+ $(ADDMOD) $(GLD)pipe -iodev pipe
+
+$(GLOBJ)gdevpipe.$(OBJ) : $(GLSRC)gdevpipe.c $(AK)\
+ $(errno__h) $(pipe__h) $(stdio__h) $(string__h) \
+ $(gserror_h) $(gsmemory_h) $(gstypes_h) $(gxiodev_h)
+ $(GLCC) $(GLO_)gdevpipe.$(OBJ) $(C_) $(GLSRC)gdevpipe.c
+
# Thread / semaphore / monitor implementation.
# Dummy implementation.
diff --git a/gs/src/math_.h b/gs/src/math_.h
index 4ba93750c..6fca7aee8 100644
--- a/gs/src/math_.h
+++ b/gs/src/math_.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1989, 1995, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1989, 1995, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -76,9 +76,9 @@ extern double hypot(double, double);
extern double atan2(), ldexp();
#endif
-#ifdef DEBUG
/* Intercept calls on sqrt for debugging. */
extern double gs_sqrt(P3(double, const char *, int));
+#ifdef DEBUG
#undef sqrt
#define sqrt(x) gs_sqrt(x, __FILE__, __LINE__)
#endif /* DEBUG */
diff --git a/gs/src/memory_.h b/gs/src/memory_.h
index ac1a411e1..80f131009 100644
--- a/gs/src/memory_.h
+++ b/gs/src/memory_.h
@@ -37,15 +37,7 @@
# else
# define memcmp_inline(b1,b2,len) __memcmp__(b1,b2,len)
# endif
-/*
- * The Turbo C implementation of memset swaps the arguments and calls
- * the non-standard routine setmem. We may as well do it in advance.
- */
-# undef memset /* just in case */
# include <mem.h>
-# ifndef memset /* Borland C++ can inline this */
-# define memset(dest,chr,cnt) setmem(dest,cnt,chr)
-# endif
#else
/* Not Turbo C, no inline functions */
# define memcmp_inline(b1,b2,len) memcmp(b1,b2,len)
diff --git a/gs/src/msvc32.mak b/gs/src/msvc32.mak
index 15bf59e42..48cdbf02a 100644
--- a/gs/src/msvc32.mak
+++ b/gs/src/msvc32.mak
@@ -300,7 +300,7 @@ SYNC=winsync
# Choose the language feature(s) to include. See gs.mak for details.
!ifndef FEATURE_DEVS
-FEATURE_DEVS=$(PSD)psl3.dev $(PSD)pdf.dev $(PSD)dpsnext.dev $(PSD)ttfont.dev
+FEATURE_DEVS=$(PSD)psl3.dev $(PSD)pdf.dev $(PSD)dpsnext.dev $(PSD)ttfont.dev $(PSD)mshandle.dev $(PSD)pipe.dev
!endif
# Choose whether to compile the .ps initialization files into the executable.
@@ -346,7 +346,7 @@ DEVICE_DEVS7=$(DD)t4693d2.dev $(DD)t4693d4.dev $(DD)t4693d8.dev $(DD)tek4696.dev
DEVICE_DEVS8=$(DD)pcxmono.dev $(DD)pcxgray.dev $(DD)pcx16.dev $(DD)pcx256.dev $(DD)pcx24b.dev $(DD)pcxcmyk.dev
DEVICE_DEVS9=$(DD)pbm.dev $(DD)pbmraw.dev $(DD)pgm.dev $(DD)pgmraw.dev $(DD)pgnm.dev $(DD)pgnmraw.dev
DEVICE_DEVS10=$(DD)tiffcrle.dev $(DD)tiffg3.dev $(DD)tiffg32d.dev $(DD)tiffg4.dev $(DD)tifflzw.dev $(DD)tiffpack.dev
-DEVICE_DEVS11=$(DD)bmpmono.dev $(DD)bmp16.dev $(DD)bmp256.dev $(DD)bmp16m.dev $(DD)tiff12nc.dev $(DD)tiff24nc.dev
+DEVICE_DEVS11=$(DD)bmpmono.dev $(DD)bmpgray.dev $(DD)bmp16.dev $(DD)bmp256.dev $(DD)bmp16m.dev $(DD)tiff12nc.dev $(DD)tiff24nc.dev
DEVICE_DEVS12=$(DD)psmono.dev $(DD)bit.dev $(DD)bitrgb.dev $(DD)bitcmyk.dev
DEVICE_DEVS13=$(DD)pngmono.dev $(DD)pnggray.dev $(DD)png16.dev $(DD)png256.dev $(DD)png16m.dev
DEVICE_DEVS14=$(DD)jpeg.dev $(DD)jpeggray.dev
diff --git a/gs/src/msvccmd.mak b/gs/src/msvccmd.mak
index 6fd64045d..9108e4fc9 100644
--- a/gs/src/msvccmd.mak
+++ b/gs/src/msvccmd.mak
@@ -62,7 +62,12 @@ CCAUX_TAIL= /link $(LINK_LIB_SWITCH)
D=\#
SH=
+
+# Define switches for the compilers.
+
+C_=
O_=-Fo
+RO_=$(O_)
# Define the arguments for genconf.
@@ -185,6 +190,7 @@ CC_=$(CC_WX) $(COMPILE_FULL_OPTIMIZED) /Za
CC_D=$(CC_WX) $(COMPILE_WITH_FRAMES)
CC_INT=$(CC_)
CC_LEAF=$(CC_) $(COMPILE_WITHOUT_FRAMES)
+CC_NO_WARN=$(CC_)
# Compiler for auxiliary programs
diff --git a/gs/src/msvclib.mak b/gs/src/msvclib.mak
index 297a5b9a6..1375d23e5 100644
--- a/gs/src/msvclib.mak
+++ b/gs/src/msvclib.mak
@@ -16,10 +16,6 @@
# all copies.
-# needed by clients that don't use msvc32.mak
-#
-
-!include $(GLSRCDIR)\version.mak
# makefile for Microsoft Visual C++ 4.1 or later, Windows NT or Windows 95 LIBRARY.
#
# All configurable options are surrounded by !ifndef/!endif to allow
@@ -118,6 +114,7 @@ GLOBJDIR=.\obj
NUL=
DD=$(GLGENDIR)\$(NUL)
GLD=$(GLGENDIR)\$(NUL)
+
# Define the directory where the IJG JPEG library sources are stored,
# and the major version of the library that is stored there.
# You may need to change this if the IJG library version changes.
@@ -247,7 +244,7 @@ SYNC=winsync
# Choose the language feature(s) to include. See gs.mak for details.
!ifndef FEATURE_DEVS
-FEATURE_DEVS=dps2lib.dev psl2cs.dev cielib.dev imasklib.dev patlib.dev htxlib.dev roplib.dev devcmap.dev bbox.dev
+FEATURE_DEVS=dps2lib.dev psl2cs.dev cielib.dev imasklib.dev patlib.dev htxlib.dev roplib.dev devcmap.dev bbox.dev pipe.dev
!endif
# Choose whether to compile the .ps initialization files into the executable.
@@ -340,7 +337,7 @@ LIB_ONLY=$(GLOBJDIR)\gslib.obj $(GLOBJDIR)\gsnogc.obj $(GLOBJDIR)\gconfig.obj $(
MAKEDLL=0
PLATFORM=mslib32_
-
+!include $(GLSRCDIR)\version.mak
!include $(GLSRCDIR)\msvccmd.mak
!include $(GLSRCDIR)\winlib.mak
!include $(GLSRCDIR)\msvctail.mak
diff --git a/gs/src/oparc.h b/gs/src/oparc.h
new file mode 100644
index 000000000..7d79a04b1
--- /dev/null
+++ b/gs/src/oparc.h
@@ -0,0 +1,34 @@
+/* Copyright (C) 1999 Aladdin Enterprises. All rights reserved.
+
+ This file is part of Aladdin Ghostscript.
+
+ Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
+ or distributor accepts any responsibility for the consequences of using it,
+ or for whether it serves any particular purpose or works at all, unless he
+ or she says so in writing. Refer to the Aladdin Ghostscript Free Public
+ License (the "License") for full details.
+
+ Every copy of Aladdin Ghostscript must include a copy of the License,
+ normally in a plain ASCII text file named PUBLIC. The License grants you
+ the right to copy, modify and redistribute Aladdin Ghostscript, but only
+ under certain conditions described in the License. Among other things, the
+ License requires that the copyright notice and this notice be preserved on
+ all copies.
+ */
+
+
+/* Arc operator declarations */
+
+#ifndef oparc_INCLUDED
+# define oparc_INCLUDED
+
+/*
+ * These declarations are in a separate from, rather than in opextern.h,
+ * because these operators are not included in PDF-only configurations.
+ */
+
+int zarc(P1(i_ctx_t *));
+int zarcn(P1(i_ctx_t *));
+int zarct(P1(i_ctx_t *));
+
+#endif /* oparc_INCLUDED */
diff --git a/gs/src/openvms.mak b/gs/src/openvms.mak
index 5737b19f5..6bc601d50 100644
--- a/gs/src/openvms.mak
+++ b/gs/src/openvms.mak
@@ -384,6 +384,7 @@ include $(GLSRCDIR)contrib.mak
CC_=$(COMP)
CC_INT=$(CC_)
CC_LEAF=$(CC_)
+CC_NO_WARN=$(CC_)
# ----------------------------- Main program ------------------------------ #
diff --git a/gs/src/openvms.mmk b/gs/src/openvms.mmk
index b319c9c51..da98df829 100644
--- a/gs/src/openvms.mmk
+++ b/gs/src/openvms.mmk
@@ -369,6 +369,7 @@ CONFLDTR=-o
CC_=$(COMP)
CC_INT=$(CC_)
CC_LEAF=$(CC_)
+CC_NO_WARN=$(CC_)
# ------------------- Include the generic makefiles ---------------------- #
diff --git a/gs/src/opextern.h b/gs/src/opextern.h
index b833311c0..efd8bd265 100644
--- a/gs/src/opextern.h
+++ b/gs/src/opextern.h
@@ -46,6 +46,10 @@ int zindex(P1(i_ctx_t *));
int zpop(P1(i_ctx_t *));
int zroll(P1(i_ctx_t *));
int zsub(P1(i_ctx_t *));
+/* Internal entry points for the interpreter. */
+int zop_add(P1(ref *));
+int zop_def(P1(i_ctx_t *));
+int zop_sub(P1(ref *));
/* Operators exported for server loop implementations. */
int zflush(P1(i_ctx_t *));
@@ -88,6 +92,42 @@ int zrcurveto(P1(i_ctx_t *));
int zrlineto(P1(i_ctx_t *));
int zrmoveto(P1(i_ctx_t *));
+/* Operators exported for the FunctionType 4 interpreter. */
+/* zarith.c: */
+int zabs(P1(i_ctx_t *));
+int zceiling(P1(i_ctx_t *));
+int zdiv(P1(i_ctx_t *));
+int zfloor(P1(i_ctx_t *));
+int zidiv(P1(i_ctx_t *));
+int zmod(P1(i_ctx_t *));
+int zmul(P1(i_ctx_t *));
+int zneg(P1(i_ctx_t *));
+int zround(P1(i_ctx_t *));
+int ztruncate(P1(i_ctx_t *));
+/* zmath.c: */
+int zatan(P1(i_ctx_t *));
+int zcos(P1(i_ctx_t *));
+int zexp(P1(i_ctx_t *));
+int zln(P1(i_ctx_t *));
+int zlog(P1(i_ctx_t *));
+int zsin(P1(i_ctx_t *));
+int zsqrt(P1(i_ctx_t *));
+/* zrelbit.c: */
+int zand(P1(i_ctx_t *));
+int zbitshift(P1(i_ctx_t *));
+int zeq(P1(i_ctx_t *));
+int zge(P1(i_ctx_t *));
+int zgt(P1(i_ctx_t *));
+int zle(P1(i_ctx_t *));
+int zlt(P1(i_ctx_t *));
+int zne(P1(i_ctx_t *));
+int znot(P1(i_ctx_t *));
+int zor(P1(i_ctx_t *));
+int zxor(P1(i_ctx_t *));
+/* ztype.c: */
+int zcvi(P1(i_ctx_t *));
+int zcvr(P1(i_ctx_t *));
+
/* Operators exported for CIE cache loading. */
int zcvx(P1(i_ctx_t *));
int zexec(P1(i_ctx_t *)); /* also for .runexec */
@@ -96,8 +136,10 @@ int zfor(P1(i_ctx_t *));
/* Odds and ends */
int zbegin(P1(i_ctx_t *));
int zcleartomark(P1(i_ctx_t *));
-int zend(P1(i_ctx_t *));
int zclosefile(P1(i_ctx_t *)); /* for runexec_cleanup */
+int zcopy_dict(P1(i_ctx_t *)); /* for zcopy */
+int zend(P1(i_ctx_t *));
+int zfor_fraction(P1(i_ctx_t *)); /* for color function sampling */
int zsetfont(P1(i_ctx_t *)); /* for cshow_continue */
/* Operators exported for special customer needs. */
diff --git a/gs/src/os2.mak b/gs/src/os2.mak
index 226dbc4b2..175064e81 100644
--- a/gs/src/os2.mak
+++ b/gs/src/os2.mak
@@ -377,6 +377,7 @@ CC_=$(CC)
CC_D=$(CC) $(CO)
CC_INT=$(CC)
CC_LEAF=$(CC_)
+CC_NO_WARN=$(CC_)
# ------ Devices and features ------ #
@@ -425,7 +426,7 @@ DEVICE_DEVS7=dfaxhigh.dev dfaxlow.dev
DEVICE_DEVS8=pcxmono.dev pcxgray.dev pcx16.dev pcx256.dev pcx24b.dev pcxcmyk.dev
DEVICE_DEVS9=pbm.dev pbmraw.dev pgm.dev pgmraw.dev pgnm.dev pgnmraw.dev pnm.dev pnmraw.dev ppm.dev ppmraw.dev
DEVICE_DEVS10=tiffcrle.dev tiffg3.dev tiffg32d.dev tiffg4.dev tifflzw.dev tiffpack.dev
-DEVICE_DEVS11=bmpmono.dev bmp16.dev bmp256.dev bmp16m.dev tiff12nc.dev tiff24nc.dev
+DEVICE_DEVS11=bmpmono.dev bmpgray.dev bmp16.dev bmp256.dev bmp16m.dev tiff12nc.dev tiff24nc.dev
DEVICE_DEVS12=psmono.dev psgray.dev bit.dev bitrgb.dev bitcmyk.dev
DEVICE_DEVS13=pngmono.dev pnggray.dev png16.dev png256.dev png16m.dev
DEVICE_DEVS14=jpeg.dev jpeggray.dev
diff --git a/gs/src/pipe_.h b/gs/src/pipe_.h
index 17679bcdc..fd2fc989a 100644
--- a/gs/src/pipe_.h
+++ b/gs/src/pipe_.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1997, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -24,6 +24,13 @@
#include "stdio_.h"
+#ifdef __WIN32__
+/*
+ * MS Windows has popen and pclose in stdio.h, but under different names.
+ */
+# define popen(cmd, mode) _popen(cmd, mode)
+# define pclose(file) _pclose(file)
+#else /* !__WIN32__ */
/*
* popen isn't POSIX-standard, so we declare it here.
* Because of inconsistent (and sometimes incorrect) header files,
@@ -32,5 +39,6 @@
*/
extern FILE *popen( /* P2(const char *, const char *) */ );
extern int pclose(P1(FILE *));
+#endif /* !__WIN32__ */
#endif /* pipe__INCLUDED */
diff --git a/gs/src/sbwbs.c b/gs/src/sbwbs.c
index f3c4d33ec..2783ac9c1 100644
--- a/gs/src/sbwbs.c
+++ b/gs/src/sbwbs.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1994, 1995, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1994, 1995, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -31,6 +31,14 @@
private_st_buffered_state();
/* Initialize */
+private void
+s_buffered_set_defaults(stream_state * st)
+{
+ stream_buffered_state *const ss = (stream_buffered_state *) st;
+
+ /* Clear pointers */
+ ss->buffer = 0;
+}
private int
s_buffered_no_block_init(stream_state * st)
{
@@ -98,6 +106,16 @@ s_buffered_release(stream_state * st)
private_st_BWBS_state();
private void s_BWBS_release(P1(stream_state *));
+/* Set default parameter values (actually, just clear pointers). */
+private void
+s_BWBS_set_defaults(stream_state * st)
+{
+ stream_BWBS_state *const ss = (stream_BWBS_state *) st;
+
+ s_buffered_set_defaults(st);
+ ss->offsets = 0;
+}
+
/* Initialize */
private int
bwbs_init(stream_state * st, uint osize)
@@ -275,8 +293,9 @@ s_BWBSE_process(stream_state * st, stream_cursor_read * pr,
}
/* Stream template */
-const stream_template s_BWBSE_template =
-{&st_BWBS_state, s_BWBSE_init, s_BWBSE_process, sizeof(int) * 2, 1, s_BWBS_release
+const stream_template s_BWBSE_template = {
+ &st_BWBS_state, s_BWBSE_init, s_BWBSE_process, sizeof(int) * 2, 1,
+ s_BWBS_release, s_BWBS_set_defaults
};
/* ------ BWBlockSortDecode ------ */
@@ -524,6 +543,7 @@ s_BWBSD_process(stream_state * st, stream_cursor_read * pr,
}
/* Stream template */
-const stream_template s_BWBSD_template =
-{&st_BWBS_state, s_BWBSD_init, s_BWBSD_process, 1, sizeof(int) * 2, s_BWBS_release
+const stream_template s_BWBSD_template = {
+ &st_BWBS_state, s_BWBSD_init, s_BWBSD_process, 1, sizeof(int) * 2,
+ s_BWBS_release, s_BWBS_set_defaults
};
diff --git a/gs/src/scf.h b/gs/src/scf.h
index eaa591831..bef21ec31 100644
--- a/gs/src/scf.h
+++ b/gs/src/scf.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1992, 1995, 1997, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1992, 1995, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -99,19 +99,22 @@ typedef hcd_code cfd_node;
* or a (negative) exceptional value.
*/
#define run_error (-1)
-#define run_zeros (-2) /* EOL follows, possibly with more padding first */
+#define run_zeros (-2) /* EOL follows, possibly with more padding first */
#define run_uncompressed (-3)
/* 2-D codes */
#define run2_pass (-4)
#define run2_horizontal (-5)
#define cfd_white_initial_bits 8
+#define cfd_white_min_bits 4 /* shortest white run */
extern const cfd_node cf_white_decode[];
#define cfd_black_initial_bits 7
+#define cfd_black_min_bits 2 /* shortest black run */
extern const cfd_node cf_black_decode[];
#define cfd_2d_initial_bits 7
+#define cfd_2d_min_bits 4 /* shortest non-H/V 2-D run */
extern const cfd_node cf_2d_decode[];
#define cfd_uncompressed_initial_bits 6 /* must be 6 */
diff --git a/gs/src/scfd.c b/gs/src/scfd.c
index 115aad2ab..493a7ea59 100644
--- a/gs/src/scfd.c
+++ b/gs/src/scfd.c
@@ -118,32 +118,39 @@ s_CFD_release(stream_state * st)
#else
# define IF_DEBUG(expr) DO_NOTHING
#endif
-#define get_run(decode, initial_bits, runlen, str, outl)\
-{ const cfd_node *np;\
+#define get_run(decode, initial_bits, min_bits, runlen, str, locl, outl)\
+ BEGIN\
+ const cfd_node *np;\
int clen;\
- ensure_bits(initial_bits, outl);\
+\
+ HCD_ENSURE_BITS_ELSE(initial_bits) {\
+ /* We might still have enough bits for the specific code. */\
+ if (bits_left < min_bits) goto outl;\
+ np = &decode[hcd_peek_bits_left() << (initial_bits - bits_left)];\
+ if ((clen = np->code_length) > bits_left) goto outl;\
+ goto locl;\
+ }\
np = &decode[peek_bits(initial_bits)];\
- if ( (clen = np->code_length) > initial_bits )\
- { IF_DEBUG(uint init_bits = peek_bits(initial_bits));\
- if ( !avail_bits(clen) ) goto outl;\
+ if ((clen = np->code_length) > initial_bits) {\
+ IF_DEBUG(uint init_bits = peek_bits(initial_bits));\
+ if (!avail_bits(clen)) goto outl;\
clen -= initial_bits;\
skip_bits(initial_bits);\
ensure_bits(clen, outl); /* can't goto outl */\
np = &decode[np->run_length + peek_var_bits(clen)];\
if_debug4('W', "%s xcode=0x%x,%d rlen=%d\n", str,\
(init_bits << np->code_length) +\
- peek_var_bits(np->code_length),\
+ peek_var_bits(np->code_length),\
initial_bits + np->code_length,\
np->run_length);\
skip_bits(np->code_length);\
- }\
- else\
- { if_debug4('W', "%s code=0x%x,%d rlen=%d\n", str,\
+ } else {\
+ locl: if_debug4('W', "%s code=0x%x,%d rlen=%d\n", str,\
peek_var_bits(clen), clen, np->run_length);\
skip_bits(clen);\
}\
runlen = np->run_length;\
-}
+ END
/* Skip data bits for a white run. */
/* rlen is either less than 64, or a multiple of 64. */
@@ -452,7 +459,8 @@ cf_decode_1d(stream_CFD_state * ss, stream_cursor_read * pr)
if (q_at_stop())
goto done;
dw: /* Decode a white run. */
- get_run(cf_white_decode, cfd_white_initial_bits, bcnt, "[w1]white", out0);
+ get_run(cf_white_decode, cfd_white_initial_bits, cfd_white_min_bits,
+ bcnt, "[w1]white", dwl, out0);
if (bcnt < 0) { /* exceptional situation */
switch (bcnt) {
case run_uncompressed: /* Uncompressed data. */
@@ -479,7 +487,8 @@ cf_decode_1d(stream_CFD_state * ss, stream_cursor_read * pr)
}
run_color = 1;
db: /* Decode a black run. */
- get_run(cf_black_decode, cfd_black_initial_bits, bcnt, "[w1]black", out1);
+ get_run(cf_black_decode, cfd_black_initial_bits, cfd_black_initial_bits,
+ bcnt, "[w1]black", dbl, out1);
if (bcnt < 0) { /* All exceptional codes are invalid here. */
/****** WRONG, uncompressed IS ALLOWED ******/
status = ERRC;
@@ -596,8 +605,8 @@ v0: skip_bits(1);
else
goto hbb;
case 0: /* everything else */
- get_run(cf_2d_decode, cfd_2d_initial_bits, rlen,
- "[w2]", out0);
+ get_run(cf_2d_decode, cfd_2d_initial_bits, cfd_2d_min_bits,
+ rlen, "[w2]", d2l, out0);
/* rlen may be run2_pass, run_uncompressed, or */
/* 0..countof(cf2_run_vertical)-1. */
if (rlen < 0)
@@ -705,16 +714,16 @@ v0: skip_bits(1);
* branch back into it if we run out of input data.
*/
/* White, then black. */
- hww:get_run(cf_white_decode, cfd_white_initial_bits, rlen,
- " white", outww);
+ hww:get_run(cf_white_decode, cfd_white_initial_bits, cfd_white_min_bits,
+ rlen, " white", wwl, outww);
if ((count -= rlen) < end_count) {
status = ERRC;
goto out;
}
skip_data(rlen, hww);
/* Handle the second half of a white-black horizontal code. */
- hwb:get_run(cf_black_decode, cfd_black_initial_bits, rlen,
- " black", outwb);
+ hwb:get_run(cf_black_decode, cfd_black_initial_bits, cfd_black_min_bits,
+ rlen, " black", wbl, outwb);
if ((count -= rlen) < end_count) {
status = ERRC;
goto out;
@@ -726,16 +735,16 @@ v0: skip_bits(1);
outwb:ss->run_color = 1;
goto out0;
/* Black, then white. */
- hbb:get_run(cf_black_decode, cfd_black_initial_bits, rlen,
- " black", outbb);
+ hbb:get_run(cf_black_decode, cfd_black_initial_bits, cfd_black_min_bits,
+ rlen, " black", bbl, outbb);
if ((count -= rlen) < end_count) {
status = ERRC;
goto out;
}
invert_data(rlen, black_byte, goto hbb, ihbb);
/* Handle the second half of a black-white horizontal code. */
- hbw:get_run(cf_white_decode, cfd_white_initial_bits, rlen,
- " white", outbw);
+ hbw:get_run(cf_white_decode, cfd_white_initial_bits, cfd_white_min_bits,
+ rlen, " white", bwl, outbw);
if ((count -= rlen) < end_count) {
status = ERRC;
goto out;
diff --git a/gs/src/scfdgen.c b/gs/src/scfdgen.c
index effd975dc..31eb31fa7 100644
--- a/gs/src/scfdgen.c
+++ b/gs/src/scfdgen.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1992, 1994, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1992, 1994, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -42,7 +42,7 @@ main()
FILE *out = fopen("scfdtab.c", "w");
cfd_node area[1 << max(cfd_white_initial_bits, cfd_black_initial_bits)];
- fputs("/* Copyright (C) 1992, 1993, 1998 Aladdin Enterprises. All rights reserved. */\n\n", out);
+ fputs("/* Copyright (C) 1992, 1993, 1998, 1999 Aladdin Enterprises. All rights reserved. */\n\n", out);
fputs("/* This file was generated automatically. It is governed by the same terms */\n", out);
fputs("/* as the files scfetab.c and scfdgen.c from which it was derived. */\n", out);
fputs("/* Consult those files for the licensing terms and conditions. */\n\n", out);
@@ -68,7 +68,8 @@ main()
cfd_build_tree(area, cfd_enumerate_uncompressed, cfd_uncompressed_initial_bits, out);
fputs("\n};\n\n", out);
fputs("/* Dummy executable code to pacify compilers. */\n", out);
- fputs("void\ncfd_dummy()\n{\n}\n", out);
+ fputs("void scfdtab_dummy(P0());\n", out);
+ fputs("void\nscfdtab_dummy()\n{\n}\n", out);
fclose(out);
return 0;
}
diff --git a/gs/src/scfdtab.c b/gs/src/scfdtab.c
index 6ba584780..27a44ce2a 100644
--- a/gs/src/scfdtab.c
+++ b/gs/src/scfdtab.c
@@ -1,10 +1,10 @@
-/* Copyright (C) 1992, 1993, 1998 Aladdin Enterprises. All rights reserved. */
+/* Copyright (C) 1992, 1993, 1998, 1999 Aladdin Enterprises. All rights reserved. */
/* This file was generated automatically. It is governed by the same terms */
-/* as the files scftab.c and scfdgen.c from which it was derived. */
+/* as the files scfetab.c and scfdgen.c from which it was derived. */
/* Consult those files for the licensing terms and conditions. */
-
+/* scfdtab.c */
/* Tables for CCITTFaxDecode filter. */
#include "std.h"
@@ -12,931 +12,928 @@
#include "scf.h"
/* White decoding table. */
-const cfd_node cf_white_decode[] =
-{
- {256, 12},
- {272, 12},
- {29, 8},
- {30, 8},
- {45, 8},
- {46, 8},
- {22, 7},
- {22, 7},
- {23, 7},
- {23, 7},
- {47, 8},
- {48, 8},
- {13, 6},
- {13, 6},
- {13, 6},
- {13, 6},
- {20, 7},
- {20, 7},
- {33, 8},
- {34, 8},
- {35, 8},
- {36, 8},
- {37, 8},
- {38, 8},
- {19, 7},
- {19, 7},
- {31, 8},
- {32, 8},
- {1, 6},
- {1, 6},
- {1, 6},
- {1, 6},
- {12, 6},
- {12, 6},
- {12, 6},
- {12, 6},
- {53, 8},
- {54, 8},
- {26, 7},
- {26, 7},
- {39, 8},
- {40, 8},
- {41, 8},
- {42, 8},
- {43, 8},
- {44, 8},
- {21, 7},
- {21, 7},
- {28, 7},
- {28, 7},
- {61, 8},
- {62, 8},
- {63, 8},
- {0, 8},
- {320, 8},
- {384, 8},
- {10, 5},
- {10, 5},
- {10, 5},
- {10, 5},
- {10, 5},
- {10, 5},
- {10, 5},
- {10, 5},
- {11, 5},
- {11, 5},
- {11, 5},
- {11, 5},
- {11, 5},
- {11, 5},
- {11, 5},
- {11, 5},
- {27, 7},
- {27, 7},
- {59, 8},
- {60, 8},
- {288, 9},
- {290, 9},
- {18, 7},
- {18, 7},
- {24, 7},
- {24, 7},
- {49, 8},
- {50, 8},
- {51, 8},
- {52, 8},
- {25, 7},
- {25, 7},
- {55, 8},
- {56, 8},
- {57, 8},
- {58, 8},
- {192, 6},
- {192, 6},
- {192, 6},
- {192, 6},
- {1664, 6},
- {1664, 6},
- {1664, 6},
- {1664, 6},
- {448, 8},
- {512, 8},
- {292, 9},
- {640, 8},
- {576, 8},
- {294, 9},
- {296, 9},
- {298, 9},
- {300, 9},
- {302, 9},
- {256, 7},
- {256, 7},
- {2, 4},
- {2, 4},
- {2, 4},
- {2, 4},
- {2, 4},
- {2, 4},
- {2, 4},
- {2, 4},
- {2, 4},
- {2, 4},
- {2, 4},
- {2, 4},
- {2, 4},
- {2, 4},
- {2, 4},
- {2, 4},
- {3, 4},
- {3, 4},
- {3, 4},
- {3, 4},
- {3, 4},
- {3, 4},
- {3, 4},
- {3, 4},
- {3, 4},
- {3, 4},
- {3, 4},
- {3, 4},
- {3, 4},
- {3, 4},
- {3, 4},
- {3, 4},
- {128, 5},
- {128, 5},
- {128, 5},
- {128, 5},
- {128, 5},
- {128, 5},
- {128, 5},
- {128, 5},
- {8, 5},
- {8, 5},
- {8, 5},
- {8, 5},
- {8, 5},
- {8, 5},
- {8, 5},
- {8, 5},
- {9, 5},
- {9, 5},
- {9, 5},
- {9, 5},
- {9, 5},
- {9, 5},
- {9, 5},
- {9, 5},
- {16, 6},
- {16, 6},
- {16, 6},
- {16, 6},
- {17, 6},
- {17, 6},
- {17, 6},
- {17, 6},
- {4, 4},
- {4, 4},
- {4, 4},
- {4, 4},
- {4, 4},
- {4, 4},
- {4, 4},
- {4, 4},
- {4, 4},
- {4, 4},
- {4, 4},
- {4, 4},
- {4, 4},
- {4, 4},
- {4, 4},
- {4, 4},
- {5, 4},
- {5, 4},
- {5, 4},
- {5, 4},
- {5, 4},
- {5, 4},
- {5, 4},
- {5, 4},
- {5, 4},
- {5, 4},
- {5, 4},
- {5, 4},
- {5, 4},
- {5, 4},
- {5, 4},
- {5, 4},
- {14, 6},
- {14, 6},
- {14, 6},
- {14, 6},
- {15, 6},
- {15, 6},
- {15, 6},
- {15, 6},
- {64, 5},
- {64, 5},
- {64, 5},
- {64, 5},
- {64, 5},
- {64, 5},
- {64, 5},
- {64, 5},
- {6, 4},
- {6, 4},
- {6, 4},
- {6, 4},
- {6, 4},
- {6, 4},
- {6, 4},
- {6, 4},
- {6, 4},
- {6, 4},
- {6, 4},
- {6, 4},
- {6, 4},
- {6, 4},
- {6, 4},
- {6, 4},
- {7, 4},
- {7, 4},
- {7, 4},
- {7, 4},
- {7, 4},
- {7, 4},
- {7, 4},
- {7, 4},
- {7, 4},
- {7, 4},
- {7, 4},
- {7, 4},
- {7, 4},
- {7, 4},
- {7, 4},
- {7, 4},
- {-2, 3},
- {-2, 3},
- {-1, 0},
- {-1, 0},
- {-1, 0},
- {-1, 0},
- {-1, 0},
- {-1, 0},
- {-1, 0},
- {-1, 0},
- {-1, 0},
- {-1, 0},
- {-1, 0},
- {-1, 0},
- {-1, 0},
- {-3, 4},
- {1792, 3},
- {1792, 3},
- {1984, 4},
- {2048, 4},
- {2112, 4},
- {2176, 4},
- {2240, 4},
- {2304, 4},
- {1856, 3},
- {1856, 3},
- {1920, 3},
- {1920, 3},
- {2368, 4},
- {2432, 4},
- {2496, 4},
- {2560, 4},
- {1472, 1},
- {1536, 1},
- {1600, 1},
- {1728, 1},
- {704, 1},
- {768, 1},
- {832, 1},
- {896, 1},
- {960, 1},
- {1024, 1},
- {1088, 1},
- {1152, 1},
- {1216, 1},
- {1280, 1},
- {1344, 1},
- {1408, 1}
+const cfd_node cf_white_decode[] = {
+ { 256, 12 },
+ { 272, 12 },
+ { 29, 8 },
+ { 30, 8 },
+ { 45, 8 },
+ { 46, 8 },
+ { 22, 7 },
+ { 22, 7 },
+ { 23, 7 },
+ { 23, 7 },
+ { 47, 8 },
+ { 48, 8 },
+ { 13, 6 },
+ { 13, 6 },
+ { 13, 6 },
+ { 13, 6 },
+ { 20, 7 },
+ { 20, 7 },
+ { 33, 8 },
+ { 34, 8 },
+ { 35, 8 },
+ { 36, 8 },
+ { 37, 8 },
+ { 38, 8 },
+ { 19, 7 },
+ { 19, 7 },
+ { 31, 8 },
+ { 32, 8 },
+ { 1, 6 },
+ { 1, 6 },
+ { 1, 6 },
+ { 1, 6 },
+ { 12, 6 },
+ { 12, 6 },
+ { 12, 6 },
+ { 12, 6 },
+ { 53, 8 },
+ { 54, 8 },
+ { 26, 7 },
+ { 26, 7 },
+ { 39, 8 },
+ { 40, 8 },
+ { 41, 8 },
+ { 42, 8 },
+ { 43, 8 },
+ { 44, 8 },
+ { 21, 7 },
+ { 21, 7 },
+ { 28, 7 },
+ { 28, 7 },
+ { 61, 8 },
+ { 62, 8 },
+ { 63, 8 },
+ { 0, 8 },
+ { 320, 8 },
+ { 384, 8 },
+ { 10, 5 },
+ { 10, 5 },
+ { 10, 5 },
+ { 10, 5 },
+ { 10, 5 },
+ { 10, 5 },
+ { 10, 5 },
+ { 10, 5 },
+ { 11, 5 },
+ { 11, 5 },
+ { 11, 5 },
+ { 11, 5 },
+ { 11, 5 },
+ { 11, 5 },
+ { 11, 5 },
+ { 11, 5 },
+ { 27, 7 },
+ { 27, 7 },
+ { 59, 8 },
+ { 60, 8 },
+ { 288, 9 },
+ { 290, 9 },
+ { 18, 7 },
+ { 18, 7 },
+ { 24, 7 },
+ { 24, 7 },
+ { 49, 8 },
+ { 50, 8 },
+ { 51, 8 },
+ { 52, 8 },
+ { 25, 7 },
+ { 25, 7 },
+ { 55, 8 },
+ { 56, 8 },
+ { 57, 8 },
+ { 58, 8 },
+ { 192, 6 },
+ { 192, 6 },
+ { 192, 6 },
+ { 192, 6 },
+ { 1664, 6 },
+ { 1664, 6 },
+ { 1664, 6 },
+ { 1664, 6 },
+ { 448, 8 },
+ { 512, 8 },
+ { 292, 9 },
+ { 640, 8 },
+ { 576, 8 },
+ { 294, 9 },
+ { 296, 9 },
+ { 298, 9 },
+ { 300, 9 },
+ { 302, 9 },
+ { 256, 7 },
+ { 256, 7 },
+ { 2, 4 },
+ { 2, 4 },
+ { 2, 4 },
+ { 2, 4 },
+ { 2, 4 },
+ { 2, 4 },
+ { 2, 4 },
+ { 2, 4 },
+ { 2, 4 },
+ { 2, 4 },
+ { 2, 4 },
+ { 2, 4 },
+ { 2, 4 },
+ { 2, 4 },
+ { 2, 4 },
+ { 2, 4 },
+ { 3, 4 },
+ { 3, 4 },
+ { 3, 4 },
+ { 3, 4 },
+ { 3, 4 },
+ { 3, 4 },
+ { 3, 4 },
+ { 3, 4 },
+ { 3, 4 },
+ { 3, 4 },
+ { 3, 4 },
+ { 3, 4 },
+ { 3, 4 },
+ { 3, 4 },
+ { 3, 4 },
+ { 3, 4 },
+ { 128, 5 },
+ { 128, 5 },
+ { 128, 5 },
+ { 128, 5 },
+ { 128, 5 },
+ { 128, 5 },
+ { 128, 5 },
+ { 128, 5 },
+ { 8, 5 },
+ { 8, 5 },
+ { 8, 5 },
+ { 8, 5 },
+ { 8, 5 },
+ { 8, 5 },
+ { 8, 5 },
+ { 8, 5 },
+ { 9, 5 },
+ { 9, 5 },
+ { 9, 5 },
+ { 9, 5 },
+ { 9, 5 },
+ { 9, 5 },
+ { 9, 5 },
+ { 9, 5 },
+ { 16, 6 },
+ { 16, 6 },
+ { 16, 6 },
+ { 16, 6 },
+ { 17, 6 },
+ { 17, 6 },
+ { 17, 6 },
+ { 17, 6 },
+ { 4, 4 },
+ { 4, 4 },
+ { 4, 4 },
+ { 4, 4 },
+ { 4, 4 },
+ { 4, 4 },
+ { 4, 4 },
+ { 4, 4 },
+ { 4, 4 },
+ { 4, 4 },
+ { 4, 4 },
+ { 4, 4 },
+ { 4, 4 },
+ { 4, 4 },
+ { 4, 4 },
+ { 4, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 14, 6 },
+ { 14, 6 },
+ { 14, 6 },
+ { 14, 6 },
+ { 15, 6 },
+ { 15, 6 },
+ { 15, 6 },
+ { 15, 6 },
+ { 64, 5 },
+ { 64, 5 },
+ { 64, 5 },
+ { 64, 5 },
+ { 64, 5 },
+ { 64, 5 },
+ { 64, 5 },
+ { 64, 5 },
+ { 6, 4 },
+ { 6, 4 },
+ { 6, 4 },
+ { 6, 4 },
+ { 6, 4 },
+ { 6, 4 },
+ { 6, 4 },
+ { 6, 4 },
+ { 6, 4 },
+ { 6, 4 },
+ { 6, 4 },
+ { 6, 4 },
+ { 6, 4 },
+ { 6, 4 },
+ { 6, 4 },
+ { 6, 4 },
+ { 7, 4 },
+ { 7, 4 },
+ { 7, 4 },
+ { 7, 4 },
+ { 7, 4 },
+ { 7, 4 },
+ { 7, 4 },
+ { 7, 4 },
+ { 7, 4 },
+ { 7, 4 },
+ { 7, 4 },
+ { 7, 4 },
+ { 7, 4 },
+ { 7, 4 },
+ { 7, 4 },
+ { 7, 4 },
+ { -2, 3 },
+ { -2, 3 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -3, 4 },
+ { 1792, 3 },
+ { 1792, 3 },
+ { 1984, 4 },
+ { 2048, 4 },
+ { 2112, 4 },
+ { 2176, 4 },
+ { 2240, 4 },
+ { 2304, 4 },
+ { 1856, 3 },
+ { 1856, 3 },
+ { 1920, 3 },
+ { 1920, 3 },
+ { 2368, 4 },
+ { 2432, 4 },
+ { 2496, 4 },
+ { 2560, 4 },
+ { 1472, 1 },
+ { 1536, 1 },
+ { 1600, 1 },
+ { 1728, 1 },
+ { 704, 1 },
+ { 768, 1 },
+ { 832, 1 },
+ { 896, 1 },
+ { 960, 1 },
+ { 1024, 1 },
+ { 1088, 1 },
+ { 1152, 1 },
+ { 1216, 1 },
+ { 1280, 1 },
+ { 1344, 1 },
+ { 1408, 1 }
};
/* Black decoding table. */
-const cfd_node cf_black_decode[] =
-{
- {128, 12},
- {160, 13},
- {224, 12},
- {256, 12},
- {10, 7},
- {11, 7},
- {288, 12},
- {12, 7},
- {9, 6},
- {9, 6},
- {8, 6},
- {8, 6},
- {7, 5},
- {7, 5},
- {7, 5},
- {7, 5},
- {6, 4},
- {6, 4},
- {6, 4},
- {6, 4},
- {6, 4},
- {6, 4},
- {6, 4},
- {6, 4},
- {5, 4},
- {5, 4},
- {5, 4},
- {5, 4},
- {5, 4},
- {5, 4},
- {5, 4},
- {5, 4},
- {1, 3},
- {1, 3},
- {1, 3},
- {1, 3},
- {1, 3},
- {1, 3},
- {1, 3},
- {1, 3},
- {1, 3},
- {1, 3},
- {1, 3},
- {1, 3},
- {1, 3},
- {1, 3},
- {1, 3},
- {1, 3},
- {4, 3},
- {4, 3},
- {4, 3},
- {4, 3},
- {4, 3},
- {4, 3},
- {4, 3},
- {4, 3},
- {4, 3},
- {4, 3},
- {4, 3},
- {4, 3},
- {4, 3},
- {4, 3},
- {4, 3},
- {4, 3},
- {3, 2},
- {3, 2},
- {3, 2},
- {3, 2},
- {3, 2},
- {3, 2},
- {3, 2},
- {3, 2},
- {3, 2},
- {3, 2},
- {3, 2},
- {3, 2},
- {3, 2},
- {3, 2},
- {3, 2},
- {3, 2},
- {3, 2},
- {3, 2},
- {3, 2},
- {3, 2},
- {3, 2},
- {3, 2},
- {3, 2},
- {3, 2},
- {3, 2},
- {3, 2},
- {3, 2},
- {3, 2},
- {3, 2},
- {3, 2},
- {3, 2},
- {3, 2},
- {2, 2},
- {2, 2},
- {2, 2},
- {2, 2},
- {2, 2},
- {2, 2},
- {2, 2},
- {2, 2},
- {2, 2},
- {2, 2},
- {2, 2},
- {2, 2},
- {2, 2},
- {2, 2},
- {2, 2},
- {2, 2},
- {2, 2},
- {2, 2},
- {2, 2},
- {2, 2},
- {2, 2},
- {2, 2},
- {2, 2},
- {2, 2},
- {2, 2},
- {2, 2},
- {2, 2},
- {2, 2},
- {2, 2},
- {2, 2},
- {2, 2},
- {2, 2},
- {-2, 4},
- {-2, 4},
- {-1, 0},
- {-1, 0},
- {-1, 0},
- {-1, 0},
- {-1, 0},
- {-1, 0},
- {-1, 0},
- {-1, 0},
- {-1, 0},
- {-1, 0},
- {-1, 0},
- {-1, 0},
- {-1, 0},
- {-3, 5},
- {1792, 4},
- {1792, 4},
- {1984, 5},
- {2048, 5},
- {2112, 5},
- {2176, 5},
- {2240, 5},
- {2304, 5},
- {1856, 4},
- {1856, 4},
- {1920, 4},
- {1920, 4},
- {2368, 5},
- {2432, 5},
- {2496, 5},
- {2560, 5},
- {18, 3},
- {18, 3},
- {18, 3},
- {18, 3},
- {18, 3},
- {18, 3},
- {18, 3},
- {18, 3},
- {52, 5},
- {52, 5},
- {640, 6},
- {704, 6},
- {768, 6},
- {832, 6},
- {55, 5},
- {55, 5},
- {56, 5},
- {56, 5},
- {1280, 6},
- {1344, 6},
- {1408, 6},
- {1472, 6},
- {59, 5},
- {59, 5},
- {60, 5},
- {60, 5},
- {1536, 6},
- {1600, 6},
- {24, 4},
- {24, 4},
- {24, 4},
- {24, 4},
- {25, 4},
- {25, 4},
- {25, 4},
- {25, 4},
- {1664, 6},
- {1728, 6},
- {320, 5},
- {320, 5},
- {384, 5},
- {384, 5},
- {448, 5},
- {448, 5},
- {512, 6},
- {576, 6},
- {53, 5},
- {53, 5},
- {54, 5},
- {54, 5},
- {896, 6},
- {960, 6},
- {1024, 6},
- {1088, 6},
- {1152, 6},
- {1216, 6},
- {64, 3},
- {64, 3},
- {64, 3},
- {64, 3},
- {64, 3},
- {64, 3},
- {64, 3},
- {64, 3},
- {13, 1},
- {13, 1},
- {13, 1},
- {13, 1},
- {13, 1},
- {13, 1},
- {13, 1},
- {13, 1},
- {13, 1},
- {13, 1},
- {13, 1},
- {13, 1},
- {13, 1},
- {13, 1},
- {13, 1},
- {13, 1},
- {23, 4},
- {23, 4},
- {50, 5},
- {51, 5},
- {44, 5},
- {45, 5},
- {46, 5},
- {47, 5},
- {57, 5},
- {58, 5},
- {61, 5},
- {256, 5},
- {16, 3},
- {16, 3},
- {16, 3},
- {16, 3},
- {17, 3},
- {17, 3},
- {17, 3},
- {17, 3},
- {48, 5},
- {49, 5},
- {62, 5},
- {63, 5},
- {30, 5},
- {31, 5},
- {32, 5},
- {33, 5},
- {40, 5},
- {41, 5},
- {22, 4},
- {22, 4},
- {14, 1},
- {14, 1},
- {14, 1},
- {14, 1},
- {14, 1},
- {14, 1},
- {14, 1},
- {14, 1},
- {14, 1},
- {14, 1},
- {14, 1},
- {14, 1},
- {14, 1},
- {14, 1},
- {14, 1},
- {14, 1},
- {15, 2},
- {15, 2},
- {15, 2},
- {15, 2},
- {15, 2},
- {15, 2},
- {15, 2},
- {15, 2},
- {128, 5},
- {192, 5},
- {26, 5},
- {27, 5},
- {28, 5},
- {29, 5},
- {19, 4},
- {19, 4},
- {20, 4},
- {20, 4},
- {34, 5},
- {35, 5},
- {36, 5},
- {37, 5},
- {38, 5},
- {39, 5},
- {21, 4},
- {21, 4},
- {42, 5},
- {43, 5},
- {0, 3},
- {0, 3},
- {0, 3},
- {0, 3}
+const cfd_node cf_black_decode[] = {
+ { 128, 12 },
+ { 160, 13 },
+ { 224, 12 },
+ { 256, 12 },
+ { 10, 7 },
+ { 11, 7 },
+ { 288, 12 },
+ { 12, 7 },
+ { 9, 6 },
+ { 9, 6 },
+ { 8, 6 },
+ { 8, 6 },
+ { 7, 5 },
+ { 7, 5 },
+ { 7, 5 },
+ { 7, 5 },
+ { 6, 4 },
+ { 6, 4 },
+ { 6, 4 },
+ { 6, 4 },
+ { 6, 4 },
+ { 6, 4 },
+ { 6, 4 },
+ { 6, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 1, 3 },
+ { 1, 3 },
+ { 1, 3 },
+ { 1, 3 },
+ { 1, 3 },
+ { 1, 3 },
+ { 1, 3 },
+ { 1, 3 },
+ { 1, 3 },
+ { 1, 3 },
+ { 1, 3 },
+ { 1, 3 },
+ { 1, 3 },
+ { 1, 3 },
+ { 1, 3 },
+ { 1, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { -2, 4 },
+ { -2, 4 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -3, 5 },
+ { 1792, 4 },
+ { 1792, 4 },
+ { 1984, 5 },
+ { 2048, 5 },
+ { 2112, 5 },
+ { 2176, 5 },
+ { 2240, 5 },
+ { 2304, 5 },
+ { 1856, 4 },
+ { 1856, 4 },
+ { 1920, 4 },
+ { 1920, 4 },
+ { 2368, 5 },
+ { 2432, 5 },
+ { 2496, 5 },
+ { 2560, 5 },
+ { 18, 3 },
+ { 18, 3 },
+ { 18, 3 },
+ { 18, 3 },
+ { 18, 3 },
+ { 18, 3 },
+ { 18, 3 },
+ { 18, 3 },
+ { 52, 5 },
+ { 52, 5 },
+ { 640, 6 },
+ { 704, 6 },
+ { 768, 6 },
+ { 832, 6 },
+ { 55, 5 },
+ { 55, 5 },
+ { 56, 5 },
+ { 56, 5 },
+ { 1280, 6 },
+ { 1344, 6 },
+ { 1408, 6 },
+ { 1472, 6 },
+ { 59, 5 },
+ { 59, 5 },
+ { 60, 5 },
+ { 60, 5 },
+ { 1536, 6 },
+ { 1600, 6 },
+ { 24, 4 },
+ { 24, 4 },
+ { 24, 4 },
+ { 24, 4 },
+ { 25, 4 },
+ { 25, 4 },
+ { 25, 4 },
+ { 25, 4 },
+ { 1664, 6 },
+ { 1728, 6 },
+ { 320, 5 },
+ { 320, 5 },
+ { 384, 5 },
+ { 384, 5 },
+ { 448, 5 },
+ { 448, 5 },
+ { 512, 6 },
+ { 576, 6 },
+ { 53, 5 },
+ { 53, 5 },
+ { 54, 5 },
+ { 54, 5 },
+ { 896, 6 },
+ { 960, 6 },
+ { 1024, 6 },
+ { 1088, 6 },
+ { 1152, 6 },
+ { 1216, 6 },
+ { 64, 3 },
+ { 64, 3 },
+ { 64, 3 },
+ { 64, 3 },
+ { 64, 3 },
+ { 64, 3 },
+ { 64, 3 },
+ { 64, 3 },
+ { 13, 1 },
+ { 13, 1 },
+ { 13, 1 },
+ { 13, 1 },
+ { 13, 1 },
+ { 13, 1 },
+ { 13, 1 },
+ { 13, 1 },
+ { 13, 1 },
+ { 13, 1 },
+ { 13, 1 },
+ { 13, 1 },
+ { 13, 1 },
+ { 13, 1 },
+ { 13, 1 },
+ { 13, 1 },
+ { 23, 4 },
+ { 23, 4 },
+ { 50, 5 },
+ { 51, 5 },
+ { 44, 5 },
+ { 45, 5 },
+ { 46, 5 },
+ { 47, 5 },
+ { 57, 5 },
+ { 58, 5 },
+ { 61, 5 },
+ { 256, 5 },
+ { 16, 3 },
+ { 16, 3 },
+ { 16, 3 },
+ { 16, 3 },
+ { 17, 3 },
+ { 17, 3 },
+ { 17, 3 },
+ { 17, 3 },
+ { 48, 5 },
+ { 49, 5 },
+ { 62, 5 },
+ { 63, 5 },
+ { 30, 5 },
+ { 31, 5 },
+ { 32, 5 },
+ { 33, 5 },
+ { 40, 5 },
+ { 41, 5 },
+ { 22, 4 },
+ { 22, 4 },
+ { 14, 1 },
+ { 14, 1 },
+ { 14, 1 },
+ { 14, 1 },
+ { 14, 1 },
+ { 14, 1 },
+ { 14, 1 },
+ { 14, 1 },
+ { 14, 1 },
+ { 14, 1 },
+ { 14, 1 },
+ { 14, 1 },
+ { 14, 1 },
+ { 14, 1 },
+ { 14, 1 },
+ { 14, 1 },
+ { 15, 2 },
+ { 15, 2 },
+ { 15, 2 },
+ { 15, 2 },
+ { 15, 2 },
+ { 15, 2 },
+ { 15, 2 },
+ { 15, 2 },
+ { 128, 5 },
+ { 192, 5 },
+ { 26, 5 },
+ { 27, 5 },
+ { 28, 5 },
+ { 29, 5 },
+ { 19, 4 },
+ { 19, 4 },
+ { 20, 4 },
+ { 20, 4 },
+ { 34, 5 },
+ { 35, 5 },
+ { 36, 5 },
+ { 37, 5 },
+ { 38, 5 },
+ { 39, 5 },
+ { 21, 4 },
+ { 21, 4 },
+ { 42, 5 },
+ { 43, 5 },
+ { 0, 3 },
+ { 0, 3 },
+ { 0, 3 },
+ { 0, 3 }
};
/* 2-D decoding table. */
-const cfd_node cf_2d_decode[] =
-{
- {128, 11},
- {144, 10},
- {6, 7},
- {0, 7},
- {5, 6},
- {5, 6},
- {1, 6},
- {1, 6},
- {-4, 4},
- {-4, 4},
- {-4, 4},
- {-4, 4},
- {-4, 4},
- {-4, 4},
- {-4, 4},
- {-4, 4},
- {-5, 3},
- {-5, 3},
- {-5, 3},
- {-5, 3},
- {-5, 3},
- {-5, 3},
- {-5, 3},
- {-5, 3},
- {-5, 3},
- {-5, 3},
- {-5, 3},
- {-5, 3},
- {-5, 3},
- {-5, 3},
- {-5, 3},
- {-5, 3},
- {4, 3},
- {4, 3},
- {4, 3},
- {4, 3},
- {4, 3},
- {4, 3},
- {4, 3},
- {4, 3},
- {4, 3},
- {4, 3},
- {4, 3},
- {4, 3},
- {4, 3},
- {4, 3},
- {4, 3},
- {4, 3},
- {2, 3},
- {2, 3},
- {2, 3},
- {2, 3},
- {2, 3},
- {2, 3},
- {2, 3},
- {2, 3},
- {2, 3},
- {2, 3},
- {2, 3},
- {2, 3},
- {2, 3},
- {2, 3},
- {2, 3},
- {2, 3},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {3, 1},
- {-2, 4},
- {-1, 0},
- {-1, 0},
- {-1, 0},
- {-1, 0},
- {-1, 0},
- {-1, 0},
- {-1, 0},
- {-1, 0},
- {-1, 0},
- {-1, 0},
- {-1, 0},
- {-1, 0},
- {-1, 0},
- {-1, 0},
- {-1, 0},
- {-1, 0},
- {-1, 0},
- {-1, 0},
- {-1, 0},
- {-1, 0},
- {-1, 0},
- {-1, 0},
- {-3, 3}
+const cfd_node cf_2d_decode[] = {
+ { 128, 11 },
+ { 144, 10 },
+ { 6, 7 },
+ { 0, 7 },
+ { 5, 6 },
+ { 5, 6 },
+ { 1, 6 },
+ { 1, 6 },
+ { -4, 4 },
+ { -4, 4 },
+ { -4, 4 },
+ { -4, 4 },
+ { -4, 4 },
+ { -4, 4 },
+ { -4, 4 },
+ { -4, 4 },
+ { -5, 3 },
+ { -5, 3 },
+ { -5, 3 },
+ { -5, 3 },
+ { -5, 3 },
+ { -5, 3 },
+ { -5, 3 },
+ { -5, 3 },
+ { -5, 3 },
+ { -5, 3 },
+ { -5, 3 },
+ { -5, 3 },
+ { -5, 3 },
+ { -5, 3 },
+ { -5, 3 },
+ { -5, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { -2, 4 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -3, 3 }
};
/* Uncompresssed decoding table. */
-const cfd_node cf_uncompressed_decode[] =
-{
- {64, 12},
- {5, 6},
- {4, 5},
- {4, 5},
- {3, 4},
- {3, 4},
- {3, 4},
- {3, 4},
- {2, 3},
- {2, 3},
- {2, 3},
- {2, 3},
- {2, 3},
- {2, 3},
- {2, 3},
- {2, 3},
- {1, 2},
- {1, 2},
- {1, 2},
- {1, 2},
- {1, 2},
- {1, 2},
- {1, 2},
- {1, 2},
- {1, 2},
- {1, 2},
- {1, 2},
- {1, 2},
- {1, 2},
- {1, 2},
- {1, 2},
- {1, 2},
- {0, 1},
- {0, 1},
- {0, 1},
- {0, 1},
- {0, 1},
- {0, 1},
- {0, 1},
- {0, 1},
- {0, 1},
- {0, 1},
- {0, 1},
- {0, 1},
- {0, 1},
- {0, 1},
- {0, 1},
- {0, 1},
- {0, 1},
- {0, 1},
- {0, 1},
- {0, 1},
- {0, 1},
- {0, 1},
- {0, 1},
- {0, 1},
- {0, 1},
- {0, 1},
- {0, 1},
- {0, 1},
- {0, 1},
- {0, 1},
- {0, 1},
- {0, 1},
- {-1, 0},
- {-1, 0},
- {8, 6},
- {9, 6},
- {6, 5},
- {6, 5},
- {7, 5},
- {7, 5},
- {4, 4},
- {4, 4},
- {4, 4},
- {4, 4},
- {5, 4},
- {5, 4},
- {5, 4},
- {5, 4},
- {2, 3},
- {2, 3},
- {2, 3},
- {2, 3},
- {2, 3},
- {2, 3},
- {2, 3},
- {2, 3},
- {3, 3},
- {3, 3},
- {3, 3},
- {3, 3},
- {3, 3},
- {3, 3},
- {3, 3},
- {3, 3},
- {0, 2},
- {0, 2},
- {0, 2},
- {0, 2},
- {0, 2},
- {0, 2},
- {0, 2},
- {0, 2},
- {0, 2},
- {0, 2},
- {0, 2},
- {0, 2},
- {0, 2},
- {0, 2},
- {0, 2},
- {0, 2},
- {1, 2},
- {1, 2},
- {1, 2},
- {1, 2},
- {1, 2},
- {1, 2},
- {1, 2},
- {1, 2},
- {1, 2},
- {1, 2},
- {1, 2},
- {1, 2},
- {1, 2},
- {1, 2},
- {1, 2},
- {1, 2}
+const cfd_node cf_uncompressed_decode[] = {
+ { 64, 12 },
+ { 5, 6 },
+ { 4, 5 },
+ { 4, 5 },
+ { 3, 4 },
+ { 3, 4 },
+ { 3, 4 },
+ { 3, 4 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { -1, 0 },
+ { -1, 0 },
+ { 8, 6 },
+ { 9, 6 },
+ { 6, 5 },
+ { 6, 5 },
+ { 7, 5 },
+ { 7, 5 },
+ { 4, 4 },
+ { 4, 4 },
+ { 4, 4 },
+ { 4, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 3, 3 },
+ { 3, 3 },
+ { 3, 3 },
+ { 3, 3 },
+ { 3, 3 },
+ { 3, 3 },
+ { 3, 3 },
+ { 3, 3 },
+ { 0, 2 },
+ { 0, 2 },
+ { 0, 2 },
+ { 0, 2 },
+ { 0, 2 },
+ { 0, 2 },
+ { 0, 2 },
+ { 0, 2 },
+ { 0, 2 },
+ { 0, 2 },
+ { 0, 2 },
+ { 0, 2 },
+ { 0, 2 },
+ { 0, 2 },
+ { 0, 2 },
+ { 0, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 }
};
/* Dummy executable code to pacify compilers. */
+void scfdtab_dummy(P0());
void
-cfd_dummy(void)
+scfdtab_dummy()
{
}
diff --git a/gs/src/scfetab.c b/gs/src/scfetab.c
index 21adc6384..3fb419bc9 100644
--- a/gs/src/scfetab.c
+++ b/gs/src/scfetab.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1992, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1992, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -158,7 +158,8 @@ const cfe_run cf_uncompressed_exit[10] =
};
/* Some C compilers insist on having executable code in every file.... */
+void scfetab_dummy(P0()); /* for picky compilers */
void
-cfe_dummy(void)
+scfetab_dummy(void)
{
}
diff --git a/gs/src/scfx.h b/gs/src/scfx.h
index abf7ada32..0957a2abf 100644
--- a/gs/src/scfx.h
+++ b/gs/src/scfx.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1995, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1993, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -66,7 +66,9 @@ typedef struct stream_CF_state_s {
(ss)->DamagedRowsBeforeError = 0, /* always set, for s_CF_get_params */\
(ss)->FirstBitLowOrder = false,\
/* Added by us */\
- (ss)->DecodedByteAlign = 1)
+ (ss)->DecodedByteAlign = 1,\
+ /* Clear pointers */\
+ (ss)->lbuf = 0, (ss)->lprev = 0)
/* CCITTFaxEncode */
typedef struct stream_CFE_state_s {
@@ -84,7 +86,7 @@ typedef struct stream_CFE_state_s {
gs_private_st_ptrs3(st_CFE_state, stream_CFE_state, "CCITTFaxEncode state",\
cfe_enum_ptrs, cfe_reloc_ptrs, lbuf, lprev, lcode)
#define s_CFE_set_defaults_inline(ss)\
- s_CF_set_defaults_inline(ss)
+ (s_CF_set_defaults_inline(ss), (ss)->lcode = 0)
extern const stream_template s_CFE_template;
/* CCITTFaxDecode */
diff --git a/gs/src/sdct.h b/gs/src/sdct.h
index 47bd17166..5aff8eb3a 100644
--- a/gs/src/sdct.h
+++ b/gs/src/sdct.h
@@ -54,6 +54,8 @@ typedef struct jpeg_compress_data_s {
/* cinfo must immediately follow the common fields */
struct jpeg_compress_struct cinfo;
struct jpeg_destination_mgr destination;
+ byte finish_compress_buf[100];
+ int fcb_size, fcb_pos;
} jpeg_compress_data;
typedef struct jpeg_decompress_data_s {
diff --git a/gs/src/sdctc.c b/gs/src/sdctc.c
index 3b96f2b38..c912e9f19 100644
--- a/gs/src/sdctc.c
+++ b/gs/src/sdctc.c
@@ -41,4 +41,7 @@ s_DCT_set_defaults(stream_state * st)
****************/
ss->ColorTransform = -1;
ss->QFactor = 1.0;
+ /* Clear pointers */
+ ss->Markers.data = 0;
+ ss->Markers.size = 0;
}
diff --git a/gs/src/sdcte.c b/gs/src/sdcte.c
index afb91f327..6fa0bc358 100644
--- a/gs/src/sdcte.c
+++ b/gs/src/sdcte.c
@@ -155,17 +155,30 @@ s_DCTE_process(stream_state * st, stream_cursor_read * pr,
ss->phase = 4;
/* falls through */
case 4: /* all data processed, finishing */
- /* jpeg_finish_compress can't suspend, so make sure
- * it has plenty of room to write the last few bytes.
+ /* jpeg_finish_compress can't suspend, so write its output
+ * to a fixed-size internal buffer.
*/
- if (pw->limit - pw->ptr < 100)
- return 1;
+ dest->next_output_byte = jcdp->finish_compress_buf;
+ dest->free_in_buffer = sizeof(jcdp->finish_compress_buf);
if (gs_jpeg_finish_compress(ss) < 0)
return ERRC;
- pw->ptr = dest->next_output_byte - 1;
+ jcdp->fcb_size =
+ dest->next_output_byte - jcdp->finish_compress_buf;
+ jcdp->fcb_pos = 0;
ss->phase = 5;
/* falls through */
- case 5: /* we are DONE */
+ case 5: /* copy the final data to the output */
+ if (jcdp->fcb_pos < jcdp->fcb_size) {
+ int count = min(jcdp->fcb_size - jcdp->fcb_pos,
+ pw->limit - pw->ptr);
+
+ memcpy(pw->ptr + 1, jcdp->finish_compress_buf + jcdp->fcb_pos,
+ count);
+ jcdp->fcb_pos += count;
+ pw->ptr += count;
+ if (jcdp->fcb_pos < jcdp->fcb_size)
+ return 1;
+ }
return EOFC;
}
/* Default case can't happen.... */
diff --git a/gs/src/seexec.c b/gs/src/seexec.c
index 5ef6f5adb..147a30958 100644
--- a/gs/src/seexec.c
+++ b/gs/src/seexec.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1994, 1997, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1994, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -71,6 +71,8 @@ s_exD_set_defaults(stream_state * st)
stream_exD_state *const ss = (stream_exD_state *) st;
ss->lenIV = 4;
+ /* Clear pointers for GC */
+ ss->pfb_state = 0;
}
/* Initialize the state for reading and decrypting. */
diff --git a/gs/src/sfilter1.c b/gs/src/sfilter1.c
index 2f4468a47..842207faa 100644
--- a/gs/src/sfilter1.c
+++ b/gs/src/sfilter1.c
@@ -167,6 +167,16 @@ const stream_template s_PFBD_template = {
private_st_SFD_state();
+/* Set default parameter values (actually, just clear pointers). */
+private void
+s_SFD_set_defaults(stream_state * st)
+{
+ stream_SFD_state *const ss = (stream_SFD_state *) st;
+
+ ss->eod.data = 0;
+ ss->eod.size = 0;
+}
+
/* Initialize the stream */
private int
s_SFD_init(stream_state * st)
@@ -293,5 +303,5 @@ xit: pr->ptr = p;
/* Stream template */
const stream_template s_SFD_template = {
- &st_SFD_state, s_SFD_init, s_SFD_process, 1, 1
+ &st_SFD_state, s_SFD_init, s_SFD_process, 1, 1, 0, s_SFD_set_defaults
};
diff --git a/gs/src/sfilter2.c b/gs/src/sfilter2.c
index 676246e2c..e3636d791 100644
--- a/gs/src/sfilter2.c
+++ b/gs/src/sfilter2.c
@@ -20,6 +20,7 @@
/* Simple Level 2 filters */
#include "stdio_.h" /* includes std.h */
#include "memory_.h"
+#include "gdebug.h"
#include "strimpl.h"
#include "sa85x.h"
#include "sbtx.h"
@@ -39,7 +40,7 @@ s_A85E_init(stream_state * st)
}
/* Process a buffer */
-#define LINE_LIMIT 80
+#define LINE_LIMIT 79 /* not 80, to satisfy Genoa FTS */
private int
s_A85E_process(stream_state * st, stream_cursor_read * pr,
stream_cursor_write * pw, bool last)
@@ -47,21 +48,34 @@ s_A85E_process(stream_state * st, stream_cursor_read * pr,
stream_A85E_state *const ss = (stream_A85E_state *) st;
register const byte *p = pr->ptr;
register byte *q = pw->ptr;
- byte *qn = q + (LINE_LIMIT - ss->count);
+ byte *qn = q + (LINE_LIMIT - ss->count); /* value of q before next EOL */
const byte *rlimit = pr->limit;
byte *wlimit = pw->limit;
int status = 0;
int count;
+ if_debug3('w', "[w85]initial ss->count = %d, rcount = %d, wcount = %d\n",
+ ss->count, (int)(rlimit - p), (int)(wlimit - q));
for (; (count = rlimit - p) >= 4; p += 4) {
ulong word =
((ulong) (((uint) p[1] << 8) + p[2]) << 16) +
(((uint) p[3] << 8) + p[4]);
if (word == 0) {
- if (wlimit - q < 2) {
- status = 1;
- break;
+ if (q >= qn) {
+ if (wlimit - q < 2) {
+ status = 1;
+ break;
+ }
+ *++q = '\n';
+ qn = q + LINE_LIMIT;
+ if_debug1('w', "[w85]EOL at %d bytes written\n",
+ (int)(q - pw->ptr));
+ } else {
+ if (q >= wlimit) {
+ status = 1;
+ break;
+ }
}
*++q = 'z';
} else {
@@ -70,7 +84,18 @@ s_A85E_process(stream_state * st, stream_cursor_read * pr,
uint v2 = v3 / 85; /* max 85^2 */
uint v1 = v2 / 85; /* max 85 */
-put: if (wlimit - q < 6) {
+put: if (q + 5 > qn) {
+ if (q >= wlimit) {
+ status = 1;
+ break;
+ }
+ *++q = '\n';
+ qn = q + LINE_LIMIT;
+ if_debug1('w', "[w85]EOL at %d bytes written\n",
+ (int)(q - pw->ptr));
+ goto put;
+ }
+ if (wlimit - q < 5) {
status = 1;
break;
}
@@ -93,6 +118,8 @@ put: if (wlimit - q < 6) {
*/
*++q = '\n';
qn = q + LINE_LIMIT;
+ if_debug1('w', "[w85]EOL at %d bytes written\n",
+ (int)(q - pw->ptr));
goto put;
}
if (q[2] == '%' && *q == '\n') {
@@ -101,10 +128,10 @@ put: if (wlimit - q < 6) {
* there are more than two %s in a row.
*/
int extra =
- (q[3] != '%' ? 1 : q[4] != '%' ? 2 :
- q[5] != '%' ? 3 : 4);
+ (q[3] != '%' ? 1 : q[4] != '%' ? 2 :
+ q[5] != '%' ? 3 : 4);
- if (wlimit - q < 6 + extra) {
+ if (wlimit - q < 5 + extra) {
status = 1;
break;
}
@@ -124,22 +151,28 @@ put: if (wlimit - q < 6) {
q[6] = q[5], q[5] = q[4], q[4] = q[3];
e1:q[3] = '%', q[2] = '\n';
}
+ if_debug1('w', "[w85]EOL at %d bytes written\n",
+ (int)(q + 2 * extra - pw->ptr));
+ qn = q + 2 * extra + LINE_LIMIT;
q += extra;
- qn = q + (5 + LINE_LIMIT);
}
}
q += 5;
}
- if (q >= qn) {
- *++q = '\n';
- qn = q + LINE_LIMIT;
- }
}
+ end:
ss->count = LINE_LIMIT - (qn - q);
/* Check for final partial word. */
if (last && status == 0 && count < 4) {
- if (wlimit - q < (count == 0 ? 2 : count + 3))
+ int nchars = (count == 0 ? 2 : count + 3);
+
+ if (wlimit - q < nchars)
status = 1;
+ else if (q + nchars > qn) {
+ *++q = '\n';
+ qn = q + LINE_LIMIT;
+ goto end;
+ }
else {
ulong word = 0;
ulong divisor = 85L * 85 * 85 * 85;
@@ -153,7 +186,7 @@ put: if (wlimit - q < 6) {
word += (ulong) p[1] << 24;
p += count;
while (count-- >= 0) {
- ulong v = word / divisor; /* actually only a byte */
+ ulong v = word / divisor; /* actually only a byte */
*++q = (byte) v + '!';
word -= v * divisor;
@@ -165,6 +198,8 @@ put: if (wlimit - q < 6) {
*++q = '>';
}
}
+ if_debug3('w', "[w85]final ss->count = %d, %d bytes read, %d written\n",
+ ss->count, (int)(p - pr->ptr), (int)(q - pw->ptr));
pr->ptr = p;
pw->ptr = q;
return status;
diff --git a/gs/src/shc.h b/gs/src/shc.h
index abb709197..11eeb75b8 100644
--- a/gs/src/shc.h
+++ b/gs/src/shc.h
@@ -212,37 +212,47 @@ typedef struct hcd_table_s {
#define hcd_bits_available(n)\
(bits_left >= (n) || rlimit - p > ((n) - bits_left - 1) >> 3)
/* For hcd_ensure_bits, n must not be greater than 8. */
+#define HCD_ENSURE_BITS_ELSE(n)\
+ if (bits_left >= n)\
+ DO_NOTHING;\
+ else HCD_MORE_BITS_ELSE
#define hcd_ensure_bits(n, outl)\
- if ( bits_left < n ) hcd_more_bits(outl)
+ BEGIN HCD_ENSURE_BITS_ELSE(n) goto outl; END
/* Load more bits into the buffer. */
-#define hcd_more_bits_1(outl)\
- { int c;\
- if ( p < rlimit ) c = *++p;\
- else goto outl;\
- if ( ss->FirstBitLowOrder ) c = byte_reverse_bits[c];\
+#define HCD_MORE_BITS_1_ELSE\
+ if (p < rlimit) {\
+ int c = *++p;\
+\
+ if (ss->FirstBitLowOrder)\
+ c = byte_reverse_bits[c];\
bits = (bits << 8) + c, bits_left += 8;\
- }
+ } else
#if hc_bits_size == 16
-# define hcd_more_bits(outl) hcd_more_bits_1(outl)
+# define HCD_MORE_BITS_ELSE HCD_MORE_BITS_1_ELSE
#else /* hc_bits_size >= 32 */
-# define hcd_more_bits(outl)\
- { if ( rlimit - p < 3 ) hcd_more_bits_1(outl)\
+# define HCD_MORE_BITS_ELSE\
+ if (rlimit - p >= 3) {\
+ if (ss->FirstBitLowOrder)\
+ bits = (bits << 24) + ((uint)byte_reverse_bits[p[1]] << 16) + ((uint)byte_reverse_bits[p[2]] << 8) + byte_reverse_bits[p[3]];\
else\
- { if ( ss->FirstBitLowOrder )\
- bits = (bits << 24) + ((uint)byte_reverse_bits[p[1]] << 16) + ((uint)byte_reverse_bits[p[2]] << 8) + byte_reverse_bits[p[3]];\
- else\
- bits = (bits << 24) + ((uint)p[1] << 16) + ((uint)p[2] << 8) + p[3];\
- bits_left += 24, p += 3;\
- }\
- }
+ bits = (bits << 24) + ((uint)p[1] << 16) + ((uint)p[2] << 8) + p[3];\
+ bits_left += 24, p += 3;\
+ } else HCD_MORE_BITS_1_ELSE
#endif
+#define hcd_more_bits(outl)\
+ BEGIN HCD_MORE_BITS_ELSE goto outl; END
#define hcd_peek_bits(n) ((bits >> (bits_left - (n))) & ((1 << (n)) - 1))
+/* hcd_peek_var_bits requires bits_left <= 8. */
#define hcd_peek_var_bits(n)\
((bits >> (bits_left - (n))) & byte_right_mask[n])
+/* hcd_peek_bits_left requires bits_left <= 8. */
+#define hcd_peek_bits_left()\
+ (bits & byte_right_mask[bits_left])
+
#define hcd_skip_bits(n) (bits_left -= (n))
#endif /* shc_INCLUDED */
diff --git a/gs/src/siscale.c b/gs/src/siscale.c
index 9d7c01bc8..064924b3b 100644
--- a/gs/src/siscale.c
+++ b/gs/src/siscale.c
@@ -23,6 +23,7 @@
#include "stdio_.h"
#include <assert.h>
#include "gconfigv.h"
+#include "gdebug.h"
#include "strimpl.h"
#include "siscale.h"
@@ -293,6 +294,8 @@ zoom_x(PixelTmp * tmp, const void /*PixelIn */ *src, int sizeofPixelIn,
PixelTmp *tp = tmp + c;
const CLIST *clp = contrib;
+ if_debug1('W', "[W]zoom_x color %d:", c);
+
#define zoom_x_loop(PixelIn, PixelIn2)\
const PixelIn *raster = (const PixelIn *)src + c;\
for ( i = 0; i < tmp_width; tp += Colors, ++clp, ++i )\
@@ -316,6 +319,7 @@ zoom_x(PixelTmp * tmp, const void /*PixelIn */ *src, int sizeofPixelIn,
}\
}\
{ PixelIn2 pixel = unscale_AccumTmp(weight);\
+ if_debug1('W', " %ld", (long)pixel);\
*tp =\
(PixelTmp)CLAMP(pixel, minPixelTmp, maxPixelTmp);\
}\
@@ -330,6 +334,7 @@ zoom_x(PixelTmp * tmp, const void /*PixelIn */ *src, int sizeofPixelIn,
zoom_x_loop(bits16, int)
#endif
}
+ if_debug0('W', "\n");
}
} /* Apply filter to zoom vertically from tmp to dst. *//* This is simpler because we can treat all columns identically *//* without regard to the number of samples per pixel. */ private void
zoom_y(void /*PixelOut */ *dst, int sizeofPixelOut, uint MaxValueOut,
@@ -343,9 +348,11 @@ zoom_y(void /*PixelOut */ *dst, int sizeofPixelOut, uint MaxValueOut,
int kc;
PixelTmp2 max_weight = MaxValueOut;
+ if_debug0('W', "[W]zoom_y: ");
+
#define zoom_y_loop(PixelOut)\
- for ( kc = 0; kc < kn; ++kc )\
- { AccumTmp weight = 0;\
+ for ( kc = 0; kc < kn; ++kc ) {\
+ AccumTmp weight = 0;\
{ const PixelTmp *pp = &tmp[kc + first_pixel];\
int j = cn;\
const CONTRIB *cp = cbp;\
@@ -353,16 +360,18 @@ zoom_y(void /*PixelOut */ *dst, int sizeofPixelOut, uint MaxValueOut,
weight += *pp * cp->weight;\
}\
{ PixelTmp2 pixel = unscale_AccumTmp(weight);\
+ if_debug1('W', " %d", pixel);\
((PixelOut *)dst)[kc] =\
(PixelOut)CLAMP(pixel, 0, max_weight);\
}\
- }
+ }
if (sizeofPixelOut == 1) {
zoom_y_loop(byte)
} else { /* sizeofPixelOut == 2 */
zoom_y_loop(bits16)
}
+ if_debug0('W', "\n");
}
/* ------ Stream implementation ------ */
@@ -401,6 +410,24 @@ calculate_dst_contrib(stream_IScale_state * ss, int y)
ss->dst_next_list.n = MAX_ISCALE_SUPPORT;
ss->dst_next_list.first_pixel = 0;
}
+#ifdef DEBUG
+ if (gs_debug_c('w')) {
+ dprintf1("[w]calc dest contrib for y = %d\n", y);
+ }
+#endif
+}
+
+/* Set default parameter values (actually, just clear pointers). */
+private void
+s_IScale_set_defaults(stream_state * st)
+{
+ stream_IScale_state *const ss = (stream_IScale_state *) st;
+
+ ss->src = 0;
+ ss->dst = 0;
+ ss->tmp = 0;
+ ss->contrib = 0;
+ ss->items = 0;
}
/* Initialize the filter. */
@@ -532,6 +559,8 @@ s_IScale_process(stream_state * st, stream_cursor_read * pr,
ss->src_offset = 0;
}
/* Apply filter to zoom horizontally from src to tmp. */
+ if_debug2('w', "[w]zoom_x y = %d to tmp row %d\n",
+ ss->src_y, (ss->src_y % MAX_ISCALE_SUPPORT));
zoom_x(ss->tmp + (ss->src_y % MAX_ISCALE_SUPPORT) *
ss->tmp_width * ss->params.Colors, row,
ss->sizeofPixelIn, ss->tmp_width, ss->params.WidthIn,
@@ -568,7 +597,7 @@ s_IScale_release(stream_state * st)
}
/* Stream template */
-const stream_template s_IScale_template =
-{&st_IScale_state, s_IScale_init, s_IScale_process, 1, 1,
- s_IScale_release
+const stream_template s_IScale_template = {
+ &st_IScale_state, s_IScale_init, s_IScale_process, 1, 1,
+ s_IScale_release, s_IScale_set_defaults
};
diff --git a/gs/src/sjpegc.c b/gs/src/sjpegc.c
index e2d53d012..ca27b1675 100644
--- a/gs/src/sjpegc.c
+++ b/gs/src/sjpegc.c
@@ -22,6 +22,7 @@
#include "string_.h"
#include "jpeglib_.h"
#include "jerror_.h"
+#include "jmemsys.h" /* for prototypes */
#include "gx.h"
#include "gserrors.h"
#include "strimpl.h"
@@ -195,7 +196,7 @@ jpeg_mem_available(j_common_ptr cinfo, long min_bytes_needed,
}
void
-jpeg_open_backing_store(j_common_ptr cinfo, void *info,
+jpeg_open_backing_store(j_common_ptr cinfo, backing_store_ptr info,
long total_bytes_needed)
{
ERREXIT(cinfo, JERR_NO_BACKING_STORE);
diff --git a/gs/src/slzwce.c b/gs/src/slzwce.c
index 5b5c20b80..55ef28dc1 100644
--- a/gs/src/slzwce.c
+++ b/gs/src/slzwce.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1994, 1995, 1996, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1994, 1995, 1996, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -87,7 +87,7 @@ lzw_put_code(register stream_LZW_state * ss, byte * q, uint code)
}
/* Initialize LZW-compatible encoding filter. */
-int
+private int
s_LZWE_reset(stream_state * st)
{
stream_LZW_state *const ss = (stream_LZW_state *) st;
diff --git a/gs/src/slzwd.c b/gs/src/slzwd.c
index 27f50ba1c..455346fa5 100644
--- a/gs/src/slzwd.c
+++ b/gs/src/slzwd.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1996, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1993, 1996, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -51,7 +51,7 @@ gs_private_st_simple(st_lzw_decode, lzw_decode, "lzw_decode");
/* Initialize LZWDecode filter */
/* We separate out the reset function for some non-stream clients. */
-int
+private int
s_LZWD_reset(stream_state * st)
{
stream_LZW_state *const ss = (stream_LZW_state *) st;
diff --git a/gs/src/slzwx.h b/gs/src/slzwx.h
index ca19f1e6c..f63f490fa 100644
--- a/gs/src/slzwx.h
+++ b/gs/src/slzwx.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1995, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1993, 1995, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -65,7 +65,9 @@ extern_st(st_LZW_state);
((ss)->InitialCodeLength = 8,\
(ss)->FirstBitLowOrder = false,\
(ss)->BlockData = false,\
- (ss)->EarlyChange = 1)
+ (ss)->EarlyChange = 1,\
+ /* Clear pointers */\
+ (ss)->table.decode /*=encode*/ = 0)
extern const stream_template s_LZWD_template;
extern const stream_template s_LZWE_template;
diff --git a/gs/src/spdiff.c b/gs/src/spdiff.c
index c6df11094..660d03dad 100644
--- a/gs/src/spdiff.c
+++ b/gs/src/spdiff.c
@@ -104,7 +104,7 @@ row:
if (ss->row_left == 0) {
ss->row_left = ss->row_count;
s0 = 0;
- memset(ss->prev + 1, s_PDiff_max_Colors - 1, 0);
+ memset(ss->prev + 1, 0, s_PDiff_max_Colors - 1);
}
{
int rcount = pr->limit - p;
diff --git a/gs/src/spngp.c b/gs/src/spngp.c
index 9ee32e776..de51c6b5d 100644
--- a/gs/src/spngp.c
+++ b/gs/src/spngp.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996, 1997, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1996, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -264,13 +264,16 @@ s_PNGPE_process(stream_state * st, stream_cursor_read * pr,
continue;
if (n < bpp) {
/*
- * We didn't have enough data to use up all of prev.
- * Shift more data into prev and exit.
+ * We didn't have both enough input data and enough output
+ * space to use up all of prev. Shift more data into prev
+ * and exit.
*/
int prev_left = bpp - n;
memmove(ss->prev, ss->prev + n, prev_left);
memcpy(ss->prev + prev_left, pr->ptr - (n - 1), n);
+ if (pw->ptr >= pw->limit && pr->ptr < pr->limit)
+ status = 1;
break;
}
/* Process bytes whose predecessors are in the input. */
@@ -342,8 +345,11 @@ s_PNGPD_process(stream_state * st, stream_cursor_read * pr,
if (ss->row_left == 0)
continue;
if (n < bpp) {
- /* We didn't have enough data to use up all of prev. */
- /* Shift more data into prev and exit. */
+ /*
+ * We didn't have both enough input data and enough output
+ * space to use up all of prev. Shift more data into prev
+ * and exit.
+ */
int prev_left = bpp - n;
memmove(ss->prev, ss->prev + n, prev_left);
diff --git a/gs/src/spngpx.h b/gs/src/spngpx.h
index 47157d4a7..b33b95639 100644
--- a/gs/src/spngpx.h
+++ b/gs/src/spngpx.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1996, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -48,7 +48,9 @@ typedef struct stream_PNGP_state_s {
prev_row)
#define s_PNGP_set_defaults_inline(ss)\
((ss)->Colors = 1, (ss)->BitsPerComponent = 8, (ss)->Columns = 1,\
- (ss)->Predictor = 15)
+ (ss)->Predictor = 15,\
+ /* Clear pointers */\
+ (ss)->prev_row = 0)
extern const stream_template s_PNGPD_template;
extern const stream_template s_PNGPE_template;
diff --git a/gs/src/gdevpstr.c b/gs/src/spprint.c
index 28f20af0e..538c5608a 100644
--- a/gs/src/gdevpstr.c
+++ b/gs/src/spprint.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1997, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -17,12 +17,12 @@
*/
-/* Stream output for PostScript- and PDF-writing drivers */
+/* Print values in ASCII form on a stream */
#include "math_.h" /* for fabs */
#include "stdio_.h" /* for stream.h */
#include "string_.h" /* for strchr */
-#include "gdevpstr.h"
#include "stream.h"
+#include "spprint.h"
/* ------ Output ------ */
diff --git a/gs/src/gdevpstr.h b/gs/src/spprint.h
index 3f7596c05..6d097659a 100644
--- a/gs/src/gdevpstr.h
+++ b/gs/src/spprint.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1997, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -17,16 +17,15 @@
*/
-/* Stream output for PostScript- and PDF-writing drivers. */
+/* Print values in ASCII form on a stream */
-#ifndef gdevpstr_INCLUDED
-# define gdevpstr_INCLUDED
+#ifndef spprint_INCLUDED
+# define spprint_INCLUDED
/* Define an opaque type for streams. */
#ifndef stream_DEFINED
# define stream_DEFINED
typedef struct stream_s stream;
-
#endif
/* Put a character on a stream. */
@@ -79,6 +78,6 @@ const char *pprints1(P3(stream * s, const char *format, const char *str));
const char *pprints2(P4(stream * s, const char *format,
const char *str1, const char *str2));
const char *pprints3(P5(stream * s, const char *format,
- const char *str1, const char *str2, const char *str3));
+ const char *str1, const char *str2, const char *str3));
-#endif /* gdevpstr_INCLUDED */
+#endif /* spprint_INCLUDED */
diff --git a/gs/src/spsdf.c b/gs/src/spsdf.c
new file mode 100644
index 000000000..df6383ded
--- /dev/null
+++ b/gs/src/spsdf.c
@@ -0,0 +1,267 @@
+/* Copyright (C) 1999 Aladdin Enterprises. All rights reserved.
+
+ This file is part of Aladdin Ghostscript.
+
+ Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
+ or distributor accepts any responsibility for the consequences of using it,
+ or for whether it serves any particular purpose or works at all, unless he
+ or she says so in writing. Refer to the Aladdin Ghostscript Free Public
+ License (the "License") for full details.
+
+ Every copy of Aladdin Ghostscript must include a copy of the License,
+ normally in a plain ASCII text file named PUBLIC. The License grants you
+ the right to copy, modify and redistribute Aladdin Ghostscript, but only
+ under certain conditions described in the License. Among other things, the
+ License requires that the copyright notice and this notice be preserved on
+ all copies.
+ */
+
+
+/* Common utilities for PostScript and PDF format printing */
+#include "stdio_.h" /* for stream.h */
+#include "string_.h"
+#include "gstypes.h"
+#include "gsmemory.h"
+#include "gserror.h"
+#include "gserrors.h"
+#include "spprint.h"
+#include "spsdf.h"
+#include "stream.h"
+#include "strimpl.h"
+#include "sa85x.h"
+#include "sstring.h"
+#include "scanchar.h"
+
+/*
+ * Write a string in its shortest form ( () or <> ). Note that
+ * this form is different depending on whether binary data are allowed.
+ * Currently we don't support ASCII85 strings ( <~ ~> ).
+ */
+void
+s_write_ps_string(stream * s, const byte * str, uint size, int print_ok)
+{
+ uint added = 0;
+ uint i;
+ const stream_template *template;
+ stream_AXE_state state;
+ stream_state *st = NULL;
+
+ if (print_ok & PRINT_BINARY_OK) {
+ /* Only need to escape (, ), \, CR, EOL. */
+ pputc(s, '(');
+ for (i = 0; i < size; ++i) {
+ byte ch = str[i];
+
+ switch (ch) {
+ case char_CR:
+ pputs(s, "\\r");
+ continue;
+ case char_EOL:
+ pputs(s, "\\n");
+ continue;
+ case '(':
+ case ')':
+ case '\\':
+ pputc(s, '\\');
+ }
+ pputc(s, ch);
+ }
+ pputc(s, ')');
+ return;
+ }
+ for (i = 0; i < size; ++i) {
+ byte ch = str[i];
+
+ if (ch == 0 || ch >= 127)
+ added += 3;
+ else if (strchr("()\\\n\r\t\b\f", ch) != 0)
+ ++added;
+ else if (ch < 32)
+ added += 3;
+ }
+
+ if (added < size) {
+ /* More efficient to represent as PostScript string. */
+ template = &s_PSSE_template;
+ pputc(s, '(');
+ } else {
+ /* More efficient to represent as hex string. */
+ template = &s_AXE_template;
+ st = (stream_state *) & state;
+ s_AXE_init_inline(&state);
+ pputc(s, '<');
+ }
+
+ {
+ byte buf[100]; /* size is arbitrary */
+ stream_cursor_read r;
+ stream_cursor_write w;
+ int status;
+
+ r.ptr = str - 1;
+ r.limit = r.ptr + size;
+ w.limit = buf + sizeof(buf) - 1;
+ do {
+ w.ptr = buf - 1;
+ status = (*template->process) (st, &r, &w, true);
+ pwrite(s, buf, (uint) (w.ptr + 1 - buf));
+ }
+ while (status == 1);
+ }
+}
+
+/* Set up a write stream that just keeps track of the position. */
+int
+s_alloc_position_stream(stream ** ps, gs_memory_t * mem)
+{
+ stream *s = *ps = s_alloc(mem, "s_alloc_position_stream");
+
+ if (s == 0)
+ return_error(gs_error_VMerror);
+ swrite_position_only(s);
+ return 0;
+}
+
+/* ---------------- Parameter printing ---------------- */
+
+private_st_printer_param_list();
+const param_printer_params_t param_printer_params_default = {
+ param_printer_params_default_values
+};
+
+/* We'll implement the other printers later if we have to. */
+private param_proc_xmit_typed(param_print_typed);
+/*private param_proc_begin_xmit_collection(param_print_begin_collection); */
+/*private param_proc_end_xmit_collection(param_print_end_collection); */
+private const gs_param_list_procs printer_param_list_procs = {
+ param_print_typed,
+ NULL /* begin_collection */ ,
+ NULL /* end_collection */ ,
+ NULL /* get_next_key */ ,
+ gs_param_request_default,
+ gs_param_requested_default
+};
+
+int
+s_init_param_printer(printer_param_list_t *prlist,
+ const param_printer_params_t * ppp, stream * s)
+{
+ prlist->procs = &printer_param_list_procs;
+ prlist->memory = 0;
+ prlist->strm = s;
+ prlist->params = *ppp;
+ prlist->any = false;
+ return 0;
+}
+int
+s_alloc_param_printer(gs_param_list ** pplist,
+ const param_printer_params_t * ppp, stream * s,
+ gs_memory_t * mem)
+{
+ printer_param_list_t *prlist =
+ gs_alloc_struct(mem, printer_param_list_t, &st_printer_param_list,
+ "s_alloc_param_printer");
+ int code;
+
+ *pplist = (gs_param_list *)prlist;
+ if (prlist == 0)
+ return_error(gs_error_VMerror);
+ code = s_init_param_printer(prlist, ppp, s);
+ prlist->memory = mem;
+ return code;
+}
+
+void
+s_release_param_printer(printer_param_list_t *prlist)
+{
+ if (prlist) {
+ if (prlist->any && prlist->params.suffix)
+ pputs(prlist->strm, prlist->params.suffix);
+ }
+}
+void
+s_free_param_printer(gs_param_list * plist)
+{
+ if (plist) {
+ printer_param_list_t *const prlist = (printer_param_list_t *) plist;
+
+ s_release_param_printer(prlist);
+ gs_free_object(prlist->memory, plist, "s_free_param_printer");
+ }
+}
+
+private int
+param_print_typed(gs_param_list * plist, gs_param_name pkey,
+ gs_param_typed_value * pvalue)
+{
+ printer_param_list_t *const prlist = (printer_param_list_t *)plist;
+ stream *s = prlist->strm;
+
+ if (!prlist->any) {
+ if (prlist->params.prefix)
+ pputs(s, prlist->params.prefix);
+ prlist->any = true;
+ }
+ if (prlist->params.item_prefix)
+ pputs(s, prlist->params.item_prefix);
+ pprints1(s, "/%s", pkey);
+ switch (pvalue->type) {
+ case gs_param_type_null:
+ pputs(s, " null");
+ break;
+ case gs_param_type_bool:
+ pputs(s, (pvalue->value.b ? " true" : " false"));
+ break;
+ case gs_param_type_int:
+ pprintd1(s, " %d", pvalue->value.i);
+ break;
+ case gs_param_type_long:
+ pprintld1(s, " %l", pvalue->value.l);
+ break;
+ case gs_param_type_float:
+ pprintg1(s, " %g", pvalue->value.f);
+ break;
+ case gs_param_type_string:
+ s_write_ps_string(s, pvalue->value.s.data, pvalue->value.s.size,
+ prlist->params.print_ok);
+ break;
+ case gs_param_type_name:
+ /****** SHOULD USE #-ESCAPES FOR PDF ******/
+ pputc(s, '/');
+ pwrite(s, pvalue->value.n.data, pvalue->value.n.size);
+ break;
+ case gs_param_type_int_array:
+ {
+ uint i;
+ char sepr = (pvalue->value.ia.size <= 10 ? ' ' : '\n');
+
+ pputc(s, '[');
+ for (i = 0; i < pvalue->value.ia.size; ++i) {
+ pprintd1(s, "%d", pvalue->value.ia.data[i]);
+ pputc(s, sepr);
+ }
+ pputc(s, ']');
+ }
+ break;
+ case gs_param_type_float_array:
+ {
+ uint i;
+ char sepr = (pvalue->value.fa.size <= 10 ? ' ' : '\n');
+
+ pputc(s, '[');
+ for (i = 0; i < pvalue->value.fa.size; ++i) {
+ pprintg1(s, "%g", pvalue->value.fa.data[i]);
+ pputc(s, sepr);
+ }
+ pputc(s, ']');
+ }
+ break;
+ /*case gs_param_type_string_array: */
+ /*case gs_param_type_name_array: */
+ default:
+ return_error(gs_error_typecheck);
+ }
+ if (prlist->params.item_suffix)
+ pputs(s, prlist->params.item_suffix);
+ return 0;
+}
diff --git a/gs/src/spsdf.h b/gs/src/spsdf.h
new file mode 100644
index 000000000..5633540b7
--- /dev/null
+++ b/gs/src/spsdf.h
@@ -0,0 +1,86 @@
+/* Copyright (C) 1999 Aladdin Enterprises. All rights reserved.
+
+ This file is part of Aladdin Ghostscript.
+
+ Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
+ or distributor accepts any responsibility for the consequences of using it,
+ or for whether it serves any particular purpose or works at all, unless he
+ or she says so in writing. Refer to the Aladdin Ghostscript Free Public
+ License (the "License") for full details.
+
+ Every copy of Aladdin Ghostscript must include a copy of the License,
+ normally in a plain ASCII text file named PUBLIC. The License grants you
+ the right to copy, modify and redistribute Aladdin Ghostscript, but only
+ under certain conditions described in the License. Among other things, the
+ License requires that the copyright notice and this notice be preserved on
+ all copies.
+ */
+
+
+/* Common output syntax and parameters for PostScript and PDF writers */
+
+#ifndef spsdf_INCLUDED
+# define spsdf_INCLUDED
+
+#include "gsparam.h"
+
+/* Define an opaque type for streams. */
+#ifndef stream_DEFINED
+# define stream_DEFINED
+typedef struct stream_s stream;
+#endif
+
+/* ---------------- Symbolic data printing ---------------- */
+
+/* Print a PostScript string in the most efficient form. */
+#define PRINT_BINARY_OK 1
+#define PRINT_ASCII85_OK 2
+void s_write_ps_string(P4(stream * s, const byte * str, uint size,
+ int print_ok));
+
+/*
+ * Create a stream that just keeps track of how much has been written
+ * to it. We use this for measuring data that will be stored rather
+ * than written to an actual stream.
+ */
+int s_alloc_position_stream(P2(stream ** ps, gs_memory_t * mem));
+
+/*
+ * Create/release a parameter list for printing (non-default) filter
+ * parameters. This should probably migrate to a lower level....
+ */
+typedef struct param_printer_params_s {
+ const char *prefix; /* before entire object, if any params */
+ const char *suffix; /* after entire object, if any params */
+ const char *item_prefix; /* before each param */
+ const char *item_suffix; /* after each param */
+ int print_ok;
+} param_printer_params_t;
+/*
+ * The implementation structure should be opaque, but there are a few
+ * clients that need to be able to stack-allocate it.
+ */
+typedef struct printer_param_list_s {
+ gs_param_list_common;
+ stream *strm;
+ param_printer_params_t params;
+ bool any;
+} printer_param_list_t;
+#define private_st_printer_param_list() /* in spsdf.c */\
+ gs_private_st_ptrs1(st_printer_param_list, printer_param_list_t,\
+ "printer_param_list_t", printer_plist_enum_ptrs, printer_plist_reloc_ptrs,\
+ strm)
+
+#define param_printer_params_default_values 0, 0, 0, "\n", 0
+extern const param_printer_params_t param_printer_params_default;
+int s_alloc_param_printer(P4(gs_param_list ** pplist,
+ const param_printer_params_t * ppp, stream * s,
+ gs_memory_t * mem));
+void s_free_param_printer(P1(gs_param_list * plist));
+/* Initialize or release a list without allocating or freeing it. */
+int s_init_param_printer(P3(printer_param_list_t *prlist,
+ const param_printer_params_t * ppp, stream * s));
+void s_release_param_printer(P1(printer_param_list_t *prlist));
+
+
+#endif /* spsdf_INCLUDED */
diff --git a/gs/src/std.h b/gs/src/std.h
index 6c8e4ed94..c370fda1d 100644
--- a/gs/src/std.h
+++ b/gs/src/std.h
@@ -53,7 +53,7 @@
#define arch_cache2_size ARCH_CACHE2_SIZE
#define arch_is_big_endian ARCH_IS_BIG_ENDIAN
#define arch_ptrs_are_signed ARCH_PTRS_ARE_SIGNED
-#define arch_floats_are_ieee ARCH_FLOATS_ARE_IEEE
+#define arch_floats_are_IEEE ARCH_FLOATS_ARE_IEEE
#define arch_arith_rshift ARCH_ARITH_RSHIFT
#define arch_can_shift_full_long ARCH_CAN_SHIFT_FULL_LONG
@@ -160,11 +160,9 @@ typedef ulong bits32;
/* Print the program line # for debugging. */
#if __LINE__ /* compiler provides it */
void dprintf_file_and_line(P3(FILE *, const char *, int));
-
# define _dpl dprintf_file_and_line(estderr, __FILE__, __LINE__),
#else
void dprintf_file_only(P2(FILE *, const char *));
-
# define _dpl dprintf_file_only(estderr, __FILE__),
#endif
@@ -260,11 +258,9 @@ long gs_revision_number(P0());
#if __LINE__ /* compiler provides it */
void lprintf_file_and_line(P3(FILE *, const char *, int));
-
# define _epl _epi lprintf_file_and_line(estderr, __FILE__, __LINE__),
#else
void lprintf_file_only(P2(FILE *, const char *));
-
# define _epl _epi lprintf_file_only(estderr, __FILE__)
#endif
@@ -291,4 +287,17 @@ void lprintf_file_only(P2(FILE *, const char *));
#define lprintf10(str,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10)\
(_epl fprintf(estderr, str, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10))
+/*
+ * Define the prototype for module initialization procedures. This is not
+ * a very good place to define this, but we can't find a better one.
+ *
+ * The return value should probably be int rather than void....
+ */
+#ifndef gs_memory_DEFINED
+# define gs_memory_DEFINED
+typedef struct gs_memory_s gs_memory_t;
+#endif
+#define init_proc(proc)\
+ void proc(P1(gs_memory_t *))
+
#endif /* std_INCLUDED */
diff --git a/gs/src/stdpre.h b/gs/src/stdpre.h
index 79b27e9a0..8c4452527 100644
--- a/gs/src/stdpre.h
+++ b/gs/src/stdpre.h
@@ -112,7 +112,33 @@
* because no commercial compiler gives the error on (void)0, although
* some give warnings.)
*/
-#define discard(expr) ((void)(expr))
+#define DISCARD(expr) ((void)(expr))
+/* Backward compatibility */
+#define discard(expr) DISCARD(expr)
+
+/*
+ * Some versions of the Watcom compiler give a "Comparison result always
+ * 0/1" message that we want to suppress because it gets in the way of
+ * meaningful warnings.
+ */
+#ifdef __WATCOMC__
+# pragma disable_message(124);
+#endif
+
+/*
+ * Some versions of gcc have a bug such that after
+ byte *p;
+ ...
+ x = *(long *)p;
+ * the compiler then thinks that p always points to long-aligned data.
+ * Detect this here so it can be handled appropriately in the few places
+ * that (we think) matter.
+ */
+#ifdef __GNUC__
+# if __GNUC__ == 2 & (7 < __GNUC_MINOR__ <= 95)
+# define ALIGNMENT_ALIASING_BUG
+# endif
+#endif
/*
* The SVR4.2 C compiler incorrectly considers the result of << and >>
diff --git a/gs/src/store.h b/gs/src/store.h
index c2e6eb4bd..cb2d8a4f9 100644
--- a/gs/src/store.h
+++ b/gs/src/store.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1989, 1995 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1989, 1995, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -23,6 +23,7 @@
# define store_INCLUDED
#include "ialloc.h" /* for imemory masks & checks */
+#include "idosave.h"
/*
* Macros for storing a ref. We use macros for storing into objects,
@@ -91,30 +92,36 @@
(*(pto) = *(pfrom))
#endif
-/****** NOTE: the following declarations are duplicated from isave.h. ******/
-
-int alloc_save_change(P4(gs_dual_memory_t *, const ref * pcont,
- ref_packed * ptr, client_name_t cname));
-int alloc_save_level(P1(const gs_dual_memory_t *));
-
-/****** END duplicated declarations. ******/
-
-#define ialloc_save_change(pcont, ptr, cname)\
- alloc_save_change(idmemory, pcont, ptr, cname)
-#define ialloc_is_in_save() (idmemory->save_level > 0)
-#define ialloc_test_mask (idmemory->test_mask)
#define ialloc_new_mask (idmemory->new_mask)
-#define ref_must_save(pto)\
- ((r_type_attrs(pto) & ialloc_test_mask) == 0)
+ /*
+ * The mmem argument may be either a gs_dual_memory_t or a
+ * gs_ref_memory_t, since it is only used for accessing the masks.
+ */
+#define ref_saving_in(mmem)\
+ ((mmem)->new_mask != 0)
+#define ref_must_save_in(mmem,pto)\
+ ((r_type_attrs(pto) & (mmem)->test_mask) == 0)
+#define ref_must_save(pto) ref_must_save_in(idmemory, pto)
+#define ref_do_save_in(mem, pcont, pto, cname)\
+ alloc_save_change_in(mem, pcont, (ref_packed *)(pto), cname)
#define ref_do_save(pcont, pto, cname)\
- ialloc_save_change(pcont, (ref_packed *)(pto), cname)
+ alloc_save_change(idmemory, pcont, (ref_packed *)(pto), cname)
+#define ref_save_in(mem, pcont, pto, cname)\
+ discard((ref_must_save_in(mem, pto) ?\
+ ref_do_save_in(mem, pcont, pto, cname) : 0))
#define ref_save(pcont, pto, cname)\
discard((ref_must_save(pto) ? ref_do_save(pcont, pto, cname) : 0))
-#define ref_mark_new(pto) ((pto)->tas.type_attrs |= ialloc_new_mask)
+#define ref_mark_new_in(mmem,pto)\
+ ((pto)->tas.type_attrs |= (mmem)->new_mask)
+#define ref_mark_new(pto) ref_mark_new_in(idmemory, pto)
+#define ref_assign_new_in(mem,pto,pfrom)\
+ discard((ref_assign(pto,pfrom), ref_mark_new_in(mem,pto)))
#define ref_assign_new(pto,pfrom)\
discard((ref_assign(pto,pfrom), ref_mark_new(pto)))
#define ref_assign_new_inline(pto,pfrom)\
discard((ref_assign_inline(pto,pfrom), ref_mark_new(pto)))
+#define ref_assign_old_in(mem,pcont,pto,pfrom,cname)\
+ (ref_save_in(mem,pcont,pto,cname), ref_assign_new_in(mem,pto,pfrom))
#define ref_assign_old(pcont,pto,pfrom,cname)\
(ref_save(pcont,pto,cname), ref_assign_new(pto,pfrom))
#define ref_assign_old_inline(pcont,pto,pfrom,cname)\
@@ -144,10 +151,16 @@ int alloc_save_level(P1(const gs_dual_memory_t *));
#endif
/* make_t must set the attributes to 0 to clear a_local! */
+#define make_ta(pref,newtype,newattrs)\
+ (r_set_type_attrs(pref, newtype, newattrs) and_fill_sv(pref))
#define make_t(pref,newtype)\
- (r_set_type_attrs(pref, newtype, 0) and_fill_sv(pref))
+ make_ta(pref, newtype, 0)
+#define make_t_new_in(mem,pref,newtype)\
+ make_ta(pref, newtype, imemory_new_mask(mem))
#define make_t_new(pref,newtype)\
- (r_set_type_attrs(pref, newtype, ialloc_new_mask) and_fill_sv(pref))
+ make_ta(pref, newtype, ialloc_new_mask)
+#define make_t_old_in(mem,pcont,pref,newtype,cname)\
+ (ref_save_in(mem,pcont,pref,cname), make_t_new_in(mem,pref,newtype))
#define make_t_old(pcont,pref,newtype,cname)\
(ref_save(pcont,pref,cname), make_t_new(pref,newtype))
@@ -197,6 +210,8 @@ int alloc_save_level(P1(const gs_dual_memory_t *));
make_t(pref, t_null)
#define make_null_new(pref)\
make_t_new(pref, t_null)
+#define make_null_old_in(mem,pcont,pref,cname)\
+ make_t_old_in(mem, pcont, pref, t_null, cname)
#define make_null_old(pcont,pref,cname)\
make_t_old(pcont, pref, t_null, cname)
diff --git a/gs/src/stream.c b/gs/src/stream.c
index 049ee6984..c0407ebb6 100644
--- a/gs/src/stream.c
+++ b/gs/src/stream.c
@@ -31,13 +31,11 @@ private int swritebuf(P3(stream *, stream_cursor_read *, bool));
private void stream_compact(P2(stream *, bool));
/* Structure types for allocating streams. */
-private_st_stream();
+public_st_stream();
public_st_stream_state(); /* default */
/* GC procedures */
-#define st ((stream *)vptr)
private
-ENUM_PTRS_BEGIN(stream_enum_ptrs) return 0;
-
+ENUM_PTRS_WITH(stream_enum_ptrs, stream *st) return 0;
case 0:
if (st->foreign)
ENUM_RETURN(NULL);
@@ -45,12 +43,10 @@ else if (st->cbuf_string.data != 0)
ENUM_RETURN_STRING_PTR(stream, cbuf_string);
else
ENUM_RETURN(st->cbuf);
-ENUM_PTR(1, stream, strm);
-ENUM_PTR(2, stream, prev);
-ENUM_PTR(3, stream, next);
+ENUM_PTR3(1, stream, strm, prev, next);
ENUM_PTR(4, stream, state);
ENUM_PTRS_END
-private RELOC_PTRS_BEGIN(stream_reloc_ptrs)
+private RELOC_PTRS_WITH(stream_reloc_ptrs, stream *st)
{
byte *cbuf_old = st->cbuf;
@@ -80,18 +76,20 @@ RELOC_PTRS_END
private void
stream_finalize(void *vptr)
{
+ stream *const st = vptr;
+
if_debug2('u', "[u]%s 0x%lx\n",
(!s_is_valid(st) ? "already closed:" :
st->is_temp ? "is_temp set:" :
st->file == 0 ? "not file:" :
"closing file:"), (ulong) st);
- if (s_is_valid(st) && !st->is_temp && st->file != 0) { /* Prevent any attempt to free the buffer. */
+ if (s_is_valid(st) && !st->is_temp && st->file != 0) {
+ /* Prevent any attempt to free the buffer. */
st->cbuf = 0;
st->cbuf_string.data = 0;
sclose(st); /* ignore errors */
}
}
-#undef st
/* Dummy template for streams that don't have a separate state. */
private const stream_template s_no_template = {
@@ -125,6 +123,14 @@ s_alloc(gs_memory_t * mem, client_name_t cname)
}
/* Allocate a stream state and initialize it minimally. */
+void
+s_init_state(stream_state *st, const stream_template *template,
+ gs_memory_t *mem)
+{
+ st->template = template;
+ st->memory = mem;
+ st->report_error = s_no_report_error;
+}
stream_state *
s_alloc_state(gs_memory_t * mem, gs_memory_type_ptr_t stype,
client_name_t cname)
@@ -135,20 +141,11 @@ s_alloc_state(gs_memory_t * mem, gs_memory_type_ptr_t stype,
client_name_string(cname),
client_name_string(stype->sname),
(ulong) st);
- if (st == 0)
- return 0;
- st->memory = mem;
- st->report_error = s_no_report_error;
+ if (st)
+ s_init_state(st, NULL, mem);
return st;
}
-/* Vacuous stream initialization */
-int
-s_no_init(stream_state * st)
-{
- return 0;
-}
-
/* Standard stream initialization */
void
s_std_init(register stream * s, byte * ptr, uint len, const stream_procs * pp,
@@ -299,16 +296,14 @@ s_no_report_error(stream_state * st, const char *str)
/* Generic procedure structures for filters. */
-const stream_procs s_filter_read_procs =
-{
+const stream_procs s_filter_read_procs = {
s_std_noavailable, s_std_noseek, s_std_read_reset,
s_std_read_flush, s_filter_close
};
-const stream_procs s_filter_write_procs =
-{
+const stream_procs s_filter_write_procs = {
s_std_noavailable, s_std_noseek, s_std_write_reset,
- s_std_write_flush, s_filter_close
+ s_filter_write_flush, s_filter_close
};
/* ------ Implementation-independent procedures ------ */
@@ -392,7 +387,10 @@ spgetcc(register stream * s, bool close_at_eod)
left <= min_left && status >= 0
)
s_process_read_buf(s);
- if (left <= min_left && (left == 0 || (status != EOFC && status != ERRC))) { /* Compact the stream so stell will return the right result. */
+ if (left <= min_left &&
+ (left == 0 || (status != EOFC && status != ERRC))
+ ) {
+ /* Compact the stream so stell will return the right result. */
stream_compact(s, true);
if (status == EOFC && close_at_eod && s->close_at_eod) {
status = sclose(s);
@@ -688,14 +686,16 @@ s_process_write_buf(stream * s, bool last)
/* Move forward or backward in a pipeline. We temporarily reverse */
/* the direction of the pointers while doing this. */
/* (Cf the Deutsch-Schorr-Waite graph marking algorithm.) */
-#define move_back(curr, prev)\
-{ stream *back = prev->strm;\
- prev->strm = curr; curr = prev; prev = back;\
-}
-#define move_ahead(curr, prev)\
-{ stream *ahead = curr->strm;\
- curr->strm = prev; prev = curr; curr = ahead;\
-}
+#define MOVE_BACK(curr, prev)\
+ BEGIN\
+ stream *back = prev->strm;\
+ prev->strm = curr; curr = prev; prev = back;\
+ END
+#define MOVE_AHEAD(curr, prev)\
+ BEGIN\
+ stream *ahead = curr->strm;\
+ curr->strm = prev; prev = curr; curr = ahead;\
+ END
/* Read from a pipeline. */
private int
@@ -736,7 +736,7 @@ sreadbuf(stream * s, stream_cursor_write * pbuf)
status = strm->end_status;
if (status < 0)
break;
- move_ahead(curr, prev);
+ MOVE_AHEAD(curr, prev);
stream_compact(curr, false);
}
/* If curr reached EOD and is a filter stream, close it. */
@@ -753,7 +753,7 @@ sreadbuf(stream * s, stream_cursor_write * pbuf)
/* If we need to do a callout, unwind all the way now. */
if (status == CALLC) {
while ((curr->end_status = status), prev != 0) {
- move_back(curr, prev);
+ MOVE_BACK(curr, prev);
}
return status;
}
@@ -762,7 +762,7 @@ sreadbuf(stream * s, stream_cursor_write * pbuf)
curr->end_status = (status >= 0 ? 0 : status);
if (prev == 0)
return status;
- move_back(curr, prev);
+ MOVE_BACK(curr, prev);
}
}
@@ -772,7 +772,7 @@ swritebuf(stream * s, stream_cursor_read * pbuf, bool last)
{
stream *prev = 0;
stream *curr = s;
- int depth = 0; /* depth of nesting in non-temp streams */
+ int depth = 0; /* # of non-temp streams before curr */
int status;
/*
@@ -786,7 +786,8 @@ swritebuf(stream * s, stream_cursor_read * pbuf, bool last)
* end_status < 0.
*/
for (;;) {
- for (;;) { /* Descend into the recursion. */
+ for (;;) {
+ /* Move ahead in the pipeline. */
stream *strm = curr->strm;
stream_cursor_write cw;
stream_cursor_read *pr;
@@ -798,8 +799,8 @@ swritebuf(stream * s, stream_cursor_read * pbuf, bool last)
* immediately below it.
*/
bool end = last &&
- (prev == 0 ||
- (depth <= 1 && prev->end_status == EOFC));
+ (prev == 0 ||
+ (depth <= 1 && prev->end_status == EOFC));
if (strm == 0)
cw.ptr = 0, cw.limit = 0, pw = &cw;
@@ -809,55 +810,62 @@ swritebuf(stream * s, stream_cursor_read * pbuf, bool last)
pr = pbuf;
else
pr = &curr->cursor.r;
- if_debug4('s', "[s]write process 0x%lx, nr=%u, nw=%u, end=%d\n",
- (ulong) curr, (uint) (pr->limit - pr->ptr),
- (uint) (pw->limit - pw->ptr), end);
+ if_debug5('s',
+ "[s]write process 0x%lx(%s), nr=%u, nw=%u, end=%d\n",
+ (ulong)curr,
+ gs_struct_type_name(curr->state->template->stype),
+ (uint)(pr->limit - pr->ptr),
+ (uint)(pw->limit - pw->ptr), end);
status = curr->end_status;
- if (status < 0)
- break;
- status = (*curr->procs.process) (curr->state,
- pr, pw, end);
- if_debug5('s', "[s]after write 0x%lx, nr=%u, nw=%u, end=%d, status=%d\n",
- (ulong) curr, (uint) (pr->limit - pr->ptr),
- (uint) (pw->limit - pw->ptr), end, status);
- if (status == 0 && end)
- status = EOFC;
- if (status == EOFC || status == ERRC)
- curr->end_status = status;
+ if (status >= 0) {
+ status = (*curr->procs.process)(curr->state, pr, pw, end);
+ if_debug5('s',
+ "[s]after write 0x%lx, nr=%u, nw=%u, end=%d, status=%d\n",
+ (ulong) curr, (uint) (pr->limit - pr->ptr),
+ (uint) (pw->limit - pw->ptr), end, status);
+ if (status == 0 && end)
+ status = EOFC;
+ if (status == EOFC || status == ERRC)
+ curr->end_status = status;
+ }
if (strm == 0 || (status < 0 && status != EOFC))
break;
- if (status == 1)
- end = false;
- else { /* Keep going if we are closing */
- /* a filter with a sub-stream. */
- /* We know status == 0 or EOFC. */
+ if (status != 1) {
+ /*
+ * Keep going if we are closing a filter with a sub-stream.
+ * We know status == 0 or EOFC.
+ */
if (!end || !strm->is_temp)
break;
}
status = strm->end_status;
if (status < 0)
break;
- move_ahead(curr, prev);
- stream_compact(curr, false);
if (!curr->is_temp)
++depth;
+ if_debug1('s', "[s]moving ahead, depth = %d\n", depth);
+ MOVE_AHEAD(curr, prev);
+ stream_compact(curr, false);
}
- /* Unwind from the recursion. */
+ /* Move back in the pipeline. */
curr->end_status = (status >= 0 ? 0 : status);
- if (status < 0 || prev == 0) { /*
- * All streams above here were called with last = true
- * and returned 0 or EOFC: finish unwinding and then
- * return.
- */
+ if (status < 0 || prev == 0) {
+ /*
+ * All streams above here were called with last = true
+ * and returned 0 or EOFC: finish unwinding and then
+ * return.
+ */
while (prev) {
- move_back(curr, prev);
+ if_debug0('s', "[s]unwinding\n");
+ MOVE_BACK(curr, prev);
curr->end_status = (status >= 0 ? 0 : status);
}
return status;
}
- move_back(curr, prev);
+ MOVE_BACK(curr, prev);
if (!curr->is_temp)
--depth;
+ if_debug1('s', "[s]moving back, depth = %d\n", depth);
}
}
@@ -900,11 +908,13 @@ stream_compact(stream * s, bool always)
/* String stream procedures */
private int
- s_string_available(P2(stream *, long *)), s_string_read_seek(P2(stream *, long)),
- s_string_write_seek(P2(stream *, long)), s_string_read_process(P4(stream_state *, stream_cursor_read *,
- stream_cursor_write *, bool)),
- s_string_write_process(P4(stream_state *, stream_cursor_read *,
- stream_cursor_write *, bool));
+ s_string_available(P2(stream *, long *)),
+ s_string_read_seek(P2(stream *, long)),
+ s_string_write_seek(P2(stream *, long)),
+ s_string_read_process(P4(stream_state *, stream_cursor_read *,
+ stream_cursor_write *, bool)),
+ s_string_write_process(P4(stream_state *, stream_cursor_read *,
+ stream_cursor_write *, bool));
/* Initialize a stream for reading a string. */
void
@@ -966,9 +976,9 @@ s_string_read_seek(register stream * s, long pos)
void
swrite_string(register stream * s, byte * ptr, uint len)
{
- static const stream_procs p =
- {s_std_noavailable, s_string_write_seek, s_std_write_reset,
- s_std_null, s_std_null, s_string_write_process
+ static const stream_procs p = {
+ s_std_noavailable, s_string_write_seek, s_std_write_reset,
+ s_std_null, s_std_null, s_string_write_process
};
s_std_init(s, ptr, len, &p, s_mode_write + s_mode_seek);
@@ -1027,3 +1037,76 @@ s_write_position_process(stream_state * st, stream_cursor_read * pr,
pr->ptr = pr->limit; /* discard data */
return 0;
}
+
+/* ------ Filter pipelines ------ */
+
+/*
+ * Add a filter to a pipeline. The client must have allocated the stream
+ * state, if any, using the given allocator. For s_init_filter, the
+ * client must have called s_init and s_init_state.
+ */
+int
+s_init_filter(stream *fs, stream_state *fss, byte *buf, uint bsize,
+ stream *target)
+{
+ const stream_template *template = fss->template;
+
+ if (bsize < template->min_out_size)
+ return ERRC;
+ s_std_init(fs, buf, bsize, &s_filter_write_procs, s_mode_write);
+ fs->procs.process = template->process;
+ fs->state = fss;
+ if (template->init)
+ (template->init)(fss);
+ fs->strm = target;
+ return 0;
+}
+stream *
+s_add_filter(stream **ps, const stream_template *template,
+ stream_state *ss, gs_memory_t *mem)
+{
+ stream *es = s_alloc(mem, "s_add_filter(stream)");
+ stream_state *ess = (ss == 0 ? (stream_state *)es : ss);
+ uint bsize = max(template->min_out_size, 256); /* arbitrary */
+ byte *buf = gs_alloc_bytes(mem, bsize, "s_add_filter(buf)");
+
+ if (es == 0 || buf == 0) {
+ gs_free_object(mem, buf, "s_add_filter(buf)");
+ gs_free_object(mem, es, "s_add_filter(stream)");
+ return 0;
+ }
+ ess->template = template;
+ ess->memory = mem;
+ es->memory = mem;
+ s_init_filter(es, ess, buf, bsize, *ps);
+ *ps = es;
+ return es;
+}
+
+/*
+ * Close the filters in a pipeline, up to a given target stream, freeing
+ * their buffers and state structures.
+ */
+int
+s_close_filters(stream **ps, stream *target)
+{
+ while (*ps != target) {
+ stream *s = *ps;
+ gs_memory_t *mem = s->state->memory;
+ byte *sbuf = s->cbuf;
+ stream *next = s->strm;
+ int status = sclose(s);
+ stream_state *ss = s->state; /* sclose may set this to s */
+
+ if (status < 0)
+ return status;
+ if (mem) {
+ gs_free_object(mem, sbuf, "s_close_filters(buf)");
+ gs_free_object(mem, s, "s_close_filters(stream)");
+ if (ss != (stream_state *)s)
+ gs_free_object(mem, ss, "s_close_filters(state)");
+ }
+ *ps = next;
+ }
+ return 0;
+}
diff --git a/gs/src/stream.h b/gs/src/stream.h
index c386e6142..95ebcdc9f 100644
--- a/gs/src/stream.h
+++ b/gs/src/stream.h
@@ -159,9 +159,12 @@ struct stream_s {
int (*save_close)(P1(stream *)); /* save original close proc */
};
-#define private_st_stream() /* in stream.c */\
- gs_private_st_composite_final(st_stream, stream, "stream",\
+/* The descriptor is only public for subclassing. */
+extern_st(st_stream);
+#define public_st_stream() /* in stream.c */\
+ gs_public_st_composite_final(st_stream, stream, "stream",\
stream_enum_ptrs, stream_reloc_ptrs, stream_finalize)
+#define STREAM_NUM_PTRS 5
/* Initialize the checking IDs of a stream. */
#define s_init_ids(s) ((s)->read_id = (s)->write_id = 1)
@@ -295,8 +298,12 @@ int spseek(P2(stream *, long));
/* Allocate a stream or a stream state. */
stream *s_alloc(P2(gs_memory_t *, client_name_t));
stream_state *s_alloc_state(P3(gs_memory_t *, gs_memory_type_ptr_t, client_name_t));
-/* Initialize a separately allocated stream, as if allocated by s_alloc. */
+/*
+ * Initialize a separately allocated stream or stream state, as if allocated
+ * by s_alloc[_state].
+ */
void s_init(P2(stream *, gs_memory_t *));
+void s_init_state(P3(stream_state *, const stream_template *, gs_memory_t *));
/* Create a stream on a string or a file. */
void sread_string(P3(stream *, const byte *, uint)),
@@ -328,4 +335,20 @@ int s_filter_write_flush(P1(stream *)), s_filter_close(P1(stream *));
/* Generic procedure structures for filters. */
extern const stream_procs s_filter_read_procs, s_filter_write_procs;
+/*
+ * Add a filter to a pipeline. The client must have allocated the stream
+ * state, if any, using the given allocator. For s_init_filter, the
+ * client must have called s_init and s_init_state.
+ */
+int s_init_filter(P5(stream *fs, stream_state *fss, byte *buf, uint bsize,
+ stream *target));
+stream *s_add_filter(P4(stream **ps, const stream_template *template,
+ stream_state *ss, gs_memory_t *mem));
+
+/*
+ * Close the filters in a pipeline, up to a given target stream, freeing
+ * their buffers and state structures.
+ */
+int s_close_filters(P2(stream **ps, stream *target));
+
#endif /* stream_INCLUDED */
diff --git a/gs/src/strimpl.h b/gs/src/strimpl.h
index 55e0301d3..5839c635e 100644
--- a/gs/src/strimpl.h
+++ b/gs/src/strimpl.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1995, 1997 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1993, 1995, 1997, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -98,6 +98,17 @@
*/
/*
+ * The set_defaults procedure in the template has a dual purpose: it sets
+ * default values for all parameters that the client can set before calling
+ * the init procedure, and it also must initialize all pointers in the
+ * stream state to a value that will be valid for the garbage collector
+ * (normally 0). The latter implies that:
+ *
+ * Any stream whose state includes additional pointers (beyond those
+ * in stream_state_common) must have a set_defaults procedure.
+ */
+
+/*
* Define a template for creating a stream.
*
* The meaning of min_in_size and min_out_size is the following:
@@ -113,24 +124,25 @@ struct stream_template_s {
gs_memory_type_ptr_t stype;
/* Define an optional initialization procedure. */
- stream_proc_init((*init));
+ stream_proc_init((*init));
/* Define the processing procedure. */
/* (The init procedure can reset other procs if it wants.) */
- stream_proc_process((*process));
+ stream_proc_process((*process));
/* Define the minimum buffer sizes. */
uint min_in_size; /* minimum size for process input */
uint min_out_size; /* minimum size for process output */
/* Define an optional releasing procedure. */
- stream_proc_release((*release));
+ stream_proc_release((*release));
- /* Define an optional parameter defaulting procedure. */
- stream_proc_set_defaults((*set_defaults));
+ /* Define an optional parameter defaulting and pointer initialization */
+ /* procedure. */
+ stream_proc_set_defaults((*set_defaults));
/* Define an optional reinitialization procedure. */
- stream_proc_reinit((*reinit));
+ stream_proc_reinit((*reinit));
};
diff --git a/gs/src/string_.h b/gs/src/string_.h
index 56ed611fa..033b9c1a5 100644
--- a/gs/src/string_.h
+++ b/gs/src/string_.h
@@ -29,24 +29,16 @@
# include <strings.h>
# define strchr index
#else
-# ifdef __TURBOC__
-# undef memset /* just in case */
-# include <string.h>
-# ifndef memset /* Borland C++ can inline this */
-# define memset(dest,chr,cnt) setmem(dest,cnt,chr)
-# endif
-# else
-# ifdef MEMORY__NEED_MEMMOVE
-# undef memmove /* This is disgusting, but so is GCC */
-# endif
-# include <string.h>
-# if defined(THINK_C)
+# ifdef MEMORY__NEED_MEMMOVE
+# undef memmove /* This is disgusting, but so is GCC */
+# endif
+# include <string.h>
+# if defined(THINK_C)
/* Patch strlen to return a uint rather than a size_t. */
-# define strlen (uint)strlen
-# endif
-# ifdef MEMORY__NEED_MEMMOVE
-# define memmove(dest,src,len) gs_memmove(dest,src,len)
-# endif
+# define strlen (uint)strlen
+# endif
+# ifdef MEMORY__NEED_MEMMOVE
+# define memmove(dest,src,len) gs_memmove(dest,src,len)
# endif
#endif
diff --git a/gs/src/szlibc.c b/gs/src/szlibc.c
index c4bcbcd66..0e6fecfa0 100644
--- a/gs/src/szlibc.c
+++ b/gs/src/szlibc.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995, 1997, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1995, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -46,6 +46,8 @@ s_zlib_set_defaults(stream_state * st)
/* DEF_MEM_LEVEL should be in zlib.h or zconf.h, but it isn't. */
ss->memLevel = min(MAX_MEM_LEVEL, 8);
ss->strategy = Z_DEFAULT_STRATEGY;
+ /* Clear pointers */
+ ss->dynamic = 0;
}
/* Allocate the dynamic state. */
diff --git a/gs/src/ugcclib.mak b/gs/src/ugcclib.mak
index 39d8102e5..080475c45 100644
--- a/gs/src/ugcclib.mak
+++ b/gs/src/ugcclib.mak
@@ -59,9 +59,12 @@ ZLIB_NAME=z
CC=gcc
CCLD=$(CC)
-GCFLAGS=-Wall -Wcast-qual -Wpointer-arith -Wstrict-prototypes -Wwrite-strings -fno-builtin -fno-common
+GCFLAGS_NO_WARN=-fno-builtin -fno-common
+GCFLAGS_WARNINGS=-Wall -Wcast-qual -Wpointer-arith -Wstrict-prototypes -Wwrite-strings
+GCFLAGS=$(GCFLAGS_NO_WARN) $(GCFLAGS_WARNINGS)
XCFLAGS=
CFLAGS=-g -O $(GCFLAGS) $(XCFLAGS)
+CFLAGS_NO_WARN=-g -O $(GCFLAGS_NO_WARN) $(XCFLAGS)
LDFLAGS=$(XLDFLAGS)
EXTRALIBS=
XINCLUDE=-I/usr/local/X/include
@@ -111,6 +114,7 @@ CCFLAGS=$(GENOPT) $(CFLAGS)
CC_=$(CC) $(CCFLAGS)
CCAUX=$(CC)
CC_LEAF=$(CC_)
+CC_NO_WARN=$(CC) $(GENOPT) $(CFLAGS_NO_WARN)
# When using gcc, CCA2K isn't needed....
CCA2K=$(CC)
diff --git a/gs/src/unix-aux.mak b/gs/src/unix-aux.mak
index 43e9f52a2..2eaf4649e 100644
--- a/gs/src/unix-aux.mak
+++ b/gs/src/unix-aux.mak
@@ -30,17 +30,6 @@ UNIX_AUX_MAK=$(GLSRC)unix-aux.mak
# We have to include a test for the existence of sys/time.h,
# because some System V platforms don't have it.
-# Define pipes as a separable feature.
-
-pipe_=$(GLOBJ)gdevpipe.$(OBJ)
-$(GLD)pipe.dev: $(UNIX_AUX_MAK) $(ECHOGS_XE) $(pipe_)
- $(SETMOD) $(GLD)pipe $(pipe_)
- $(ADDMOD) $(GLD)pipe -iodev pipe
-
-$(GLOBJ)gdevpipe.$(OBJ): $(GLSRC)gdevpipe.c $(AK) $(errno__h) $(pipe__h) $(stdio__h) $(string__h) \
- $(gserror_h) $(gsmemory_h) $(gstypes_h) $(gxiodev_h) $(stream_h)
- $(GLCC) $(GLO_)gdevpipe.$(OBJ) $(C_) $(GLSRC)gdevpipe.c
-
# Unix platforms other than System V, and also System V Release 4
# (SVR4) platforms.
unix__=$(GLOBJ)gp_getnv.$(OBJ) $(GLOBJ)gp_nofb.$(OBJ) $(GLOBJ)gp_unix.$(OBJ) $(GLOBJ)gp_unifs.$(OBJ) $(GLOBJ)gp_unifn.$(OBJ)
diff --git a/gs/src/unix-gcc.mak b/gs/src/unix-gcc.mak
index 7a84b8545..e50210dcb 100755
--- a/gs/src/unix-gcc.mak
+++ b/gs/src/unix-gcc.mak
@@ -52,8 +52,7 @@ PSD=$(PSGENDIR)/
# the directories also define the default search path for the
# initialization files (gs_*.ps) and the fonts.
-# If your system has installbsd, change install to installbsd in the next line.
-INSTALL = install -c
+INSTALL = $(GLSRCDIR)/instcopy -c
INSTALL_PROGRAM = $(INSTALL) -m 755
INSTALL_DATA = $(INSTALL) -m 644
@@ -183,7 +182,7 @@ CCLD=$(CC)
# the 2.7.0-2.7.2 optimizer bug, either "-Dconst=" or
# "-Wcast-qual -Wwrite-strings" is automatically included.
-GCFLAGS=-Wall -Wstrict-prototypes -Wtraditional -fno-builtin -fno-common
+GCFLAGS=-Wall -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -Wtraditional -fno-builtin -fno-common
# Define the added flags for standard, debugging, and profiling builds.
@@ -275,11 +274,15 @@ SYNC=posync
# Choose the language feature(s) to include. See gs.mak for details.
# Note that there is one feature that requires a GNU library:
# $(PSD)gnrdline.dev, which adds support for GNU readline, including
-# on-the-fly name completion and evaluation. For details, see gp_gnrdl.c.
+# on-the-fly name completion and evaluation. For details, including
+# licensing problems that will arise if you add this feature to Aladdin
+# Ghostscript releases, see gp_gnrdl.c.
-#FEATURE_DEVS=$(PSD)psl3.dev $(PSD)pdf.dev $(PSD)dpsnext.dev $(PSD)ttfont.dev $(PSD)pipe.dev
-FEATURE_DEVS=$(PSD)psl3.dev $(PSD)pdf.dev $(PSD)dpsnext.dev $(PSD)ttfont.dev $(PSD)pipe.dev $(PSD)rasterop.dev
-#FEATURE_DEVS=$(PSD)psl3.dev $(PSD)pdf.dev $(PSD)dpsnext.dev $(PSD)ttfont.dev $(PSD)pipe.dev $(PSD)rasterop.dev $(PSD)double.dev $(PSD)trapping.dev $(PSD)compht.dev
+FEATURE_DEVS=$(PSD)psl3.dev $(PSD)pdf.dev $(PSD)dpsnext.dev $(PSD)ttfont.dev $(PSD)pipe.dev
+#FEATURE_DEVS=$(PSD)psl3.dev $(PSD)pdf.dev $(PSD)dpsnext.dev $(PSD)ttfont.dev $(PSD)pipe.dev $(PSD)rasterop.dev
+# The following is strictly for testing.
+FEATURE_DEVS_ALL=$(PSD)psl3.dev $(PSD)pdf.dev $(PSD)dpsnext.dev $(PSD)ttfont.dev $(PSD)pipe.dev $(PSD)rasterop.dev $(PSD)double.dev $(PSD)trapping.dev $(PSD)compht.dev $(PSD)gnrdline.dev
+#FEATURE_DEVS=$(FEATURE_DEVS_ALL)
# Choose whether to compile the .ps initialization files into the executable.
# See gs.mak for details.
@@ -302,13 +305,34 @@ BAND_LIST_COMPRESSOR=zlib
FILE_IMPLEMENTATION=stdio
+# Define the name table capacity size of 2^(16+n).
+# Setting this to a non-zero value will slow down the interpreter.
+
+EXTEND_NAMES=0
+
# Choose the device(s) to include. See devs.mak for details,
# devs.mak and contrib.mak for the list of available devices.
DEVICE_DEVS=$(DD)x11.dev $(DD)x11alpha.dev $(DD)x11cmyk.dev $(DD)x11gray2.dev $(DD)x11gray4.dev $(DD)x11mono.dev
-DEVICE_DEVS1=$(DD)bmpmono.dev $(DD)bmpsep1.dev $(DD)bmpsep8.dev $(DD)bmp16.dev $(DD)bmp256.dev $(DD)bmp16m.dev $(DD)bmp32b.dev
-DEVICE_DEVS2=$(DD)bmpamono.dev $(DD)bmpasep1.dev $(DD)bmpasep8.dev $(DD)bmpa16.dev $(DD)bmpa256.dev $(DD)bmpa16m.dev $(DD)bmpa32b.dev
+
+#DEVICE_DEVS1=
#DEVICE_DEVS2=
+#DEVICE_DEVS3=
+#DEVICE_DEVS4=
+#DEVICE_DEVS5=
+#DEVICE_DEVS6=
+#DEVICE_DEVS7=
+#DEVICE_DEVS8=
+#DEVICE_DEVS9=
+#DEVICE_DEVS10=
+#DEVICE_DEVS11=
+#DEVICE_DEVS12=
+#DEVICE_DEVS13=
+#DEVICE_DEVS14=
+#DEVICE_DEVS15=
+
+DEVICE_DEVS1=$(DD)bmpmono.dev $(DD)bmpgray.dev $(DD)bmpsep1.dev $(DD)bmpsep8.dev $(DD)bmp16.dev $(DD)bmp256.dev $(DD)bmp16m.dev $(DD)bmp32b.dev
+DEVICE_DEVS2=$(DD)bmpamono.dev $(DD)bmpasep1.dev $(DD)bmpasep8.dev $(DD)bmpa16.dev $(DD)bmpa256.dev $(DD)bmpa16m.dev $(DD)bmpa32b.dev
DEVICE_DEVS3=$(DD)deskjet.dev $(DD)djet500.dev $(DD)laserjet.dev $(DD)ljetplus.dev $(DD)ljet2p.dev $(DD)ljet3.dev $(DD)ljet3d.dev $(DD)ljet4.dev $(DD)ljet4d.dev $(DD)lj5mono.dev $(DD)lj5gray.dev
DEVICE_DEVS4=$(DD)cdeskjet.dev $(DD)cdjcolor.dev $(DD)cdjmono.dev $(DD)cdj550.dev $(DD)pj.dev $(DD)pjxl.dev $(DD)pjxl300.dev
DEVICE_DEVS5=$(DD)uniprint.dev
@@ -322,6 +346,7 @@ DEVICE_DEVS12=$(DD)psmono.dev $(DD)psgray.dev $(DD)psrgb.dev $(DD)bit.dev $(DD)b
DEVICE_DEVS13=$(DD)pngmono.dev $(DD)pnggray.dev $(DD)png16.dev $(DD)png256.dev $(DD)png16m.dev
DEVICE_DEVS14=$(DD)jpeg.dev $(DD)jpeggray.dev
DEVICE_DEVS15=$(DD)pdfwrite.dev $(DD)pswrite.dev $(DD)epswrite.dev $(DD)pxlmono.dev $(DD)pxlcolor.dev
+
DEVICE_DEVS16=
DEVICE_DEVS17=
DEVICE_DEVS18=
@@ -350,6 +375,9 @@ CCAUX=$(CC) `cat $(AK)`
CC_LEAF=$(CC_) -fomit-frame-pointer
# gcc can't use -fomit-frame-pointer with -pg.
CC_LEAF_PG=$(CC_)
+# These are the specific warnings we have to turn off to compile those
+# specific few files that need this. We may turn off others in the future.
+CC_NO_WARN=$(CC_) -Wno-cast-qual -Wno-traditional
# ---------------- End of platform-specific section ---------------- #
diff --git a/gs/src/unixansi.mak b/gs/src/unixansi.mak
index 45c0f2b82..e61012016 100755
--- a/gs/src/unixansi.mak
+++ b/gs/src/unixansi.mak
@@ -52,8 +52,7 @@ PSD=$(PSGENDIR)/
# the directories also define the default search path for the
# initialization files (gs_*.ps) and the fonts.
-# If your system has installbsd, change install to installbsd in the next line.
-INSTALL = install -c
+INSTALL = $(GLSRCDIR)/instcopy -c
INSTALL_PROGRAM = $(INSTALL) -m 755
INSTALL_DATA = $(INSTALL) -m 644
@@ -333,6 +332,7 @@ CC_=$(CC) $(CCFLAGS)
CCAUX=$(CC)
CC_LEAF=$(CC_)
CC_LEAF_PG=$(CC_)
+CC_NO_WARN=$(CC_)
# ---------------- End of platform-specific section ---------------- #
diff --git a/gs/src/unixinst.mak b/gs/src/unixinst.mak
index f57cfb6ee..8b63cabcd 100644
--- a/gs/src/unixinst.mak
+++ b/gs/src/unixinst.mak
@@ -61,14 +61,14 @@ install-data: man/gs.1
-mkdir $(gsdatadir)
-mkdir $(gsdatadir)/lib
cd lib; $(SH) -c 'for f in \
-Fontmap \
+Fontmap Fontmap.GS \
cbjc600.ppd cbjc800.ppd *.upp \
gs_init.ps gs_btokn.ps gs_ccfnt.ps gs_cff.ps gs_cidfn.ps gs_cmap.ps \
gs_diskf.ps gs_dpnxt.ps gs_dps.ps gs_dps1.ps gs_dps2.ps gs_epsf.ps \
gs_fonts.ps gs_kanji.ps gs_lev2.ps gs_ll3.ps \
gs_pfile.ps gs_rdlin.ps gs_res.ps gs_setpd.ps gs_statd.ps \
gs_trap.ps gs_ttf.ps gs_typ32.ps gs_typ42.ps gs_type1.ps \
-gs_dbt_e.ps gs_iso_e.ps gs_ksb_e.ps gs_std_e.ps gs_sym_e.ps \
+gs_dbt_e.ps gs_il1_e.ps gs_il2_e.ps gs_ksb_e.ps gs_std_e.ps gs_sym_e.ps \
ht_ccbnm.ps \
acctest.ps align.ps bdftops.ps caption.ps cid2code.ps decrypt.ps docie.ps \
errpage.ps font2c.ps font2pcl.ps gslp.ps impath.ps \
@@ -83,7 +83,8 @@ winmaps.ps wftopfa.ps wrfont.ps zeroline.ps \
gs_l2img.ps \
pdf2dsc.ps \
pdf_base.ps pdf_draw.ps pdf_font.ps pdf_main.ps pdf_ops.ps pdf_sec.ps \
-gs_mex_e.ps gs_mro_e.ps gs_pdf_e.ps gs_wan_e.ps \
+gs_lgo_e.ps gs_lgx_e.ps gs_mex_e.ps gs_mgl_e.ps gs_mro_e.ps \
+gs_pdf_e.ps gs_wan_e.ps \
gs_pdfwr.ps ;\
do if ( test -f $$f ); then $(INSTALL_DATA) $$f $(gsdatadir)/lib/$$f; fi;\
done'
@@ -93,10 +94,11 @@ PUBLIC README \
ps2epsi.txt \
Bug-form.htm C-style.htm Commprod.htm Copying.htm Current.htm \
DLL.htm Devices.htm Drivers.htm Fonts.htm \
-Helpers.htm Hershey.htm History1.htm History2.htm History3.htm History4.htm \
+Helpers.htm Hershey.htm \
+History1.htm History2.htm History3.htm History4.htm History5.htm \
Htmstyle.htm Humor.htm Install.htm Language.htm Lib.htm Make.htm New-user.htm \
-News.htm Ps2pdf.htm Psfiles.htm Public.htm \
-Readme.htm Source.htm Unix-lpr.htm Use.htm Xfonts.htm ;\
+News.htm Ps2pdf.htm Psfiles.htm Public.htm Readme.htm Release.htm \
+Source.htm Tester.htm Unix-lpr.htm Use.htm Xfonts.htm ;\
do if ( test -f $$f ); then $(INSTALL_DATA) $$f $(docdir)/$$f; fi;\
done'
-mkdir $(exdir)
diff --git a/gs/src/unixtrad.mak b/gs/src/unixtrad.mak
index 830d30788..86b09ba23 100644
--- a/gs/src/unixtrad.mak
+++ b/gs/src/unixtrad.mak
@@ -52,8 +52,7 @@ PSD=$(PSGENDIR)/
# the directories also define the default search path for the
# initialization files (gs_*.ps) and the fonts.
-# If your system has installbsd, change install to installbsd in the next line.
-INSTALL = install -c
+INSTALL = $(GLSRCDIR)/instcopy -c
INSTALL_PROGRAM = $(INSTALL) -m 755
INSTALL_DATA = $(INSTALL) -m 644
@@ -336,6 +335,7 @@ CCA2K=$(CC)
CCAUX=$(GLSRCDIR)/ccgs $(AK) "$(CC)"
CC_LEAF=$(CC_)
CC_LEAF_PG=$(CC_)
+CC_NO_WARN=$(CC_)
# ---------------- End of platform-specific section ---------------- #
diff --git a/gs/src/version.mak b/gs/src/version.mak
index bc7053dcf..d1f84ef3b 100644
--- a/gs/src/version.mak
+++ b/gs/src/version.mak
@@ -21,10 +21,10 @@
# Major and minor version numbers.
# MINOR0 is different from MINOR only if MINOR is a single digit.
GS_VERSION_MAJOR=5
-GS_VERSION_MINOR=84
-GS_VERSION_MINOR0=84
+GS_VERSION_MINOR=93
+GS_VERSION_MINOR0=93
# Revision date: year x 10000 + month x 100 + day.
-GS_REVISIONDATE=19990519
+GS_REVISIONDATE=19990911
# Derived values
GS_VERSION=$(GS_VERSION_MAJOR)$(GS_VERSION_MINOR0)
GS_DOT_VERSION=$(GS_VERSION_MAJOR).$(GS_VERSION_MINOR)
diff --git a/gs/src/watc.mak b/gs/src/watc.mak
index 33f4a28da..dde7e2260 100644
--- a/gs/src/watc.mak
+++ b/gs/src/watc.mak
@@ -78,14 +78,14 @@ GS=gs386
# source, generated intermediate file, and object directories
# for the graphics library (GL) and the PostScript/PDF interpreter (PS).
-BINDIR=.\bin
-GLSRCDIR=.\src
-GLGENDIR=.\obj
-GLOBJDIR=.\obj
-PSSRCDIR=.\src
-PSLIBDIR=.\lib
-PSGENDIR=.\obj
-PSOBJDIR=.\obj
+BINDIR=bin
+GLSRCDIR=src
+GLGENDIR=obj
+GLOBJDIR=obj
+PSSRCDIR=src
+PSLIBDIR=lib
+PSGENDIR=obj
+PSOBJDIR=obj
# Do not edit the next group of lines.
NUL=
@@ -206,8 +206,13 @@ FILE_IMPLEMENTATION=stdio
# Choose the device(s) to include. See devs.mak for details,
# devs.mak and contrib.mak for the list of available devices.
-DEVICE_DEVS=$(DD)vga.dev $(DD)ega.dev $(DD)svga16.dev
-DEVICE_DEVS1=$(DD)atiw.dev $(DD)tseng.dev $(DD)tvga.dev
+# ****** NOTE: the PC frame buffer devices won't compile with the binnt
+# ****** compiler. If you know what needs to be changed, let us know!
+# ****** Probably it's just a compiler command line switch.
+#DEVICE_DEVS=$(DD)vga.dev $(DD)ega.dev $(DD)svga16.dev
+DEVICE_DEVS=
+#DEVICE_DEVS1=$(DD)atiw.dev $(DD)tseng.dev $(DD)tvga.dev
+DEVICE_DEVS1=
DEVICE_DEVS2=
DEVICE_DEVS3=$(DD)deskjet.dev $(DD)djet500.dev $(DD)laserjet.dev $(DD)ljetplus.dev $(DD)ljet2p.dev
DEVICE_DEVS4=$(DD)cdeskjet.dev $(DD)cdjcolor.dev $(DD)cdjmono.dev $(DD)cdj550.dev
@@ -217,7 +222,7 @@ DEVICE_DEVS7=
DEVICE_DEVS8=$(DD)pcxmono.dev $(DD)pcxgray.dev $(DD)pcx16.dev $(DD)pcx256.dev $(DD)pcx24b.dev $(DD)pcxcmyk.dev
DEVICE_DEVS9=
DEVICE_DEVS10=$(DD)tiffcrle.dev $(DD)tiffg3.dev $(DD)tiffg32d.dev $(DD)tiffg4.dev $(DD)tifflzw.dev $(DD)tiffpack.dev
-DEVICE_DEVS11=$(DD)bmpmono.dev $(DD)bmp16.dev $(DD)bmp256.dev $(DD)bmp16m.dev $(DD)tiff12nc.dev $(DD)tiff24nc.dev
+DEVICE_DEVS11=$(DD)bmpmono.dev $(DD)bmpgray.dev $(DD)bmp16.dev $(DD)bmp256.dev $(DD)bmp16m.dev $(DD)tiff12nc.dev $(DD)tiff24nc.dev
DEVICE_DEVS12=$(DD)psmono.dev $(DD)psgray.dev $(DD)bit.dev $(DD)bitrgb.dev $(DD)bitcmyk.dev
DEVICE_DEVS13=
DEVICE_DEVS14=$(DD)jpeg.dev $(DD)jpeggray.dev
diff --git a/gs/src/watcw32.mak b/gs/src/watcw32.mak
index fbae2358e..42dd7decd 100644
--- a/gs/src/watcw32.mak
+++ b/gs/src/watcw32.mak
@@ -22,8 +22,7 @@
# Someone with access to the Watcom 16-bit documentation will need to
# do this.
# Created 1997-02-23 by Russell Lang from MSVC++ 4.0 makefile.
-#**************** THIS MAKEFILE DOES NOT WORK. ****************
-#**************** DO NOT ATTEMPT TO USE IT. ****************
+# Major revisions 1999-07-26 by Ray Johnston.
# ------------------------------- Options ------------------------------- #
@@ -89,14 +88,14 @@ MAKEDLL=1
# source, generated intermediate file, and object directories
# for the graphics library (GL) and the PostScript/PDF interpreter (PS).
-BINDIR=.\bin
-GLSRCDIR=.\src
-GLGENDIR=.\obj
-GLOBJDIR=.\obj
-PSSRCDIR=.\src
-PSLIBDIR=.\lib
-PSGENDIR=.\obj
-PSOBJDIR=.\obj
+BINDIR=bin
+GLSRCDIR=src
+GLGENDIR=obj
+GLOBJDIR=obj
+PSSRCDIR=src
+PSLIBDIR=lib
+PSGENDIR=obj
+PSOBJDIR=obj
# Define the directory where the IJG JPEG library sources are stored,
# and the major version of the library that is stored there.
@@ -134,20 +133,18 @@ CFLAGS=
# COMPAUX is the compiler name for DOS utilities.
# RCOMP is the resource compiler name.
# LINK is the full linker path name.
-# WBIND is used for binding resources to an EXE or DLL
# Note that INCDIR and LIBDIR are always followed by a \,
# so if you want to use the current directory, use an explicit '.'.
-COMPBASE=d:\watcom
-COMPDIR=$(COMPBASE)\binb
-INCDIR=$(COMPBASE)\h;$(COMPBASE)\h\nt
+COMPBASE=$(%WATCOM)
+COMPDIR=$(COMPBASE)\binnt
+INCDIR=$(COMPBASE)\h -i$(COMPBASE)\h\nt
LIBDIR=$(COMPBASE)\lib386;$(COMPBASE)\lib386\nt
COMP=$(COMPDIR)\wcc386
COMPCPP=$(COMPDIR)\wpp386
COMPAUX=$(COMPDIR)\wcc386
RCOMP=$(COMPDIR)\wrc
LINK=$(COMPDIR)\wlink
-WBIND=$(COMPDIR)\wbind
# Define the processor architecture. (always i386)
CPU_FAMILY=i386
@@ -174,6 +171,12 @@ FPU_TYPE=0
SYNC=winsync
+# Do not edit the next group of lines.
+NUL=
+DD=$(GLGENDIR)\$(NUL)
+GLD=$(GLGENDIR)\$(NUL)
+PSD=$(GLGENDIR)\$(NUL)
+
# ------ Devices and features ------ #
# Choose the language feature(s) to include. See gs.mak for details.
@@ -204,24 +207,24 @@ FILE_IMPLEMENTATION=stdio
# Choose the device(s) to include. See devs.mak for details,
# devs.mak and contrib.mak for the list of available devices.
-DEVICE_DEVS=mswindll.dev mswinprn.dev mswinpr2.dev
-DEVICE_DEVS2=epson.dev eps9high.dev eps9mid.dev epsonc.dev ibmpro.dev
-DEVICE_DEVS3=deskjet.dev djet500.dev laserjet.dev ljetplus.dev ljet2p.dev
-DEVICE_DEVS4=cdeskjet.dev cdjcolor.dev cdjmono.dev cdj550.dev
-DEVICE_DEVS5=djet500c.dev declj250.dev lj250.dev jetp3852.dev r4081.dev lbp8.dev uniprint.dev
-DEVICE_DEVS6=st800.dev stcolor.dev bj10e.dev bj200.dev m8510.dev necp6.dev bjc600.dev bjc800.dev
-DEVICE_DEVS7=t4693d2.dev t4693d4.dev t4693d8.dev tek4696.dev
-DEVICE_DEVS8=pcxmono.dev pcxgray.dev pcx16.dev pcx256.dev pcx24b.dev pcxcmyk.dev
-DEVICE_DEVS9=pbm.dev pbmraw.dev pgm.dev pgmraw.dev pgnm.dev pgnmraw.dev pnm.dev pnmraw.dev ppm.dev ppmraw.dev
-DEVICE_DEVS10=tiffcrle.dev tiffg3.dev tiffg32d.dev tiffg4.dev tifflzw.dev tiffpack.dev
-DEVICE_DEVS11=bmpmono.dev bmp16.dev bmp256.dev bmp16m.dev tiff12nc.dev tiff24nc.dev
-DEVICE_DEVS12=psmono.dev bit.dev bitrgb.dev bitcmyk.dev
-DEVICE_DEVS13=pngmono.dev pnggray.dev png16.dev png256.dev png16m.dev
-DEVICE_DEVS14=jpeg.dev jpeggray.dev
-DEVICE_DEVS15=pdfwrite.dev pswrite.dev epswrite.dev pxlmono.dev pxlcolor.dev
+DEVICE_DEVS=$(DD)mswindll.dev $(DD)mswinprn.dev $(DD)mswinpr2.dev
+DEVICE_DEVS2=$(DD)epson.dev $(DD)eps9high.dev $(DD)eps9mid.dev $(DD)epsonc.dev $(DD)ibmpro.dev
+DEVICE_DEVS3=$(DD)deskjet.dev $(DD)djet500.dev $(DD)laserjet.dev $(DD)ljetplus.dev $(DD)ljet2p.dev
+DEVICE_DEVS4=$(DD)cdeskjet.dev $(DD)cdjcolor.dev $(DD)cdjmono.dev $(DD)cdj550.dev
+DEVICE_DEVS5=$(DD)djet500c.dev $(DD)declj250.dev $(DD)lj250.dev $(DD)jetp3852.dev $(DD)r4081.dev $(DD)lbp8.dev $(DD)uniprint.dev
+DEVICE_DEVS6=$(DD)st800.dev $(DD)stcolor.dev $(DD)bj10e.dev $(DD)bj200.dev $(DD)m8510.dev $(DD)necp6.dev $(DD)bjc600.dev $(DD)bjc800.dev
+DEVICE_DEVS7=$(DD)t4693d2.dev $(DD)t4693d4.dev $(DD)t4693d8.dev $(DD)tek4696.dev
+DEVICE_DEVS8=$(DD)pcxmono.dev $(DD)pcxgray.dev $(DD)pcx16.dev $(DD)pcx256.dev $(DD)pcx24b.dev $(DD)pcxcmyk.dev
+DEVICE_DEVS9=$(DD)pbm.dev $(DD)pbmraw.dev $(DD)pgm.dev $(DD)pgmraw.dev $(DD)pgnm.dev $(DD)pgnmraw.dev $(DD)pnm.dev $(DD)pnmraw.dev $(DD)ppm.dev $(DD)ppmraw.dev
+DEVICE_DEVS10=$(DD)tiffcrle.dev $(DD)tiffg3.dev $(DD)tiffg32d.dev $(DD)tiffg4.dev $(DD)tifflzw.dev $(DD)tiffpack.dev
+DEVICE_DEVS11=$(DD)bmpmono.dev $(DD)bmp16.dev $(DD)bmp256.dev $(DD)bmp16m.dev $(DD)tiff12nc.dev $(DD)tiff24nc.dev
+DEVICE_DEVS12=$(DD)psmono.dev $(DD)bit.dev $(DD)bitrgb.dev $(DD)bitcmyk.dev
+DEVICE_DEVS13=$(DD)pngmono.dev $(DD)pnggray.dev $(DD)png16.dev $(DD)png256.dev $(DD)png16m.dev
+DEVICE_DEVS14=$(DD)jpeg.dev $(DD)jpeggray.dev
+DEVICE_DEVS15=$(DD)pdfwrite.dev $(DD)pswrite.dev $(DD)epswrite.dev $(DD)pxlmono.dev $(DD)pxlcolor.dev
# Overflow for DEVS3,4,5,6,9
-DEVICE_DEVS16=ljet3.dev ljet3d.dev ljet4.dev ljet4d.dev
-DEVICE_DEVS17=pj.dev pjxl.dev pjxl300.dev
+DEVICE_DEVS16=$(DD)ljet3.dev $(DD)ljet3d.dev $(DD)ljet4.dev $(DD)ljet4d.dev
+DEVICE_DEVS17=$(DD)pj.dev $(DD)pjxl.dev $(DD)pjxl300.dev
DEVICE_DEVS18=
DEVICE_DEVS19=
DEVICE_DEVS20=
@@ -242,7 +245,7 @@ SH=
# Define the arguments for genconf.
-CONFILES=-p %%s, -l $(GLGENDIR)\lib.tr
+CONFILES=-e ~ -p FILE~s~ps
CONFLDTR=-o
# Define the generic compilation flags.
@@ -294,7 +297,7 @@ CP=
!endif
!ifneq DEBUG 0
-CD=/DDEBUG
+CD=-dDEBUG
!else
CD=
!endif
@@ -309,8 +312,8 @@ COMPILE_WITHOUT_FRAMES= # no optimization when debugging
!else
CT=-d1
LCT=DEBUG LINES
-COMPILE_FULL_OPTIMIZED=-Oilmre -s
-COMPILE_WITH_FRAMES=-Of+
+COMPILE_FULL_OPTIMIZED=-oilmre -s
+COMPILE_WITH_FRAMES=-of+
COMPILE_WITHOUT_FRAMES=-s
!endif
@@ -321,15 +324,15 @@ CS=-s
!endif
# Specify function prolog type
-COMPILE_FOR_DLL=/LD
+COMPILE_FOR_DLL=-bd
COMPILE_FOR_EXE=
COMPILE_FOR_CONSOLE_EXE=
-GENOPT=$(CP) $(CD) $(CT) $(CS) -zq
+GENOPT=-d+ $(CP) $(CD) $(CT) $(CS) -zq -zp8
CCFLAGS=$(PLATOPT) $(FPFLAGS) $(CPFLAGS) $(CFLAGS) $(XCFLAGS)
-CC=$(COMP) -c $(CCFLAGS) @$(GLGENDIR)\ccf32.tr
-CPP=$(COMPCPP) -c $(CCFLAGS) @$(GLGENDIR)\ccf32.tr
+CC=$(COMP) $(CCFLAGS) @$(GLGENDIR)\ccf32.tr
+CPP=$(COMPCPP) $(CCFLAGS) @$(GLGENDIR)\ccf32.tr
!ifneq MAKEDLL 0
WX=$(COMPILE_FOR_DLL)
!else
@@ -340,13 +343,14 @@ CC_=$(CC_WX) $(COMPILE_FULL_OPTIMIZED)
CC_D=$(CC_WX) $(COMPILE_WITH_FRAMES)
CC_INT=$(CC)
CC_LEAF=$(CC_) $(COMPILE_WITHOUT_FRAMES)
+CC_NO_WARN=$(CC_)
# No additional flags are needed for Windows compilation.
CCWINFLAGS=
# Compiler for auxiliary programs
-CCAUX=$(COMPAUX) -I$(INCDIR) -O
+CCAUX=$(COMPAUX) -I$(INCDIR) -otexan
# Define the files to be removed by `make clean'.
# nmake expands macros when encountered, not when used,
@@ -354,8 +358,15 @@ CCAUX=$(COMPAUX) -I$(INCDIR) -O
BEGINFILES2=gsdll32.rex gswin32.rex gswin32c.rex
+# Define the switches for the compilers.
+
+C_=
+O_=-fo=
+RO_=$(O_)
+
# Include the generic makefiles.
+!include $(GLSRCDIR)\version.mak
!include $(GLSRCDIR)\winlib.mak
!include $(GLSRCDIR)\winint.mak
@@ -364,8 +375,47 @@ BEGINFILES2=gsdll32.rex gswin32.rex gswin32c.rex
$(GLGENDIR)\ccf32.tr: $(TOP_MAKEFILES)
echo $(GENOPT) -I$(INCDIR) -DCHECK_INTERRUPTS -D_Windows -D__WIN32__ -D_WATCOM_ > $(GLGENDIR)\ccf32.tr
+$(ECHOGS_XE): $(GLSRC)echogs.c
+ $(CCAUX) $(GLSRC)echogs.c $(O_)$(GLOBJ)echogs.obj
+ $(LINK) FILE $(GLOBJ)echogs.obj NAME $(ECHOGS_XE)
+
+# Don't create genarch if it's not needed
+!ifdef GENARCH_XE
+$(GENARCH_XE): $(GLSRC)genarch.c $(GENARCH_DEPS) $(GLGENDIR)\ccf32.tr
+ $(CCAUX) $(GLSRC)genarch.c @$(GLGENDIR)\ccf32.tr $(O_)$(GLOBJ)genarch.obj
+ $(LINK) FILE $(GLOBJ)genarch.obj NAME $(GENARCH_XE)
+!endif
+
+$(GENCONF_XE): $(GLSRC)genconf.c $(GENCONF_DEPS)
+ $(CCAUX) $(GLSRC)genconf.c $(O_)$(GLOBJ)genconf.obj
+ $(LINK) FILE $(GLOBJ)genconf.obj NAME $(GENCONF_XE)
+
+$(GENDEV_XE): $(GLSRC)gendev.c $(GENDEV_DEPS)
+ $(CCAUX) $(GLSRC)gendev.c $(O_)$(GLOBJ)gendev.obj
+ $(LINK) FILE $(GLOBJ)gendev.obj NAME $(GENDEV_XE)
+
+$(GENHT_XE): $(GLSRC)genht.c $(GENHT_DEPS)
+ $(CCAUX) $(GENHT_CFLAGS) $(GLSRC)genht.c $(O_)$(GLOBJ)genht.obj
+ $(LINK) FILE $(GLOBJ)genht.obj NAME $(GENHT_XE)
+
+# PSSRC and PSOBJ aren't defined yet, so we spell out the definitions.
+$(GENINIT_XE): $(PSSRCDIR)$(D)geninit.c $(GENINIT_DEPS)
+ $(CCAUX) $(PSSRCDIR)$(D)geninit.c $(O_)$(PSOBJDIR)$(D)geninit.obj
+ $(LINK) FILE $(GLOBJ)geninit.obj NAME $(GENINIT_XE)
+
# -------------------------------- Library -------------------------------- #
+# make sure the target directories exist - use special Watcom .BEFORE
+# (This is not the best way to do this, but we will have to wait until
+# the makefiles get disentangled to do it better.)
+.BEFORE
+ @if not exist $(GLGENDIR) mkdir $(GLGENDIR)
+ @if not exist $(GLOBJDIR) mkdir $(GLOBJDIR)
+ @if not exist $(PSGENDIR) mkdir $(PSGENDIR)
+ @if not exist $(PSOBJDIR) mkdir $(PSOBJDIR)
+ @if not exist $(BINDIR) mkdir $(BINDIR)
+ @if not exist $(GLGENDIR)\lib.tr copy nul: $(GLGENDIR)\lib.tr
+
# See winlib.mak
# ----------------------------- Main program ------------------------------ #
@@ -373,48 +423,50 @@ $(GLGENDIR)\ccf32.tr: $(TOP_MAKEFILES)
#LIBCTR=libc32.tr
LIBCTR=
-#rjl
-#$(LIBCTR): $(TOP_MAKEFILES) $(ECHOGS_XE)
-# echogs -w $(LIBCTR) $(LIBDIR)\shell32.lib
-# echogs -a $(LIBCTR) $(LIBDIR)\comdlg32.lib
+GSCONSOLE_XE=$(BINDIR)\$(GSCONSOLE).exe
+GSDLL_DLL=$(BINDIR)\$(GSDLL).dll
-DWOBJLINK=dwdll.obj, dwimg.obj, dwmain.obj, dwtext.obj, gscdefs.obj, gp_wgetv.obj
-DWOBJNOLINK= dwnodll.obj, dwimg.obj, dwmain.obj, dwtext.obj
-OBJCLINK=dwmainc.obj, dwdllc.obj, gscdefs.obj, gp_wgetv.obj
-OBJCNOLINK=dwmainc.obj, dwnodllc.obj
+DWOBJLINK=$(GLOBJ)dwdll.obj, $(GLOBJ)dwimg.obj, $(GLOBJ)dwmain.obj, $(GLOBJ)dwtext.obj, $(GLOBJ)gscdefw.obj, $(GLOBJ)gp_wgetw.obj
+DWOBJNOLINK= $(GLOBJ)dwnodll.obj, $(GLOBJ)dwimg.obj, $(GLOBJ)dwmain.obj, $(GLOBJ)dwtext.obj
+OBJCLINK=$(GLOBJ)dwmainc.obj, $(GLOBJ)dwdllc.obj, $(GLOBJ)gscdefw.obj, $(GLOBJ)gp_wgetw.obj
+OBJCNOLINK=$(GLOBJ)dwmainc.obj, $(GLOBJ)dwnodllc.obj
!ifneq MAKEDLL 0
+
+# The non DLL compiles of the some modules also in the DLL
+$(GLOBJ)gp_wgetw.$(OBJ): $(GLSRC)gp_wgetv.c $(AK) $(gscdefs_h)
+ $(CC) $(COMPILE_FOR_CONSOLE_EXE) $(GLCCFLAGS) $(CCWINFLAGS) $(I_)$(GLI_)$(_I) $(GLF_) $(GLO_)gp_wgetw.$(OBJ) $(C_) $(GLSRC)gp_wgetv.c
+
+$(GLOBJ)gscdefw.$(OBJ): $(GLGEN)gscdefs.c $(AK) $(gscdefs_h)
+ $(CC) $(COMPILE_FOR_CONSOLE_EXE) $(GLCCFLAGS) $(CCWINFLAGS) $(I_)$(GLI_)$(_I) $(GLF_) $(GLO_)gscdefw.$(OBJ) $(C_) $(GLGEN)gscdefs.c
+
# The graphical small EXE loader
-$(GS_XE): $(GSDLL).dll $(GSDLL).lib $(DWOBJ) $(GSCONSOLE).exe $(GS).res
- $(LINK) system nt_win $(LCT) Name $(GS_XE) File $(DWOBJLINK) Library $(GSDLL).lib
- $(WBIND) $(GS_XE) -R $(GS).res
+$(GS_XE): $(GSDLL_DLL) $(GLOBJ)$(GSDLL).lib $(DWOBJ) $(GSCONSOLE_XE) $(GLOBJ)$(GS).res \
+ $(GLOBJ)gp_wgetw.obj $(GLOBJ)gscdefw.obj
+ $(LINK) system nt_win $(LCT) Name $(GS_XE) File $(DWOBJLINK) Library $(GLOBJ)$(GSDLL).lib
# The console mode small EXE loader
-$(GSCONSOLE).exe: $(OBJC) $(GS).res dw32c.def
- $(LINK) system nt option map $(LCT) Name $(GSCONSOLE).exe File $(OBJCLINK) Library $(GSDLL).lib
- $(WBIND) $(GSCONSOLE).exe -R $(GS).res
+$(GSCONSOLE_XE): $(OBJC) $(GLOBJ)$(GS).res $(GLSRCDIR)\dw32c.def \
+ $(GLOBJ)gp_wgetw.obj $(GLOBJ)gscdefw.obj
+ $(LINK) system nt option map $(LCT) Name $(GSCONSOLE_XE) File $(OBJCLINK) Library $(GLOBJ)$(GSDLL).lib
# The big DLL
-$(GSDLL).dll: $(GS_ALL) $(DEVS_ALL) gsdll.$(OBJ) $(GSDLL).res
- $(LINK) system nt_dll initinstance terminstance @gsdll32.wex $(LCT) Name $(GSDLL).dll File gsdll.obj, @$(ld_tr)
- $(WBIND) $(GSDLL).dll -R $(GSDLL).res
+$(GSDLL_DLL): $(GS_ALL) $(DEVS_ALL) $(GLOBJ)gsdll.$(OBJ) $(GLOBJ)$(GSDLL).res
+ $(LINK) system nt_dll initinstance terminstance $(LCT) Name $(GSDLL_DLL) File $(GLOBJ)gsdll.obj @$(ld_tr) @$(GLSRC)gsdll32w.lnk
-$(GSDLL).lib: $(GSDLL).dll
- erase $(GSDLL).lib
- wlib $(GSDLL) +$(GSDLL).dll
+$(GLOBJ)$(GSDLL).lib: $(GSDLL_DLL)
+ erase $(GLOBJ)$(GSDLL).lib
+ wlib $(GLOBJ)$(GSDLL) +$(GSDLL_DLL)
!else
# The big graphical EXE
-$(GS_XE): $(GSCONSOLE).exe $(GS_ALL) $(DEVS_ALL) gsdll.$(OBJ) $(DWOBJNO) $(GS).res dwmain32.def
- $(LINK) option map $(LCT) Name $(GS) File gsdll, $(DWOBJNOLINK), @$(ld_tr)
- $(WBIND) $(GS_XE) -R $(GSDLL).res
+$(GS_XE): $(GSCONSOLE_XE) $(GS_ALL) $(DEVS_ALL) $(GLOBJ)gsdll.$(OBJ) $(DWOBJNO) $(GLOBJ)$(GS).res $(GLOBJ)dwmain32.def
+ $(LINK) option map $(LCT) Name $(GS) File $(GLOBJ)gsdll, $(DWOBJNOLINK) @$(ld_tr)
# The big console mode EXE
-$(GSCONSOLE).exe: $(GS_ALL) $(DEVS_ALL) gsdll.$(OBJ) $(OBJCNO) $(GS).res dw32c.def
- $(COMPDIR)\$(LINK) option map $(LCT) Name $(GSCONSOLE).exe File gsdll, $(OBJCNOLINK), @$(ld_tr)
- $(WBIND) $(GSCONSOLE).exe -R $(GSDLL).res
+$(GSCONSOLE_XE): $(GS_ALL) $(DEVS_ALL) $(GLOBJ)gsdll.$(OBJ) $(OBJCNO) $(GLOBJ)$(GS).res $(GLSRCDIR)\dw32c.def
+ $(COMPDIR)\$(LINK) option map $(LCT) Name $(GSCONSOLE_XE) File $(GLOBJ)gsdll, $(OBJCNOLINK), @$(ld_tr)
!endif
# end of makefile
-
diff --git a/gs/src/wccommon.mak b/gs/src/wccommon.mak
index 049460ee6..084cf6f5f 100644
--- a/gs/src/wccommon.mak
+++ b/gs/src/wccommon.mak
@@ -55,17 +55,18 @@ SHARE_ZLIB=0
NULL=
+C_=
CMD=.bat
D_=-D
-# Watcom C requires quoting parameter values with a - in them!
-_D_=$(NULL)="
-_D="
+_D_=$(NULL)=
+_D=
I_=-i=
II=-i=
_I=
NO_OP=%null
O_=-fo=
OBJ=obj
+RO_=$(O_)
XE=.exe
XEAUX=.exe
@@ -219,7 +220,7 @@ LCT=DEBUG LINES
GENOPT=$(CP) $(CD) $(CT) $(CS)
-CCOPT=-i=$(INCDIRS) -zq -zp8
+CCOPT=-d+ -i=$(INCDIRS) -zq -zp8
CCFLAGS=$(CCOPT) $(GENOPT) $(PLATOPT) $(FPFLAGS) $(CFLAGS) $(XCFLAGS)
CC=$(COMP) -oi $(CCFLAGS)
CCAUX=$(COMP) -oi $(CCOPT) $(FPFLAGS)
@@ -227,3 +228,4 @@ CC_=$(CC)
CC_D=$(CC)
CC_INT=$(COMP) -oit $(CCFLAGS)
CC_LEAF=$(CC_) -s
+CC_NO_WARN=$(CC_)
diff --git a/gs/src/winint.mak b/gs/src/winint.mak
index c665811d2..394308dcc 100644
--- a/gs/src/winint.mak
+++ b/gs/src/winint.mak
@@ -59,18 +59,18 @@ $(GLGEN)gstext.ico: $(GLSRC)gstext.icx $(ECHOGS_XE) $(WININT_MAK)
# resources for short EXE loader (no dialogs)
$(GS_OBJ).res: $(GLSRC)dwmain.rc $(dwmain_h) $(ICONS) $(WININT_MAK)
- $(ECHOGS_XE) -w $(GLGEN)_exe.rc -x 23 define -s gstext_ico $(GLGENDIR)/gstext.ico
- $(ECHOGS_XE) -a $(GLGEN)_exe.rc -x 23 define -s gsgraph_ico $(GLGENDIR)/gsgraph.ico
+ $(ECHOGS_XE) -w $(GLGEN)_exe.rc -x 23 define -s gstext_ico $(GLGENDIR)\gstext.ico
+ $(ECHOGS_XE) -a $(GLGEN)_exe.rc -x 23 define -s gsgraph_ico $(GLGENDIR)\gsgraph.ico
$(ECHOGS_XE) -a $(GLGEN)_exe.rc -R $(GLSRC)dwmain.rc
- $(RCOMP) -I$(GLSRCDIR) -i$(INCDIR) -r -fo$(GS_OBJ).res $(GLGEN)_exe.rc
+ $(RCOMP) -I$(GLSRCDIR) -i$(INCDIR)$(_I) -r $(RO_)$(GS_OBJ).res $(GLGEN)_exe.rc
del $(GLGEN)_exe.rc
# resources for main program (includes dialogs)
$(GSDLL_OBJ).res: $(GLSRC)gsdll32.rc $(gp_mswin_h) $(ICONS) $(WININT_MAK)
- $(ECHOGS_XE) -w $(GLGEN)_dll.rc -x 23 define -s gstext_ico $(GLGENDIR)/gstext.ico
- $(ECHOGS_XE) -a $(GLGEN)_dll.rc -x 23 define -s gsgraph_ico $(GLGENDIR)/gsgraph.ico
+ $(ECHOGS_XE) -w $(GLGEN)_dll.rc -x 23 define -s gstext_ico $(GLGENDIR)\gstext.ico
+ $(ECHOGS_XE) -a $(GLGEN)_dll.rc -x 23 define -s gsgraph_ico $(GLGENDIR)\gsgraph.ico
$(ECHOGS_XE) -a $(GLGEN)_dll.rc -R $(GLSRC)gsdll32.rc
- $(RCOMP) -I$(GLSRCDIR) -i$(INCDIR) -r -fo$(GSDLL_OBJ).res $(GLGEN)_dll.rc
+ $(RCOMP) -I$(GLSRCDIR) -i$(INCDIR)$(_I) -r $(RO_)$(GSDLL_OBJ).res $(GLGEN)_dll.rc
del $(GLGEN)_dll.rc
@@ -80,19 +80,19 @@ DWOBJ=$(GLOBJ)dwdll.obj $(GLOBJ)dwimg.obj $(GLOBJ)dwmain.obj $(GLOBJ)dwtext.obj
$(GLOBJ)dwdll.obj: $(GLSRC)dwdll.cpp $(AK)\
$(dwdll_h) $(gsdll_h) $(gsdllwin_h)
- $(GLCPP) $(COMPILE_FOR_EXE) $(GLO_)dwdll.obj -c $(GLSRC)dwdll.cpp
+ $(GLCPP) $(COMPILE_FOR_EXE) $(GLO_)dwdll.obj $(C_) $(GLSRC)dwdll.cpp
$(GLOBJ)dwimg.obj: $(GLSRC)dwimg.cpp $(AK)\
$(dwmain_h) $(dwdll_h) $(dwtext_h) $(dwimg_h)\
$(gscdefs_h) $(gsdll_h)
- $(GLCPP) $(COMPILE_FOR_EXE) $(GLO_)dwimg.obj -c $(GLSRC)dwimg.cpp
+ $(GLCPP) $(COMPILE_FOR_EXE) $(GLO_)dwimg.obj $(C_) $(GLSRC)dwimg.cpp
$(GLOBJ)dwmain.obj: $(GLSRC)dwmain.cpp $(AK)\
$(dwdll_h) $(gscdefs_h) $(gsdll_h)
- $(GLCPP) $(COMPILE_FOR_EXE) $(GLO_)dwmain.obj -c $(GLSRC)dwmain.cpp
+ $(GLCPP) $(COMPILE_FOR_EXE) $(GLO_)dwmain.obj $(C_) $(GLSRC)dwmain.cpp
$(GLOBJ)dwtext.obj: $(GLSRC)dwtext.cpp $(AK) $(dwtext_h)
- $(GLCPP) $(COMPILE_FOR_EXE) $(GLO_)dwtext.obj -c $(GLSRC)dwtext.cpp
+ $(GLCPP) $(COMPILE_FOR_EXE) $(GLO_)dwtext.obj $(C_) $(GLSRC)dwtext.cpp
# Modules for big EXE
@@ -100,12 +100,12 @@ DWOBJNO = $(GLOBJ)dwnodll.obj $(GLOBJ)dwimg.obj $(GLOBJ)dwmain.obj $(GLOBJ)dwtex
$(GLOBJ)dwnodll.obj: $(GLSRC)dwnodll.cpp $(AK)\
$(dwdll_h) $(gsdll_h) $(gsdllwin_h)
- $(GLCPP) $(COMPILE_FOR_EXE) $(GLO_)dwnodll.obj -c $(GLSRC)dwnodll.cpp
+ $(GLCPP) $(COMPILE_FOR_EXE) $(GLO_)dwnodll.obj $(C_) $(GLSRC)dwnodll.cpp
# Compile gsdll.c, the main program of the DLL.
$(GLOBJ)gsdll.obj: $(GLSRC)gsdll.c $(AK) $(gsdll_h) $(ghost_h)
- $(PSCCWIN) $(COMPILE_FOR_DLL) $(GLO_)gsdll.$(OBJ) -c $(GLSRC)gsdll.c
+ $(PSCCWIN) $(COMPILE_FOR_DLL) $(GLO_)gsdll.$(OBJ) $(C_) $(GLSRC)gsdll.c
# Modules for console mode EXEs
@@ -113,12 +113,12 @@ OBJC=$(GLOBJ)dwmainc.obj $(GLOBJ)dwdllc.obj $(GLOBJ)gscdefs.obj $(GLOBJ)gp_wgetv
OBJCNO=$(GLOBJ)dwmainc.obj $(GLOBJ)dwnodllc.obj
$(GLOBJ)dwmainc.obj: $(GLSRC)dwmainc.cpp $(AK) $(dwmain_h) $(dwdll_h) $(gscdefs_h) $(gsdll_h)
- $(GLCPP) $(COMPILE_FOR_CONSOLE_EXE) $(GLO_)dwmainc.obj -c $(GLSRC)dwmainc.cpp
+ $(GLCPP) $(COMPILE_FOR_CONSOLE_EXE) $(GLO_)dwmainc.obj $(C_) $(GLSRC)dwmainc.cpp
$(GLOBJ)dwdllc.obj: $(GLSRC)dwdll.cpp $(AK) $(dwdll_h) $(gsdll_h)
- $(GLCPP) $(COMPILE_FOR_CONSOLE_EXE) $(GLO_)dwdllc.obj -c $(GLSRC)dwdll.cpp
+ $(GLCPP) $(COMPILE_FOR_CONSOLE_EXE) $(GLO_)dwdllc.obj $(C_) $(GLSRC)dwdll.cpp
$(GLOBJ)dwnodllc.obj: $(GLSRC)dwnodll.cpp $(AK) $(dwdll_h) $(gsdll_h)
- $(GLCPP) $(COMPILE_FOR_CONSOLE_EXE) $(GLO_)dwnodllc.obj -c $(GLSRC)dwnodll.cpp
+ $(GLCPP) $(COMPILE_FOR_CONSOLE_EXE) $(GLO_)dwnodllc.obj $(C_) $(GLSRC)dwnodll.cpp
# end of winint.mak
diff --git a/gs/src/winlib.mak b/gs/src/winlib.mak
index 88954fb8e..d1f103b83 100644
--- a/gs/src/winlib.mak
+++ b/gs/src/winlib.mak
@@ -46,7 +46,6 @@ AK=$(GLGENDIR)\ccf32.tr
NULL=
CMD=.bat
-C_=-c
D_=-D
_D_=$(NULL)=
_D=
@@ -152,4 +151,16 @@ $(GLOBJ)gp_mswin.$(OBJ): $(GLSRC)gp_mswin.c $(AK) $(gp_mswin_h) \
$(GLOBJ)gp_wgetv.$(OBJ): $(GLSRC)gp_wgetv.c $(AK) $(gscdefs_h)
$(GLCCWIN) $(GLO_)gp_wgetv.$(OBJ) $(C_) $(GLSRC)gp_wgetv.c
+# Define MS-Windows handles (file system) as a separable feature.
+
+mshandle_=$(GLOBJ)gp_mshdl.$(OBJ)
+$(GLD)mshandle.dev: $(ECHOGS_XE) $(mshandle_)
+ $(SETMOD) $(GLD)mshandle $(mshandle_)
+ $(ADDMOD) $(GLD)mshandle -iodev handle
+
+$(GLOBJ)gp_mshdl.$(OBJ): $(GLSRC)gp_mshdl.c $(AK)\
+ $(ctype__h) $(errno__h) $(stdio__h) $(string__h)\
+ $(gserror_h) $(gsmemory_h) $(gstypes_h) $(gxiodev_h)
+ $(GLCC) $(GLO_)gp_mshdl.$(OBJ) $(C_) $(GLSRC)gp_mshdl.c
+
# end of winlib.mak
diff --git a/gs/src/zarith.c b/gs/src/zarith.c
index ae5e91466..c93779bc3 100644
--- a/gs/src/zarith.c
+++ b/gs/src/zarith.c
@@ -26,6 +26,11 @@
/****** NOTE: none of the arithmetic operators ******/
/****** currently check for floating exceptions ******/
+/*
+ * Many of the procedures in this file are public only so they can be
+ * called from the FunctionType 4 interpreter (zfunc4.c).
+ */
+
/* Define max and min values for what will fit in value.intval. */
#define MIN_INTVAL min_long
#define MAX_INTVAL max_long
@@ -84,7 +89,7 @@ zadd(i_ctx_t *i_ctx_p)
}
/* <num1> <num2> div <real_quotient> */
-private int
+int
zdiv(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
@@ -126,7 +131,7 @@ zdiv(i_ctx_t *i_ctx_p)
}
/* <num1> <num2> mul <product> */
-private int
+int
zmul(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
@@ -232,7 +237,7 @@ zsub(i_ctx_t *i_ctx_p)
}
/* <num1> <num2> idiv <int_quotient> */
-private int
+int
zidiv(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
@@ -251,7 +256,7 @@ zidiv(i_ctx_t *i_ctx_p)
}
/* <int1> <int2> mod <remainder> */
-private int
+int
zmod(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
@@ -266,7 +271,7 @@ zmod(i_ctx_t *i_ctx_p)
}
/* <num1> neg <num2> */
-private int
+int
zneg(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
@@ -286,8 +291,29 @@ zneg(i_ctx_t *i_ctx_p)
return 0;
}
+/* <num1> abs <num2> */
+int
+zabs(i_ctx_t *i_ctx_p)
+{
+ os_ptr op = osp;
+
+ switch (r_type(op)) {
+ default:
+ return_op_typecheck(op);
+ case t_real:
+ if (op->value.realval >= 0)
+ return 0;
+ break;
+ case t_integer:
+ if (op->value.intval >= 0)
+ return 0;
+ break;
+ }
+ return zneg(i_ctx_p);
+}
+
/* <num1> ceiling <num2> */
-private int
+int
zceiling(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
@@ -303,7 +329,7 @@ zceiling(i_ctx_t *i_ctx_p)
}
/* <num1> floor <num2> */
-private int
+int
zfloor(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
@@ -319,7 +345,7 @@ zfloor(i_ctx_t *i_ctx_p)
}
/* <num1> round <num2> */
-private int
+int
zround(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
@@ -335,7 +361,7 @@ zround(i_ctx_t *i_ctx_p)
}
/* <num1> truncate <num2> */
-private int
+int
ztruncate(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
@@ -372,6 +398,7 @@ zbitadd(i_ctx_t *i_ctx_p)
const op_def zarith_op_defs[] =
{
+ {"1abs", zabs},
{"2add", zadd},
{"2.bitadd", zbitadd},
{"1ceiling", zceiling},
diff --git a/gs/src/zarray.c b/gs/src/zarray.c
index 843e3b184..234ac898c 100644
--- a/gs/src/zarray.c
+++ b/gs/src/zarray.c
@@ -95,20 +95,21 @@ zastore(i_ctx_t *i_ctx_p)
check_write_type(*op, t_array);
size = r_size(op);
- if (size > op - osbot) { /* The store operation might involve other stack segments. */
+ if (size > op - osbot) {
+ /* The store operation might involve other stack segments. */
ref arr;
if (size >= ref_stack_count(&o_stack))
return_error(e_stackunderflow);
arr = *op;
- code = ref_stack_store(&o_stack, &arr, size, 1, 0, true,
+ code = ref_stack_store(&o_stack, &arr, size, 1, 0, true, idmemory,
"astore");
if (code < 0)
return code;
ref_stack_pop(&o_stack, size);
*ref_stack_index(&o_stack, 0) = arr;
} else {
- code = refcpy_to_old(op, 0, op - size, size, "astore");
+ code = refcpy_to_old(op, 0, op - size, size, idmemory, "astore");
if (code < 0)
return code;
op[-(int)size] = *op;
diff --git a/gs/src/zbfont.c b/gs/src/zbfont.c
index 6295ac49e..2061fdca1 100644
--- a/gs/src/zbfont.c
+++ b/gs/src/zbfont.c
@@ -25,7 +25,6 @@
#include "gxfixed.h"
#include "gsmatrix.h"
#include "gxdevice.h"
-#include "gschar.h"
#include "gxfont.h"
#include "bfont.h"
#include "ialloc.h"
@@ -85,17 +84,17 @@ zbuildfont3(i_ctx_t *i_ctx_p)
}
/* Encode a character. */
-private gs_glyph
-zfont_encode_char(gs_show_enum * penum, gs_font * pfont, gs_char * pchr)
+gs_glyph
+zfont_encode_char(gs_font *pfont, gs_char chr, gs_glyph_space_t ignored)
{
const ref *pencoding = &pfont_data(pfont)->Encoding;
- ulong index = *pchr; /* work around VAX widening bug */
+ ulong index = chr; /* work around VAX widening bug */
ref cname;
int code = array_get(pencoding, (long)index, &cname);
if (code < 0 || !r_has_type(&cname, t_name))
return gs_no_glyph;
- return (gs_glyph) name_index(&cname);
+ return (gs_glyph)name_index(&cname);
}
/* Encode a character in a known encoding. */
@@ -289,9 +288,9 @@ build_gs_simple_font(i_ctx_t *i_ctx_p, os_ptr op, gs_font_base ** ppfont,
return code;
pfont = *ppfont;
pfont->procs.init_fstack = gs_default_init_fstack;
- pfont->procs.next_char = gs_default_next_char;
pfont->procs.define_font = gs_no_define_font;
pfont->procs.make_font = zbase_make_font;
+ pfont->procs.next_char_glyph = gs_default_next_char_glyph;
pfont->FontBBox.p.x = bbox[0];
pfont->FontBBox.p.y = bbox[1];
pfont->FontBBox.q.x = bbox[2];
@@ -459,14 +458,14 @@ build_gs_font(i_ctx_t *i_ctx_p, os_ptr op, gs_font ** ppfont, font_type ftype,
if (pencoding)
encoding = *pencoding;
ialloc_set_space(idmemory, r_space(op));
- pfont = ialloc_struct(gs_font, pstype,
+ pfont = gs_font_alloc(imemory, pstype, &gs_font_procs_default, NULL,
"buildfont(font)");
pdata = ialloc_struct(font_data, &st_font_data,
"buildfont(data)");
if (pfont == 0 || pdata == 0)
code = gs_note_error(e_VMerror);
else
- code = add_FID(i_ctx_p, op, pfont);
+ code = add_FID(i_ctx_p, op, pfont, iimemory);
if (code < 0) {
ifree_object(pdata, "buildfont(data)");
ifree_object(pfont, "buildfont(font)");
@@ -479,12 +478,6 @@ build_gs_font(i_ctx_t *i_ctx_p, os_ptr op, gs_font ** ppfont, font_type ftype,
ref_assign_new(&pdata->BuildGlyph, &pbuild->BuildGlyph);
if (pencoding)
ref_assign_new(&pdata->Encoding, &encoding);
- /* Clear the chain pointers so as not to confuse the memory */
- /* manager if we bail out after returning from here. */
- pfont->next = pfont->prev = 0;
- pfont->memory = imemory;
- pfont->dir = 0;
- pfont->base = pfont;
pfont->client_data = pdata;
pfont->FontType = ftype;
pfont->FontMatrix = mat;
@@ -493,9 +486,6 @@ build_gs_font(i_ctx_t *i_ctx_p, os_ptr op, gs_font ** ppfont, font_type ftype,
pfont->InBetweenSize = (fbit_type) inbetweensize;
pfont->TransformedChar = (fbit_type) transformedchar;
pfont->WMode = wmode;
- pfont->PaintType = 0;
- pfont->StrokeWidth = 0.0;
- pfont->procs.build_char = gs_no_build_char;
pfont->procs.encode_char = zfont_encode_char;
pfont->procs.callbacks.glyph_name = zfont_glyph_name;
pfont->procs.callbacks.known_encode = zfont_known_encode;
diff --git a/gs/src/zcfont.c b/gs/src/zcfont.c
index ec57e26cb..edeeef2ab 100644
--- a/gs/src/zcfont.c
+++ b/gs/src/zcfont.c
@@ -20,11 +20,10 @@
/* Composite font-related character operators */
#include "ghost.h"
#include "oper.h"
-#include "gschar.h"
#include "gsmatrix.h" /* for gxfont.h */
#include "gxfixed.h" /* for gxfont.h */
#include "gxfont.h"
-#include "gxchar.h"
+#include "gxtext.h"
#include "estack.h"
#include "ichar.h"
#include "ifont.h"
@@ -42,12 +41,12 @@ zcshow(i_ctx_t *i_ctx_p)
os_ptr op = osp;
os_ptr proc_op = op - 1;
os_ptr str_op = op;
- gs_show_enum *penum;
+ gs_text_enum_t *penum;
int code;
/*
* Even though this is not documented anywhere by Adobe,
- * the Adobe interpreters apparently allow the string and
+ * some Adobe interpreters apparently allow the string and
* the procedure to be provided in either order!
*/
if (r_is_proc(proc_op))
@@ -59,15 +58,14 @@ zcshow(i_ctx_t *i_ctx_p)
check_op(2);
return_error(e_typecheck);
}
- if ((code = op_show_setup(i_ctx_p, str_op, &penum)) != 0)
+ if ((code = op_show_setup(i_ctx_p, str_op)) != 0 ||
+ (code = gs_cshow_begin(igs, str_op->value.bytes, r_size(str_op),
+ imemory, &penum)) < 0)
return code;
- if ((code = gs_cshow_n_init(penum, igs, (char *)str_op->value.bytes,
- r_size(str_op))) < 0
- ) {
+ if ((code = op_show_finish_setup(i_ctx_p, penum, 2, NULL)) < 0) {
ifree_object(penum, "op_show_enum_setup");
return code;
}
- op_show_finish_setup(i_ctx_p, penum, 2, NULL);
sslot = *proc_op; /* save kerning proc */
pop(2);
return cshow_continue(i_ctx_p);
@@ -76,14 +74,14 @@ private int
cshow_continue(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
- gs_show_enum *penum = senum;
+ gs_text_enum_t *penum = senum;
int code;
check_estack(4); /* in case we call the procedure */
- code = gs_show_next(penum);
- if (code != gs_show_move) {
+ code = gs_text_process(penum);
+ if (code != TEXT_PROCESS_INTERVENE) {
code = op_show_continue_dispatch(i_ctx_p, 0, code);
- if (code == o_push_estack) /* must be gs_show_render */
+ if (code == o_push_estack) /* must be TEXT_PROCESS_RENDER */
make_op_estack(esp - 1, cshow_continue);
return code;
}
@@ -91,42 +89,33 @@ cshow_continue(i_ctx_t *i_ctx_p)
{
ref *pslot = &sslot;
gs_point wpt;
- gs_font *font = gs_show_current_font(penum);
+ gs_font *font = gs_text_current_font(penum);
+ gs_font *root_font = gs_rootfont(igs);
gs_font *scaled_font;
+ uint font_space = r_space(pfont_dict(font));
+ uint root_font_space = r_space(pfont_dict(root_font));
- gs_show_current_width(penum, &wpt);
-#if 0
- /****************
- * The following code is logically correct (or at least,
- * probably more correct than the code it replaces),
- * but because of the issues about creating the scaled
- * font in the correct VM space that make_font (in zfont.c)
- * has to deal with, it creates references pointing to
- * the wrong spaces. Therefore, we've removed it.
- *****************/
- {
- int fdepth = penum->fstack.depth;
-
- if (fdepth <= 0)
- scaled_font = font; /* not composite */
- else {
- code = gs_makefont(font->dir, font,
- &penum->fstack.items[fdepth - 1].font->
- FontMatrix, &scaled_font);
- if (code < 0)
- return code;
- }
+ gs_text_current_width(penum, &wpt);
+ if (font == root_font)
+ scaled_font = font;
+ else {
+ /* Construct a scaled version of the leaf font. */
+ uint save_space = idmemory->current_space;
+
+ ialloc_set_space(idmemory, font_space);
+ code = gs_makefont(font->dir, font, &root_font->FontMatrix,
+ &scaled_font);
+ ialloc_set_space(idmemory, save_space);
+ if (code < 0)
+ return code;
}
-#else
- scaled_font = font;
-#endif
push(3);
- make_int(op - 2, gs_show_current_char(penum) & 0xff);
+ make_int(op - 2, gs_text_current_char(penum) & 0xff);
make_real(op - 1, wpt.x);
make_real(op, wpt.y);
- push_op_estack(cshow_continue);
- if (scaled_font != gs_rootfont(igs))
- push_op_estack(cshow_restore_font);
+ make_struct(&ssfont, font_space, font);
+ make_struct(&srfont, root_font_space, root_font);
+ push_op_estack(cshow_restore_font);
/* cshow does not change rootfont for user procedure */
gs_set_currentfont(igs, scaled_font);
*++esp = *pslot; /* user procedure */
@@ -135,8 +124,11 @@ cshow_continue(i_ctx_t *i_ctx_p)
}
private int
cshow_restore_font(i_ctx_t *i_ctx_p)
-{ /* We have 1 more entry on the e-stack (cshow_continue). */
- return gs_show_restore_font(esenum(esp - 1));
+{
+ /* We must restore both the root font and the current font. */
+ gs_setfont(igs, r_ptr(&srfont, gs_font));
+ gs_set_currentfont(igs, r_ptr(&ssfont, gs_font));
+ return cshow_continue(i_ctx_p);
}
/* - rootfont <font> */
diff --git a/gs/src/zchar.c b/gs/src/zchar.c
index 13a7b0be3..b026552e5 100644
--- a/gs/src/zchar.c
+++ b/gs/src/zchar.c
@@ -21,10 +21,10 @@
#include "ghost.h"
#include "oper.h"
#include "gsstruct.h"
+# include "gstext.h"
#include "gxarith.h"
#include "gxfixed.h"
#include "gxmatrix.h" /* for ifont.h */
-#include "gxchar.h" /* for stringwidth_flag */
#include "gxdevice.h" /* for gxfont.h */
#include "gxfont.h"
#include "gzstate.h"
@@ -52,16 +52,16 @@ private int
zshow(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
- gs_show_enum *penum;
- int code = op_show_setup(i_ctx_p, op, &penum);
+ gs_text_enum_t *penum;
+ int code = op_show_setup(i_ctx_p, op);
- if (code != 0)
+ if (code != 0 ||
+ (code = gs_show_begin(igs, op->value.bytes, r_size(op), imemory, &penum)) < 0)
return code;
- if ((code = gs_show_n_init(penum, igs, (char *)op->value.bytes, r_size(op))) < 0) {
+ if ((code = op_show_finish_setup(i_ctx_p, penum, 1, finish_show)) < 0) {
ifree_object(penum, "op_show_enum_setup");
return code;
}
- op_show_finish_setup(i_ctx_p, penum, 1, finish_show);
return op_show_contioue_pop(i_ctx_p, 1);
}
@@ -70,19 +70,18 @@ private int
zashow(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
- gs_show_enum *penum;
- int code;
+ gs_text_enum_t *penum;
double axy[2];
+ int code = num_params(op - 1, 2, axy);
- if ((code = num_params(op - 1, 2, axy)) < 0 ||
- (code = op_show_setup(i_ctx_p, op, &penum)) != 0
- )
+ if (code < 0 ||
+ (code = op_show_setup(i_ctx_p, op)) != 0 ||
+ (code = gs_ashow_begin(igs, axy[0], axy[1], op->value.bytes, r_size(op), imemory, &penum)) < 0)
return code;
- if ((code = gs_ashow_n_init(penum, igs, axy[0], axy[1], (char *)op->value.bytes, r_size(op))) < 0) {
+ if ((code = op_show_finish_setup(i_ctx_p, penum, 3, finish_show)) < 0) {
ifree_object(penum, "op_show_enum_setup");
return code;
}
- op_show_finish_setup(i_ctx_p, penum, 3, finish_show);
return op_show_continue_pop(i_ctx_p, 3);
}
@@ -91,25 +90,24 @@ private int
zwidthshow(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
- gs_show_enum *penum;
- int code;
+ gs_text_enum_t *penum;
double cxy[2];
+ int code;
check_type(op[-1], t_integer);
if ((gs_char) (op[-1].value.intval) != op[-1].value.intval)
return_error(e_rangecheck);
if ((code = num_params(op - 2, 2, cxy)) < 0 ||
- (code = op_show_setup(i_ctx_p, op, &penum)) != 0
- )
+ (code = op_show_setup(i_ctx_p, op)) != 0 ||
+ (code = gs_widthshow_begin(igs, cxy[0], cxy[1],
+ (gs_char) op[-1].value.intval,
+ op->value.bytes, r_size(op),
+ imemory, &penum)) < 0)
return code;
- if ((code = gs_widthshow_n_init(penum, igs, cxy[0], cxy[1],
- (gs_char) op[-1].value.intval,
- (char *)op->value.bytes,
- r_size(op))) < 0) {
+ if ((code = op_show_finish_setup(i_ctx_p, penum, 4, finish_show)) < 0) {
ifree_object(penum, "op_show_enum_setup");
return code;
}
- op_show_finish_setup(i_ctx_p, penum, 4, finish_show);
return op_show_continue_pop(i_ctx_p, 4);
}
@@ -118,27 +116,26 @@ private int
zawidthshow(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
- gs_show_enum *penum;
- int code;
+ gs_text_enum_t *penum;
double cxy[2], axy[2];
+ int code;
check_type(op[-3], t_integer);
if ((gs_char) (op[-3].value.intval) != op[-3].value.intval)
return_error(e_rangecheck);
if ((code = num_params(op - 4, 2, cxy)) < 0 ||
(code = num_params(op - 1, 2, axy)) < 0 ||
- (code = op_show_setup(i_ctx_p, op, &penum)) != 0
- )
+ (code = op_show_setup(i_ctx_p, op)) != 0 ||
+ (code = gs_awidthshow_begin(igs, cxy[0], cxy[1],
+ (gs_char) op[-3].value.intval,
+ axy[0], axy[1],
+ op->value.bytes, r_size(op),
+ imemory, &penum)) < 0)
return code;
- if ((code = gs_awidthshow_n_init(penum, igs, cxy[0], cxy[1],
- (gs_char) op[-3].value.intval,
- axy[0], axy[1],
- (char *)op->value.bytes,
- r_size(op))) < 0) {
+ if ((code = op_show_finish_setup(i_ctx_p, penum, 6, finish_show)) < 0) {
ifree_object(penum, "op_show_enum_setup");
return code;
}
- op_show_finish_setup(i_ctx_p, penum, 6, finish_show);
return op_show_continue_pop(i_ctx_p, 6);
}
@@ -147,17 +144,18 @@ private int
zkshow(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
- gs_show_enum *penum;
+ gs_text_enum_t *penum;
int code;
check_proc(op[-1]);
- if ((code = op_show_setup(i_ctx_p, op, &penum)) != 0)
+ if ((code = op_show_setup(i_ctx_p, op)) != 0 ||
+ (code = gs_kshow_begin(igs, op->value.bytes, r_size(op),
+ imemory, &penum)) < 0)
return code;
- if ((code = gs_kshow_n_init(penum, igs, (char *)op->value.bytes, r_size(op))) < 0) {
+ if ((code = op_show_finish_setup(i_ctx_p, penum, 2, finish_show)) < 0) {
ifree_object(penum, "op_show_enum_setup");
return code;
}
- op_show_finish_setup(i_ctx_p, penum, 2, finish_show);
sslot = op[-1]; /* save kerning proc */
return op_show_continue_pop(i_ctx_p, 2);
}
@@ -175,16 +173,17 @@ private int
zstringwidth(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
- gs_show_enum *penum;
- int code = op_show_setup(i_ctx_p, op, &penum);
+ gs_text_enum_t *penum;
+ int code = op_show_setup(i_ctx_p, op);
- if (code != 0)
+ if (code != 0 ||
+ (code = gs_stringwidth_begin(igs, op->value.bytes, r_size(op),
+ imemory, &penum)) < 0)
return code;
- if ((code = gs_stringwidth_n_init(penum, igs, (char *)op->value.bytes, r_size(op))) < 0) {
+ if ((code = op_show_finish_setup(i_ctx_p, penum, 1, finish_stringwidth)) < 0) {
ifree_object(penum, "op_show_enum_setup");
return code;
}
- op_show_finish_setup(i_ctx_p, penum, 1, finish_stringwidth);
return op_show_continue_pop(i_ctx_p, 1);
}
/* Finishing procedure for stringwidth. */
@@ -195,7 +194,7 @@ finish_stringwidth(i_ctx_t *i_ctx_p)
os_ptr op = osp;
gs_point width;
- gs_show_width(senum, &width);
+ gs_text_total_width(senum, &width);
push(2);
make_real(op - 1, width.x);
make_real(op, width.y);
@@ -205,34 +204,36 @@ finish_stringwidth(i_ctx_t *i_ctx_p)
/* Common code for charpath and .charboxpath. */
private int
zchar_path(i_ctx_t *i_ctx_p,
- int (*init)(P5(gs_show_enum *, gs_state *, const char *, uint, bool)))
+ int (*begin)(P6(gs_state *, const byte *, uint,
+ bool, gs_memory_t *, gs_text_enum_t **)))
{
os_ptr op = osp;
- gs_show_enum *penum;
+ gs_text_enum_t *penum;
int code;
check_type(*op, t_boolean);
- code = op_show_setup(i_ctx_p, op - 1, &penum);
- if (code != 0)
+ code = op_show_setup(i_ctx_p, op - 1);
+ if (code != 0 ||
+ (code = begin(igs, op[-1].value.bytes, r_size(op - 1),
+ op->value.boolval, imemory, &penum)) < 0)
return code;
- if ((code = (*init)(penum, igs, (char *)op[-1].value.bytes, r_size(op - 1), op->value.boolval)) < 0) {
+ if ((code = op_show_finish_setup(i_ctx_p, penum, 2, finish_show)) < 0) {
ifree_object(penum, "op_show_enum_setup");
return code;
}
- op_show_finish_setup(i_ctx_p, penum, 2, finish_show);
return op_show_continue_pop(i_ctx_p, 2);
}
/* <string> <outline_bool> charpath - */
private int
zcharpath(i_ctx_t *i_ctx_p)
{
- return zchar_path(i_ctx_p, gs_charpath_n_init);
+ return zchar_path(i_ctx_p, gs_charpath_begin);
}
/* <string> <box_bool> .charboxpath - */
private int
zcharboxpath(i_ctx_t *i_ctx_p)
{
- return zchar_path(i_ctx_p, gs_charboxpath_n_init);
+ return zchar_path(i_ctx_p, gs_charboxpath_begin);
}
/* <wx> <wy> <llx> <lly> <urx> <ury> setcachedevice - */
@@ -241,16 +242,16 @@ zsetcachedevice(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
double wbox[6];
- gs_show_enum *penum = op_show_find(i_ctx_p);
+ gs_text_enum_t *penum = op_show_find(i_ctx_p);
int code = num_params(op, 6, wbox);
if (penum == 0)
return_error(e_undefined);
if (code < 0)
return code;
- if (gs_show_width_only(penum))
+ if (zchar_show_width_only(penum))
return op_show_return_width(i_ctx_p, 6, &wbox[0]);
- code = gs_setcachedevice_double(penum, igs, wbox);
+ code = gs_text_setcachedevice(penum, wbox);
if (code < 0)
return code;
pop(6);
@@ -265,18 +266,18 @@ zsetcachedevice2(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
double wbox[10];
- gs_show_enum *penum = op_show_find(i_ctx_p);
+ gs_text_enum_t *penum = op_show_find(i_ctx_p);
int code = num_params(op, 10, wbox);
if (penum == 0)
return_error(e_undefined);
if (code < 0)
return code;
- if (gs_show_width_only(penum))
+ if (zchar_show_width_only(penum))
return op_show_return_width(i_ctx_p, 10,
(gs_rootfont(igs)->WMode ?
&wbox[6] : &wbox[0]));
- code = gs_setcachedevice2_double(penum, igs, wbox);
+ code = gs_text_setcachedevice2(penum, wbox);
if (code < 0)
return code;
pop(10);
@@ -291,16 +292,16 @@ zsetcharwidth(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
double width[2];
- gs_show_enum *penum = op_show_find(i_ctx_p);
+ gs_text_enum_t *penum = op_show_find(i_ctx_p);
int code = num_params(op, 2, width);
if (penum == 0)
return_error(e_undefined);
if (code < 0)
return code;
- if (gs_show_width_only(penum))
+ if (zchar_show_width_only(penum))
return op_show_return_width(i_ctx_p, 2, &width[0]);
- code = gs_setcharwidth(penum, igs, width[0], width[1]);
+ code = gs_text_setcharwidth(penum, width);
if (code < 0)
return code;
pop(2);
@@ -360,7 +361,7 @@ const op_def zchar_op_defs[] =
/* Most of these are exported for zchar2.c. */
/* Convert a glyph to a ref. */
-private void
+void
glyph_ref(gs_glyph glyph, ref * gref)
{
if (glyph < gs_min_cid_glyph)
@@ -369,55 +370,83 @@ glyph_ref(gs_glyph glyph, ref * gref)
make_int(gref, glyph - gs_min_cid_glyph);
}
-/* Prepare to set up for a show operator. */
+/* Prepare to set up for a text operator. */
/* Don't change any state yet. */
int
-op_show_setup(i_ctx_t *i_ctx_p, os_ptr op, gs_show_enum ** ppenum)
+op_show_setup(i_ctx_t *i_ctx_p, os_ptr op)
{
check_read_type(*op, t_string);
- return op_show_enum_setup(i_ctx_p, ppenum);
+ return op_show_enum_setup(i_ctx_p);
}
int
-op_show_enum_setup(i_ctx_t *i_ctx_p, gs_show_enum ** ppenum)
+op_show_enum_setup(i_ctx_t *i_ctx_p)
{
check_estack(snumpush + 2);
- if ((*ppenum = gs_show_enum_alloc((gs_memory_t *) imemory, igs, "op_show_enum_setup")) == 0)
- return_error(e_VMerror);
return 0;
}
-/* Finish setting up a show operator. This can't fail, since */
-/* op_show_enum_setup did the check_estack. */
-void
-op_show_finish_setup(i_ctx_t *i_ctx_p, gs_show_enum * penum, int npop,
+/* Finish setting up a text operator. */
+int
+op_show_finish_setup(i_ctx_t *i_ctx_p, gs_text_enum_t * penum, int npop,
op_proc_t endproc /* end procedure */ )
{
- register es_ptr ep = esp + snumpush;
+ gs_text_enum_t *osenum = op_show_find(i_ctx_p);
+ es_ptr ep = esp + snumpush;
+ gs_glyph glyph;
- esp = ep;
+ /*
+ * If we are in the procedure of a cshow for a CID font and this is
+ * a show operator, do something special, per the Red Book.
+ */
+ if (osenum &&
+ SHOW_IS_ALL_OF(osenum,
+ TEXT_FROM_STRING | TEXT_DO_NONE | TEXT_INTERVENE) &&
+ SHOW_IS_ALL_OF(penum, TEXT_FROM_STRING | TEXT_RETURN_WIDTH) &&
+ (glyph = gs_text_current_glyph(osenum)) != gs_no_glyph &&
+ glyph >= gs_min_cid_glyph
+ ) {
+ gs_text_params_t text;
+
+ if (!(penum->text.size == 1 &&
+ penum->text.data.bytes[0] == (glyph & 0xff))
+ )
+ return_error(e_rangecheck);
+ text = penum->text;
+ text.operation =
+ (text.operation &
+ ~(TEXT_FROM_STRING | TEXT_FROM_BYTES | TEXT_FROM_CHARS |
+ TEXT_FROM_GLYPHS | TEXT_FROM_SINGLE_CHAR)) |
+ TEXT_FROM_SINGLE_GLYPH;
+ text.data.d_glyph = glyph;
+ text.size = 1;
+ gs_text_restart(penum, &text);
+ }
make_mark_estack(ep - (snumpush - 1), es_show, op_show_cleanup);
if (endproc == NULL)
endproc = finish_show;
make_null(&esslot(ep));
- make_int(&essindex(ep), 0);
make_int(&esodepth(ep), 0); /* see gs_show_render case in */
/* op_show_continue_dispatch */
make_int(&esddepth(ep), 0); /* ditto */
make_int(&esgslevel(ep), igs->level);
+ make_null(&essfont(ep));
+ make_null(&esrfont(ep));
make_op_estack(&eseproc(ep), endproc);
make_istruct(ep, 0, penum);
+ esp = ep;
+ return 0;
}
/* Continuation operator for character rendering. */
int
op_show_continue(i_ctx_t *i_ctx_p)
{
- return op_show_continue_dispatch(i_ctx_p, 0, gs_show_next(senum));
+ return op_show_continue_dispatch(i_ctx_p, 0, gs_text_process(senum));
}
int
op_show_continue_pop(i_ctx_t *i_ctx_p, int npop)
{
- return op_show_continue_dispatch(i_ctx_p, npop, gs_show_next(senum));
+ return op_show_continue_dispatch(i_ctx_p, npop, gs_text_process(senum));
}
/*
* Note that op_show_continue_dispatch sets osp = op explicitly iff the
@@ -429,7 +458,7 @@ int
op_show_continue_dispatch(i_ctx_t *i_ctx_p, int npop, int code)
{
os_ptr op = osp - npop;
- gs_show_enum *penum = senum;
+ gs_text_enum_t *penum = senum;
switch (code) {
case 0: { /* all done */
@@ -444,21 +473,21 @@ op_show_continue_dispatch(i_ctx_t *i_ctx_p, int npop, int code)
}
return o_pop_estack;
}
- case gs_show_kern: {
- ref *pslot = &sslot;
+ case TEXT_PROCESS_INTERVENE: {
+ ref *pslot = &sslot; /* only used for kshow */
push(2);
- make_int(op - 1, gs_kshow_previous_char(penum));
- make_int(op, gs_kshow_next_char(penum));
+ make_int(op - 1, gs_text_current_char(penum)); /* previous char */
+ make_int(op, gs_text_next_char(penum));
push_op_estack(op_show_continue); /* continue after kerning */
*++esp = *pslot; /* kerning procedure */
return o_push_estack;
}
- case gs_show_render: {
+ case TEXT_PROCESS_RENDER: {
gs_font *pfont = gs_currentfont(igs);
font_data *pfdata = pfont_data(pfont);
- gs_char chr = gs_show_current_char(penum);
- gs_glyph glyph = gs_show_current_glyph(penum);
+ gs_char chr = gs_text_current_char(penum);
+ gs_glyph glyph = gs_text_current_glyph(penum);
push(2);
op[-1] = pfdata->dict; /* push the font */
@@ -564,7 +593,7 @@ map_glyph_to_char(const ref * pgref, const ref * pencoding, ref * pch)
/* Find the index of the e-stack mark for the current show enumerator. */
/* Return 0 if we can't find the mark. */
-uint
+private uint
op_show_find_index(i_ctx_t *i_ctx_p)
{
ref_stack_enum_t rsenum;
@@ -583,7 +612,7 @@ op_show_find_index(i_ctx_t *i_ctx_p)
}
/* Find the current show enumerator on the e-stack. */
-gs_show_enum *
+gs_text_enum_t *
op_show_find(i_ctx_t *i_ctx_p)
{
uint index = op_show_find_index(i_ctx_p);
@@ -591,7 +620,32 @@ op_show_find(i_ctx_t *i_ctx_p)
if (index == 0)
return 0; /* no mark */
return r_ptr(ref_stack_index(&e_stack, index - (snumpush - 1)),
- gs_show_enum);
+ gs_text_enum_t);
+}
+
+/*
+ * Return true if we only need the width from the rasterizer
+ * and can short-circuit the full rendering of the character,
+ * false if we need the actual character bits. This is only safe if
+ * we know the character is well-behaved, i.e., is not defined by an
+ * arbitrary PostScript procedure.
+ */
+bool
+zchar_show_width_only(const gs_text_enum_t * penum)
+{
+ if (!gs_text_is_width_only(penum))
+ return false;
+ switch (penum->orig_font->FontType) {
+ case ft_encrypted:
+ case ft_encrypted2:
+ case ft_CID_encrypted:
+ case ft_CID_TrueType:
+ case ft_CID_bitmap:
+ case ft_TrueType:
+ return true;
+ default:
+ return false;
+ }
}
/* Shortcut the BuildChar or BuildGlyph procedure at the point */
@@ -603,7 +657,7 @@ op_show_return_width(i_ctx_t *i_ctx_p, uint npop, double *pwidth)
{
uint index = op_show_find_index(i_ctx_p);
es_ptr ep = (es_ptr) ref_stack_index(&e_stack, index - (snumpush - 1));
- int code = gs_setcharwidth(esenum(ep), igs, pwidth[0], pwidth[1]);
+ int code = gs_text_setcharwidth(esenum(ep), pwidth);
uint ocount, dsaved, dcount;
if (code < 0)
@@ -637,7 +691,7 @@ private int
op_show_restore(i_ctx_t *i_ctx_p, bool for_error)
{
register es_ptr ep = esp + snumpush;
- gs_show_enum *penum = esenum(ep);
+ gs_text_enum_t *penum = esenum(ep);
int saved_level = esgslevel(ep).value.intval;
int code = 0;
@@ -651,14 +705,19 @@ op_show_restore(i_ctx_t *i_ctx_p, bool for_error)
if (SHOW_IS_STRINGWIDTH(penum)) { /* stringwidth does an extra gsave */
--saved_level;
}
+ if (penum->text.operation & TEXT_REPLACE_WIDTHS) {
+ gs_free_const_object(penum->memory, penum->text.y_widths, "y_widths");
+ if (penum->text.x_widths != penum->text.y_widths)
+ gs_free_const_object(penum->memory, penum->text.x_widths, "x_widths");
+ }
/*
- * We might have been inside a cshow, in which case currentfont
- * was reset temporarily, as though we were inside a BuildChar/
- * BuildGlyph procedure. If this is the case, set currentfont
- * back to its normal state, the root font.
+ * We might have been inside a cshow, in which case currentfont was
+ * reset temporarily, as though we were inside a BuildChar/ BuildGlyph
+ * procedure. To handle this case, set currentfont back to its original
+ * state. NOTE: this code previously used fstack[0] in the enumerator
+ * for the root font: we aren't sure that this change is correct.
*/
- if (penum->fstack.depth >= 0)
- gs_set_currentfont(igs, penum->fstack.items[0].font);
+ gs_set_currentfont(igs, penum->orig_font);
while (igs->level > saved_level && code >= 0) {
if (igs->saved == 0 || igs->saved->saved == 0) {
/*
@@ -669,7 +728,7 @@ op_show_restore(i_ctx_t *i_ctx_p, bool for_error)
} else
code = gs_grestore(igs);
}
- gs_show_enum_release(penum, (gs_memory_t *) imemory);
+ gs_text_release(penum, "op_show_restore");
return code;
}
/* Clean up after an error. */
diff --git a/gs/src/zchar1.c b/gs/src/zchar1.c
index 281fed557..4ef90aac7 100644
--- a/gs/src/zchar1.c
+++ b/gs/src/zchar1.c
@@ -24,8 +24,6 @@
#include "gsstruct.h"
#include "gxfixed.h"
#include "gxmatrix.h"
-#include "gxchar.h" /* for gs_type1_init in gstype1.h */
- /* (should only be gschar.h) */
#include "gxdevice.h" /* for gxfont.h */
#include "gxfont.h"
#include "gxfont1.h"
@@ -46,7 +44,7 @@
#include "iname.h"
#include "store.h"
-/* ---------------- Inline utilities ---------------- */
+/* ---------------- Utilities ---------------- */
/* Test whether a font is a CharString font. */
private bool
@@ -57,6 +55,22 @@ font_uses_charstrings(const gs_font *pfont)
pfont->FontType == ft_disk_based);
}
+/* Initialize a Type 1 interpreter. */
+private int
+type1_exec_init(gs_type1_state *pcis, gs_text_enum_t *penum,
+ gs_state *pgs, gs_font_type1 *pfont1)
+{
+ /*
+ * We have to disregard penum->pis and penum->path, and render to
+ * the current gstate and path. This is a design bug that we will
+ * have to address someday!
+ */
+ return gs_type1_interp_init(pcis, (gs_imager_state *)pgs, pgs->path,
+ &penum->log2_scale,
+ (penum->text.operation & TEXT_DO_ANY_CHARPATH) != 0,
+ pfont1->PaintType, pfont1);
+}
+
/* ---------------- .type1execchar ---------------- */
/*
@@ -131,14 +145,14 @@ charstring_execchar(i_ctx_t *i_ctx_p, int font_type_mask)
gs_font_base *const pbfont = (gs_font_base *) pfont;
gs_font_type1 *const pfont1 = (gs_font_type1 *) pfont;
const gs_type1_data *pdata;
- gs_show_enum *penum = op_show_find(i_ctx_p);
+ gs_text_enum_t *penum = op_show_find(i_ctx_p);
gs_type1exec_state cxs;
gs_type1_state *const pcis = &cxs.cis;
if (code < 0)
return code;
if (penum == 0 ||
- pfont->FontType > sizeof(font_type_mask) * 8 ||
+ pfont->FontType >= sizeof(font_type_mask) * 8 ||
!(font_type_mask & (1 << (int)pfont->FontType)))
return_error(e_undefined);
pdata = &pfont1->data;
@@ -179,9 +193,7 @@ charstring_execchar(i_ctx_t *i_ctx_p, int font_type_mask)
code = gs_moveto(igs, 0.0, 0.0);
if (code < 0)
return code;
- code = gs_type1_init(pcis, penum, NULL,
- gs_show_in_charpath(penum) != cpm_show,
- pfont1->PaintType, pfont1);
+ code = type1_exec_init(pcis, penum, igs, pfont1);
if (code < 0)
return code;
gs_type1_set_callback_data(pcis, &cxs);
@@ -341,7 +353,7 @@ bbox_finish(i_ctx_t *i_ctx_p, int (*cont) (P1(i_ctx_t *)))
os_ptr op = osp;
gs_font *pfont;
int code;
- gs_show_enum *penum = op_show_find(i_ctx_p);
+ gs_text_enum_t *penum = op_show_find(i_ctx_p);
gs_type1exec_state cxs; /* stack allocate to avoid sandbars */
gs_type1_state *const pcis = &cxs.cis;
double sbxy[2];
@@ -374,11 +386,11 @@ bbox_finish(i_ctx_t *i_ctx_p, int (*cont) (P1(i_ctx_t *)))
if (lenIV > 0 && r_size(opc) <= lenIV)
return_error(e_invalidfont);
check_estack(5); /* in case we need to do a callout */
- code = gs_type1_init(pcis, penum, psbpt,
- gs_show_in_charpath(penum) != cpm_show,
- pfont1->PaintType, pfont1);
+ code = type1_exec_init(pcis, penum, igs, pfont1);
if (code < 0)
return code;
+ if (psbpt)
+ gs_type1_set_lsb(pcis, psbpt);
}
opstr = opc;
icont:
@@ -430,7 +442,7 @@ bbox_draw(i_ctx_t *i_ctx_p, int (*draw)(P1(gs_state *)))
os_ptr op = osp;
gs_rect bbox;
gs_font *pfont;
- gs_show_enum *penum;
+ gs_text_enum_t *penum;
gs_font_base * pbfont;
gs_font_type1 * pfont1;
gs_type1exec_state cxs;
@@ -458,21 +470,13 @@ bbox_draw(i_ctx_t *i_ctx_p, int (*draw)(P1(gs_state *)))
/* Enlarge the FontBBox to save work in the future. */
rect_merge(pbfont->FontBBox, bbox);
/* Dismantle everything we've done, and start over. */
- if (penum->cc) {
- gx_free_cached_char(pfont->dir, penum->cc);
- penum->cc = 0;
- }
- gs_grestore(penum->pgs);
- penum->width_status = sws_none;
- penum->log2_current_scale.x = penum->log2_current_scale.y = 0;
+ gs_text_retry(penum);
pfont1 = (gs_font_type1 *) pfont;
code = zchar_get_metrics(pbfont, op - 1, cxs.sbw);
if (code < 0)
return code;
cxs.present = code;
- code = gs_type1_init(&cxs.cis, penum, NULL,
- gs_show_in_charpath(penum) != cpm_show,
- pfont1->PaintType, pfont1);
+ code = type1_exec_init(&cxs.cis, penum, igs, pfont1);
if (code < 0)
return code;
cxs.char_bbox = pfont1->FontBBox;
@@ -671,7 +675,7 @@ nobbox_finish(i_ctx_t *i_ctx_p, gs_type1exec_state * pcxs)
{
os_ptr op = osp;
int code;
- gs_show_enum *penum = op_show_find(i_ctx_p);
+ gs_text_enum_t *penum = op_show_find(i_ctx_p);
gs_font *pfont;
if ((code = gs_pathbbox(igs, &pcxs->char_bbox)) < 0 ||
@@ -700,9 +704,7 @@ nobbox_finish(i_ctx_t *i_ctx_p, gs_type1exec_state * pcxs)
) {
gs_newpath(igs);
gs_moveto(igs, 0.0, 0.0);
- code = gs_type1_init(&pcxs->cis, penum, NULL,
- gs_show_in_charpath(penum) != cpm_show,
- pfont1->PaintType, pfont1);
+ code = type1_exec_init(&pcxs->cis, penum, igs, pfont1);
if (code < 0)
return code;
return type1exec_bbox(i_ctx_p, pcxs, pfont);
@@ -759,30 +761,12 @@ const op_def zchar1_op_defs[] =
/* ------ Auxiliary procedures for type 1 fonts ------ */
private int
-z1_charstring_data(gs_font_type1 * pfont, const ref * pgref,
- gs_const_string * pstr)
-{
- ref *pcstr;
-
- if (dict_find(&pfont_data(pfont)->CharStrings, pgref, &pcstr) <= 0)
- return_error(e_undefined);
- check_type_only(*pcstr, t_string);
- pstr->data = pcstr->value.const_bytes;
- pstr->size = r_size(pcstr);
- return 0;
-
-}
-
-private int
z1_glyph_data(gs_font_type1 * pfont, gs_glyph glyph, gs_const_string * pstr)
{
ref gref;
- if (glyph < gs_min_cid_glyph)
- name_index_ref(glyph, &gref);
- else
- make_int(&gref, glyph - gs_min_cid_glyph);
- return z1_charstring_data(pfont, &gref, pstr);
+ glyph_ref(glyph, &gref);
+ return zchar_charstring_data((gs_font *)pfont, &gref, pstr);
}
private int
@@ -812,34 +796,7 @@ z1_seac_data(gs_font_type1 * pfont, int index, gs_const_string * pstr)
if (code < 0)
return code;
- return z1_charstring_data(pfont, &enc_entry, pstr);
-}
-
-private int
-z1_next_glyph(gs_font_type1 * pfont, int *pindex, gs_glyph * pglyph)
-{
- ref *pcsdict = &pfont_data(pfont)->CharStrings;
- int index = *pindex - 1;
- ref elt[2];
-
- if (index < 0)
- index = dict_first(pcsdict);
-next:
- index = dict_next(pcsdict, index, elt);
- *pindex = index + 1;
- if (index >= 0) {
- switch (r_type(elt)) {
- case t_integer:
- *pglyph = gs_min_cid_glyph + elt[0].value.intval;
- break;
- case t_name:
- *pglyph = name_index(elt);
- break;
- default: /* can't handle it */
- goto next;
- }
- }
- return 0;
+ return zchar_charstring_data((gs_font *)pfont, &enc_entry, pstr);
}
private int
@@ -874,8 +831,93 @@ z1_pop(void *callback_data, fixed * pf)
}
/* Define the Type 1 procedure vector. */
-const gs_type1_data_procs_t z1_data_procs =
-{
- z1_glyph_data, z1_subr_data, z1_seac_data, z1_next_glyph,
- z1_push, z1_pop
+const gs_type1_data_procs_t z1_data_procs = {
+ z1_glyph_data, z1_subr_data, z1_seac_data, z1_push, z1_pop
};
+
+/* ------ Font procedures for Type 1 fonts ------ */
+
+int
+zcharstring_glyph_outline(gs_font *font, gs_glyph glyph, const gs_matrix *pmat,
+ gx_path *ppath)
+{
+ gs_font_type1 *const pfont1 = (gs_font_type1 *)font;
+ gs_const_string charstring;
+ ref gref;
+ gs_const_string *pchars = &charstring;
+ int code;
+ gs_type1exec_state cxs;
+ gs_type1_state *const pcis = &cxs.cis;
+ static const gs_log2_scale_point no_scale = {0, 0};
+ const gs_type1_data *pdata;
+ const ref *pfdict;
+ ref *pcdevproc;
+ int value;
+ gs_imager_state gis;
+ double sbw[4];
+ gs_point mpt;
+
+ glyph_ref(glyph, &gref);
+ code = zchar_charstring_data(font, &gref, &charstring);
+ if (code < 0)
+ return code;
+ pdata = &pfont1->data;
+ if (charstring.size <= max(pdata->lenIV, 0))
+ return_error(e_invalidfont);
+ pfdict = &pfont_data(pfont1)->dict;
+ if (dict_find_string(pfdict, "CDevProc", &pcdevproc) > 0)
+ return_error(e_rangecheck); /* can't call CDevProc from here */
+ switch (font->WMode) {
+ default:
+ code = zchar_get_metrics2((gs_font_base *)pfont1, &gref, sbw);
+ if (code)
+ break;
+ /* falls through */
+ case 0:
+ code = zchar_get_metrics((gs_font_base *)pfont1, &gref, sbw);
+ }
+ if (code < 0)
+ return code;
+ cxs.present = code;
+ /* Initialize just enough of the imager state. */
+ if (pmat)
+ gs_matrix_fixed_from_matrix(&gis.ctm, pmat);
+ else {
+ gs_matrix imat;
+
+ gs_make_identity(&imat);
+ gs_matrix_fixed_from_matrix(&gis.ctm, &imat);
+ }
+ gis.flatness = 0;
+ code = gs_type1_interp_init(&cxs.cis, &gis, ppath, &no_scale, true, 0,
+ pfont1);
+ if (code < 0)
+ return code;
+ gs_type1_set_callback_data(pcis, &cxs);
+ switch (cxs.present) {
+ case metricsSideBearingAndWidth:
+ mpt.x = sbw[0], mpt.y = sbw[1];
+ gs_type1_set_lsb(pcis, &mpt);
+ /* falls through */
+ case metricsWidthOnly:
+ mpt.x = sbw[2], mpt.y = sbw[3];
+ gs_type1_set_width(pcis, &mpt);
+ case metricsNone:
+ ;
+ }
+ /* Continue interpreting. */
+icont:
+ code = pfont1->data.interpret(pcis, pchars, &value);
+ switch (code) {
+ case 0: /* all done */
+ /* falls through */
+ default: /* code < 0, error */
+ return code;
+ case type1_result_callothersubr: /* unknown OtherSubr */
+ return_error(e_rangecheck); /* can't handle it */
+ case type1_result_sbw: /* [h]sbw, just continue */
+ type1_cis_get_metrics(pcis, cxs.sbw);
+ pchars = 0;
+ goto icont;
+ }
+}
diff --git a/gs/src/zchar32.c b/gs/src/zchar32.c
index bf90d9c6c..f9eecceda 100644
--- a/gs/src/zchar32.c
+++ b/gs/src/zchar32.c
@@ -24,7 +24,6 @@
#include "gsmatrix.h"
#include "gsutil.h"
#include "gxfixed.h"
-#include "gxchar.h"
#include "gxfont.h"
#include "gxfcache.h"
#include "ifont.h"
diff --git a/gs/src/zchar42.c b/gs/src/zchar42.c
index e23eac752..aa9506c28 100644
--- a/gs/src/zchar42.c
+++ b/gs/src/zchar42.c
@@ -24,11 +24,11 @@
#include "gspaint.h" /* for gs_fill, gs_stroke */
#include "gspath.h"
#include "gxfixed.h"
-#include "gxchar.h"
#include "gxfont.h"
#include "gxfont42.h"
#include "gxistate.h"
#include "gxpath.h"
+#include "gxtext.h"
#include "gzstate.h" /* only for ->path */
#include "dstack.h" /* only for systemdict */
#include "estack.h"
@@ -38,14 +38,6 @@
#include "igstate.h"
#include "store.h"
-/* Imported procedures */
-int gs_type42_append(P7(uint glyph_index, gs_imager_state * pis,
- gx_path * ppath, const gs_log2_scale_point * pscale,
- bool charpath_flag, int paint_type,
- gs_font_type42 * pfont));
-int gs_type42_get_metrics(P3(gs_font_type42 * pfont, uint glyph_index,
- float psbw[4]));
-
/* <font> <code|name> <name> <glyph_index> .type42execchar - */
private int type42_fill(P1(i_ctx_t *));
private int type42_stroke(P1(i_ctx_t *));
@@ -56,7 +48,7 @@ ztype42execchar(i_ctx_t *i_ctx_p)
gs_font *pfont;
int code = font_param(op - 3, &pfont);
gs_font_base *const pbfont = (gs_font_base *) pfont;
- gs_show_enum *penum = op_show_find(i_ctx_p);
+ gs_text_enum_t *penum = op_show_find(i_ctx_p);
int present;
double sbw[4];
@@ -135,7 +127,7 @@ type42_finish(i_ctx_t *i_ctx_p, int (*cont) (P1(gs_state *)))
os_ptr op = osp;
gs_font *pfont;
int code;
- gs_show_enum *penum = op_show_find(i_ctx_p);
+ gs_text_enum_t *penum = op_show_find(i_ctx_p);
double sbxy[2];
gs_point sbpt;
gs_point *psbpt = 0;
@@ -159,17 +151,19 @@ type42_finish(i_ctx_t *i_ctx_p, int (*cont) (P1(gs_state *)))
pfont->FontType != ft_CID_TrueType)
)
return_error(e_undefined);
- code = gs_type42_append((uint) opc->value.intval,
- (gs_imager_state *) penum->pgs,
- penum->pgs->path,
- &penum->log2_current_scale,
- gs_show_in_charpath(penum) != cpm_show,
- pfont->PaintType,
- (gs_font_type42 *) pfont);
+ /*
+ * We have to disregard penum->pis and penum->path, and render to
+ * the current gstate and path. This is a design bug that we will
+ * have to address someday!
+ */
+ code = gs_type42_append((uint)opc->value.intval, (gs_imager_state *)igs,
+ igs->path, &penum->log2_scale,
+ (penum->text.operation & TEXT_DO_ANY_CHARPATH) != 0,
+ pfont->PaintType, (gs_font_type42 *)pfont);
if (code < 0)
return code;
pop((psbpt == 0 ? 4 : 6));
- return (*cont)(penum->pgs);
+ return (*cont)(igs);
}
/* ------ Initialization procedure ------ */
diff --git a/gs/src/zcharout.c b/gs/src/zcharout.c
index 924fd74ba..b7d96df6a 100644
--- a/gs/src/zcharout.c
+++ b/gs/src/zcharout.c
@@ -20,7 +20,7 @@
/* Common code for outline (Type 1 / 4 / 42) fonts */
#include "ghost.h"
#include "oper.h"
-#include "gschar.h"
+#include "gstext.h"
#include "gxdevice.h" /* for gxfont.h */
#include "gxfont.h"
#include "dstack.h" /* only for systemdict */
@@ -30,12 +30,9 @@
#include "idict.h"
#include "ifont.h"
#include "igstate.h"
+#include "iname.h"
#include "store.h"
-/* Imported operators */
-int zsetcachedevice(P1(i_ctx_t *)); /* zchar.c */
-int zsetcachedevice2(P1(i_ctx_t *)); /* zchar.c */
-
/*
* Execute an outline defined by a PostScript procedure.
* The top elements of the stack are:
@@ -119,6 +116,31 @@ zchar_get_metrics(const gs_font_base * pbfont, const ref * pcnref,
return metricsNone;
}
+/* Get the vertical metrics for a character from Metrics2, if present. */
+int
+zchar_get_metrics2(const gs_font_base * pbfont, const ref * pcnref,
+ double pwv[4])
+{
+ const ref *pfdict = &pfont_data(pbfont)->dict;
+ ref *pmdict;
+
+ if (dict_find_string(pfdict, "Metrics2", &pmdict) > 0) {
+ ref *pmvalue;
+
+ check_type_only(*pmdict, t_dictionary);
+ check_dict_read(*pmdict);
+ if (dict_find(pmdict, pcnref, &pmvalue) > 0) {
+ check_read_type_only(*pmvalue, t_array);
+ if (r_size(pmvalue) == 4) {
+ int code = num_params(pmvalue->value.refs + 3, 4, pwv);
+
+ return (code < 0 ? code : metricsSideBearingAndWidth);
+ }
+ }
+ }
+ return metricsNone;
+}
+
/*
* Consult Metrics2 and CDevProc, and call setcachedevice[2]. Return
* o_push_estack if we had to call a CDevProc, or if we are skipping the
@@ -132,14 +154,13 @@ zchar_set_cache(i_ctx_t *i_ctx_p, const gs_font_base * pbfont,
{
os_ptr op = osp;
const ref *pfdict = &pfont_data(pbfont)->dict;
- ref *pmdict;
ref *pcdevproc;
int have_cdevproc;
ref rpop;
- bool metrics2 = false;
+ bool metrics2;
op_proc_t cont;
double w2[10];
- gs_show_enum *penum = op_show_find(i_ctx_p);
+ gs_text_enum_t *penum = op_show_find(i_ctx_p);
w2[0] = pwidth[0], w2[1] = pwidth[1];
@@ -160,26 +181,18 @@ zchar_set_cache(i_ctx_t *i_ctx_p, const gs_font_base * pbfont,
/* Check for Metrics2. */
- if (dict_find_string(pfdict, "Metrics2", &pmdict) > 0) {
- ref *pmvalue;
-
- check_type_only(*pmdict, t_dictionary);
- check_dict_read(*pmdict);
- if (dict_find(pmdict, pcnref, &pmvalue) > 0) {
- check_read_type_only(*pmvalue, t_array);
- if (r_size(pmvalue) == 4) {
- int code = num_params(pmvalue->value.refs + 3, 4, w2 + 6);
+ {
+ int code = zchar_get_metrics2(pbfont, pcnref, w2 + 6);
- if (code < 0)
- return code;
- metrics2 = true;
- }
- }
+ if (code < 0)
+ return code;
+ metrics2 = code > 0;
}
+
/* Check for CDevProc or "short-circuiting". */
have_cdevproc = dict_find_string(pfdict, "CDevProc", &pcdevproc) > 0;
- if (have_cdevproc || gs_show_width_only(penum)) {
+ if (have_cdevproc || zchar_show_width_only(penum)) {
int i;
op_proc_t zsetc;
int nparams;
@@ -219,8 +232,8 @@ zchar_set_cache(i_ctx_t *i_ctx_p, const gs_font_base * pbfont,
return o_push_estack;
} {
int code =
- (metrics2 ? gs_setcachedevice2_double(penum, igs, w2) :
- gs_setcachedevice_double(penum, igs, w2));
+ (metrics2 ? gs_text_setcachedevice2(penum, w2) :
+ gs_text_setcachedevice(penum, w2));
if (code < 0)
return code;
@@ -236,3 +249,51 @@ zchar_set_cache(i_ctx_t *i_ctx_p, const gs_font_base * pbfont,
}
return cont(i_ctx_p);
}
+
+/*
+ * Get the CharString data corresponding to a glyph. Return typecheck
+ * if it isn't a string.
+ */
+int
+zchar_charstring_data(gs_font *font, const ref *pgref, gs_const_string *pstr)
+{
+ ref *pcstr;
+
+ if (dict_find(&pfont_data(font)->CharStrings, pgref, &pcstr) <= 0)
+ return_error(e_undefined);
+ check_type_only(*pcstr, t_string);
+ pstr->data = pcstr->value.const_bytes;
+ pstr->size = r_size(pcstr);
+ return 0;
+}
+
+/*
+ * Enumerate the next glyph from a directory. This is essentially a
+ * wrapper around dict_first/dict_next to implement the enumerate_glyph
+ * font procedure.
+ */
+int
+zchar_enumerate_glyph(const ref *prdict, int *pindex, gs_glyph *pglyph)
+{
+ int index = *pindex - 1;
+ ref elt[2];
+
+ if (index < 0)
+ index = dict_first(prdict);
+next:
+ index = dict_next(prdict, index, elt);
+ *pindex = index + 1;
+ if (index >= 0) {
+ switch (r_type(elt)) {
+ case t_integer:
+ *pglyph = gs_min_cid_glyph + elt[0].value.intval;
+ break;
+ case t_name:
+ *pglyph = name_index(elt);
+ break;
+ default: /* can't handle it */
+ goto next;
+ }
+ }
+ return 0;
+}
diff --git a/gs/src/zcharx.c b/gs/src/zcharx.c
index b20d111c1..4f0cc5b9a 100644
--- a/gs/src/zcharx.c
+++ b/gs/src/zcharx.c
@@ -20,34 +20,15 @@
/* Level 2 character operators */
#include "ghost.h"
#include "oper.h"
-#include "gschar.h"
#include "gsmatrix.h" /* for gxfont.h */
-#include "gsstruct.h" /* for st_stream */
+#include "gstext.h"
#include "gxfixed.h" /* for gxfont.h */
#include "gxfont.h"
-#include "gxchar.h"
-#include "estack.h"
#include "ialloc.h"
#include "ichar.h"
-#include "ifont.h"
#include "igstate.h"
#include "iname.h"
-#include "store.h"
-#include "stream.h"
#include "ibnum.h"
-#include "gspath.h" /* gs_rmoveto prototype */
-
-/* Table of continuation procedures. */
-private int xshow_continue(P1(i_ctx_t *));
-private int yshow_continue(P1(i_ctx_t *));
-private int xyshow_continue(P1(i_ctx_t *));
-static const op_proc_t xyshow_continues[4] = {
- 0, xshow_continue, yshow_continue, xyshow_continue
-};
-
-/* Forward references */
-private int moveshow(P2(i_ctx_t *, int));
-private int moveshow_continue(P2(i_ctx_t *, int));
/* <charname> glyphshow - */
private int
@@ -55,7 +36,7 @@ zglyphshow(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
gs_glyph glyph;
- gs_show_enum *penum;
+ gs_text_enum_t *penum;
int code;
switch (gs_currentfont(igs)->FontType) {
@@ -70,141 +51,79 @@ zglyphshow(i_ctx_t *i_ctx_p)
check_type(*op, t_name);
glyph = name_index(op);
}
- if ((code = op_show_enum_setup(i_ctx_p, &penum)) != 0)
+ if ((code = op_show_enum_setup(i_ctx_p)) != 0 ||
+ (code = gs_glyphshow_begin(igs, glyph, imemory, &penum)) < 0)
return code;
- if ((code = gs_glyphshow_init(penum, igs, glyph)) < 0) {
+ if ((code = op_show_finish_setup(i_ctx_p, penum, 1, NULL)) < 0) {
ifree_object(penum, "op_show_glyph");
return code;
}
- op_show_finish_setup(i_ctx_p, penum, 1, NULL);
return op_show_continue_pop(i_ctx_p, 1);
}
/* <string> <numarray|numstring> xshow - */
-private int
-zxshow(i_ctx_t *i_ctx_p)
-{
- return moveshow(i_ctx_p, 1);
-}
-
/* <string> <numarray|numstring> yshow - */
-private int
-zyshow(i_ctx_t *i_ctx_p)
-{
- return moveshow(i_ctx_p, 2);
-}
-
/* <string> <numarray|numstring> xyshow - */
private int
-zxyshow(i_ctx_t *i_ctx_p)
-{
- return moveshow(i_ctx_p, 3);
-}
-
-/* Common code for {x,y,xy}show */
-private int
-moveshow(i_ctx_t *i_ctx_p, int xymask)
+moveshow(i_ctx_t *i_ctx_p, bool have_x, bool have_y)
{
os_ptr op = osp;
- gs_show_enum *penum;
- int code = op_show_setup(i_ctx_p, op - 1, &penum);
+ gs_text_enum_t *penum;
+ int code = op_show_setup(i_ctx_p, op - 1);
+ int format;
+ uint i, size;
+ float *values;
if (code != 0)
return code;
- if ((code = gs_xyshow_n_init(penum, igs, (char *)op[-1].value.bytes, r_size(op - 1)) < 0)) {
- ifree_object(penum, "op_show_enum_setup");
- return code;
+ format = num_array_format(op);
+ if (format < 0)
+ return format;
+ size = num_array_size(op, format);
+ values = (float *)ialloc_byte_array(size, sizeof(float), "moveshow");
+ if (values == 0)
+ return_error(e_VMerror);
+ for (i = 0; i < size; ++i) {
+ ref value;
+
+ switch (code = num_array_get(op, format, i, &value)) {
+ case t_integer:
+ values[i] = value.value.intval; break;
+ case t_real:
+ values[i] = value.value.realval; break;
+ case t_null:
+ code = gs_note_error(e_rangecheck);
+ /* falls through */
+ default:
+ ifree_object(values, "moveshow");
+ return code;
+ }
}
- code = num_array_format(op);
- if (code < 0) {
- ifree_object(penum, "op_show_enum_setup");
+ if ((code = gs_xyshow_begin(igs, op[-1].value.bytes, r_size(op - 1),
+ (have_x ? values : (float *)0),
+ (have_y ? values : (float *)0),
+ size, imemory, &penum)) < 0 ||
+ (code = op_show_finish_setup(i_ctx_p, penum, 2, NULL)) < 0) {
+ ifree_object(values, "moveshow");
return code;
}
- op_show_finish_setup(i_ctx_p, penum, 2, NULL);
- ref_assign(&sslot, op);
pop(2);
- return moveshow_continue(i_ctx_p, xymask);
+ return op_show_continue(i_ctx_p);
}
-
-/* Continuation procedures */
-
private int
-xshow_continue(i_ctx_t *i_ctx_p)
-{
- return moveshow_continue(i_ctx_p, 1);
-}
-
-private int
-yshow_continue(i_ctx_t *i_ctx_p)
-{
- return moveshow_continue(i_ctx_p, 2);
-}
-
-private int
-xyshow_continue(i_ctx_t *i_ctx_p)
+zxshow(i_ctx_t *i_ctx_p)
{
- return moveshow_continue(i_ctx_p, 3);
+ return moveshow(i_ctx_p, true, false);
}
-
-/* Get one value from the encoded number string or array. */
-/* Sets pvalue->value.realval. */
private int
-sget_real(const ref * nsp, int format, uint index, ref * pvalue)
+zyshow(i_ctx_t *i_ctx_p)
{
- int code;
-
- switch (code = num_array_get(nsp, format, index, pvalue)) {
- case t_integer:
- pvalue->value.realval = pvalue->value.intval;
- case t_real:
- return t_real;
- case t_null:
- code = gs_note_error(e_rangecheck);
- default:
- return code;
- }
+ return moveshow(i_ctx_p, false, true);
}
-
private int
-moveshow_continue(i_ctx_t *i_ctx_p, int xymask)
+zxyshow(i_ctx_t *i_ctx_p)
{
- const ref *nsp = &sslot;
- int format = num_array_format(nsp);
- int code;
- gs_show_enum *penum = senum;
- uint index = ssindex.value.intval;
-
- for (;;) {
- ref rwx, rwy;
-
- code = gs_show_next(penum);
- if (code != gs_show_move) {
- ssindex.value.intval = index;
- code = op_show_continue_dispatch(i_ctx_p, 0, code);
- if (code == o_push_estack) { /* must be gs_show_render */
- make_op_estack(esp - 1, xyshow_continues[xymask]);
- }
- return code;
- }
- /* Move according to the next value(s) from the stream. */
- if (xymask & 1) {
- code = sget_real(nsp, format, index++, &rwx);
- if (code < 0)
- break;
- } else
- rwx.value.realval = 0;
- if (xymask & 2) {
- code = sget_real(nsp, format, index++, &rwy);
- if (code < 0)
- break;
- } else
- rwy.value.realval = 0;
- code = gs_rmoveto(igs, rwx.value.realval, rwy.value.realval);
- if (code < 0)
- break;
- }
- /* An error occurred. Clean up before returning. */
- return op_show_free(i_ctx_p, code);
+ return moveshow(i_ctx_p, true, true);
}
/* ------ Initialization procedure ------ */
@@ -216,9 +135,5 @@ const op_def zcharx_op_defs[] =
{"2xshow", zxshow},
{"2xyshow", zxyshow},
{"2yshow", zyshow},
- /* Internal operators */
- {"0%xshow_continue", xshow_continue},
- {"0%yshow_continue", yshow_continue},
- {"0%xyshow_continue", xyshow_continue},
op_def_end(0)
};
diff --git a/gs/src/zcie.c b/gs/src/zcie.c
index f51cb5e5d..9eb58c006 100644
--- a/gs/src/zcie.c
+++ b/gs/src/zcie.c
@@ -603,6 +603,7 @@ cie_cache_finish_store(i_ctx_t *i_ctx_p, bool replicate)
/* the pointer to the cache. */
pcache = (cie_cache_floats *) (r_ptr(esp - 1, char) + esp->value.intval);
+ pcache->params.is_identity = false; /* cache_set_linear computes this */
if_debug3('c', "[c]cache 0x%lx base=%g, factor=%g:\n",
(ulong) pcache, pcache->params.base, pcache->params.factor);
if (replicate ||
diff --git a/gs/src/zcolor.c b/gs/src/zcolor.c
index 745f73a18..8ab2e6ec4 100644
--- a/gs/src/zcolor.c
+++ b/gs/src/zcolor.c
@@ -32,10 +32,6 @@
#include "gxcmap.h"
#include "icolor.h"
-/* Import the 'for' operator */
-extern int
- zfor_fraction(P1(i_ctx_t *));
-
/* Imported from gsht.c */
void gx_set_effective_transfer(P1(gs_state *));
diff --git a/gs/src/zcolor1.c b/gs/src/zcolor1.c
index 7aed55910..17972661a 100644
--- a/gs/src/zcolor1.c
+++ b/gs/src/zcolor1.c
@@ -193,50 +193,11 @@ zsetundercolorremoval(i_ctx_t *i_ctx_p)
/* <width> <height> <bits/comp> <matrix> */
/* <datasrc_0> ... <datasrc_ncomp-1> true <ncomp> colorimage - */
/* <datasrc> false <ncomp> colorimage - */
-int zimage_multiple(P2(i_ctx_t *i_ctx_p, bool has_alpha));
private int
zcolorimage(i_ctx_t *i_ctx_p)
{
return zimage_multiple(i_ctx_p, false);
}
-/* We export zimage_multiple for alphaimage. */
-int
-zimage_multiple(i_ctx_t *i_ctx_p, bool has_alpha)
-{
- os_ptr op = osp;
- int spp; /* samples per pixel */
- int npop = 7;
- os_ptr procp = op - 2;
- const gs_color_space *pcs;
- bool multi = false;
-
- check_int_leu(*op, 4); /* ncolors */
- check_type(op[-1], t_boolean); /* multiproc */
- switch ((spp = (int)(op->value.intval))) {
- case 1:
- pcs = gs_current_DeviceGray_space(igs);
- break;
- case 3:
- pcs = gs_current_DeviceRGB_space(igs);
- goto color;
- case 4:
- pcs = gs_current_DeviceCMYK_space(igs);
-color:
- if (op[-1].value.boolval) { /* planar format */
- if (has_alpha)
- ++spp;
- npop += spp - 1;
- procp -= spp - 1;
- multi = true;
- }
- break;
- default:
- return_error(e_rangecheck);
- }
- return zimage_opaque_setup(i_ctx_p, procp, multi,
- (has_alpha ? gs_image_alpha_last : gs_image_alpha_none),
- pcs, npop);
-}
/* ------ Initialization procedure ------ */
diff --git a/gs/src/zcontext.c b/gs/src/zcontext.c
index f12374128..c79885c4d 100644
--- a/gs/src/zcontext.c
+++ b/gs/src/zcontext.c
@@ -93,24 +93,25 @@ struct gs_context_s {
};
/* GC descriptor */
-#define pctx ((gs_context *)vptr)
private
CLEAR_MARKS_PROC(context_clear_marks)
{
+ gs_context *const pctx = vptr;
+
(*st_context_state.clear_marks)
(&pctx->state, sizeof(pctx->state), &st_context_state);
}
private
-ENUM_PTRS_BEGIN(context_enum_ptrs) ENUM_PREFIX(st_context_state, 4);
-
+ENUM_PTRS_BEGIN(context_enum_ptrs)
+ENUM_PREFIX(st_context_state, 4);
ENUM_PTR3(0, gs_context, scheduler, next, joiner);
ENUM_PTR(3, gs_context, table_next);
ENUM_PTRS_END
-private RELOC_PTRS_BEGIN(context_reloc_ptrs) RELOC_PREFIX(st_context_state);
+private RELOC_PTRS_BEGIN(context_reloc_ptrs)
+RELOC_PREFIX(st_context_state);
RELOC_PTR3(gs_context, scheduler, next, joiner);
RELOC_PTR(gs_context, table_next);
RELOC_PTRS_END
-#undef pctx
gs_private_st_complex_only(st_context, gs_context, "context",
context_clear_marks, context_enum_ptrs, context_reloc_ptrs, 0);
@@ -146,7 +147,6 @@ struct gs_scheduler_s {
#define CTX_TABLE_SIZE 19
gs_context *table[CTX_TABLE_SIZE];
};
-private gs_scheduler_t *the_gs_scheduler;
/* Structure definition */
gs_private_st_composite(st_scheduler, gs_scheduler_t, "gs_scheduler",
@@ -237,6 +237,7 @@ zcontext_init(i_ctx_t *i_ctx_p)
private int
ctx_initialize(i_ctx_t **pi_ctx_p)
{
+ i_ctx_t *i_ctx_p = *pi_ctx_p; /* for gs_imemory */
gs_ref_memory_t *imem = iimemory_system;
gs_scheduler_t *psched =
gs_alloc_struct((gs_memory_t *) imem, gs_scheduler_t,
@@ -251,10 +252,7 @@ ctx_initialize(i_ctx_t **pi_ctx_p)
lprintf("Can't create initial context!");
gs_abort();
}
- the_gs_scheduler = psched;
- gs_register_struct_root((gs_memory_t *) imem, NULL,
- (void **)&the_gs_scheduler,
- "the_gs_scheduler");
+ psched->current->scheduler = psched;
/* Hook into the interpreter. */
*pi_ctx_p = &psched->current->state;
gs_interp_reschedule_proc = ctx_reschedule;
@@ -271,8 +269,8 @@ ctx_initialize(i_ctx_t **pi_ctx_p)
private int
ctx_reschedule(i_ctx_t **pi_ctx_p)
{
- gs_scheduler_t *psched = the_gs_scheduler;
- gs_context *current = psched->current;
+ gs_context *current = (gs_context *)*pi_ctx_p;
+ gs_scheduler_t *psched = current->scheduler;
#ifdef DEBUG
if (*pi_ctx_p != &current->state) {
@@ -351,7 +349,7 @@ ctx_reschedule(i_ctx_t **pi_ctx_p)
private int
ctx_time_slice(i_ctx_t **pi_ctx_p)
{
- gs_scheduler_t *psched = the_gs_scheduler;
+ gs_scheduler_t *psched = ((gs_context *)*pi_ctx_p)->scheduler;
if (psched->active.head == 0)
return 0;
@@ -367,10 +365,10 @@ private int
zcurrentcontext(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
- const gs_scheduler_t *psched = the_gs_scheduler;
+ const gs_context *current = (const gs_context *)i_ctx_p;
push(1);
- make_int(op, psched->current->index);
+ make_int(op, current->index);
return 0;
}
@@ -379,7 +377,7 @@ private int
zdetach(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
- const gs_scheduler_t *psched = the_gs_scheduler;
+ const gs_scheduler_t *psched = ((gs_context *)i_ctx_p)->scheduler;
gs_context *pctx;
int code;
@@ -401,8 +399,8 @@ zdetach(i_ctx_t *i_ctx_p)
}
private int
- do_fork(P5(os_ptr op, const ref * pstdin, const ref * pstdout,
- uint mcount, bool local)),
+ do_fork(P6(i_ctx_t *i_ctx_p, os_ptr op, const ref * pstdin,
+ const ref * pstdout, uint mcount, bool local)),
values_older_than(P4(const ref_stack_t * pstack, uint first, uint last,
int max_space));
private int
@@ -424,7 +422,7 @@ zfork(i_ctx_t *i_ctx_p)
if (mcount == 0)
return_error(e_unmatchedmark);
make_null(&rnull);
- return do_fork(op, &rnull, &rnull, mcount, false);
+ return do_fork(i_ctx_p, op, &rnull, &rnull, mcount, false);
}
private int
zlocalfork(i_ctx_t *i_ctx_p)
@@ -438,7 +436,7 @@ zlocalfork(i_ctx_t *i_ctx_p)
code = values_older_than(&o_stack, 1, mcount - 1, avm_local);
if (code < 0)
return code;
- code = do_fork(op - 2, op - 1, op, mcount - 2, true);
+ code = do_fork(i_ctx_p, op - 2, op - 1, op, mcount - 2, true);
if (code < 0)
return code;
op = osp;
@@ -449,12 +447,11 @@ zlocalfork(i_ctx_t *i_ctx_p)
/* Internal procedure to actually do the fork operation. */
private int
-do_fork(os_ptr op, const ref * pstdin, const ref * pstdout, uint mcount,
- bool local)
+do_fork(i_ctx_t *i_ctx_p, os_ptr op, const ref * pstdin, const ref * pstdout,
+ uint mcount, bool local)
{
- gs_scheduler_t *psched = the_gs_scheduler;
- gs_context *pcur = psched->current;
- i_ctx_t *i_ctx_p = &pcur->state;
+ gs_context *pcur = (gs_context *)i_ctx_p;
+ gs_scheduler_t *psched = pcur->scheduler;
stream *s;
gs_dual_memory_t dmem;
gs_context *pctx;
@@ -462,7 +459,7 @@ do_fork(os_ptr op, const ref * pstdin, const ref * pstdout, uint mcount,
int code;
check_proc(*op);
- if (gs_imemory.save_level)
+ if (iimemory_local->save_level)
return_error(e_invalidcontext);
if (r_has_type(pstdout, t_null)) {
code = zget_stdout(i_ctx_p, &s);
@@ -483,7 +480,9 @@ do_fork(os_ptr op, const ref * pstdin, const ref * pstdout, uint mcount,
/* Share global VM, private local VM. */
ref *puserdict;
uint userdict_size;
+ gs_raw_memory_t *parent = iimemory_local->parent;
gs_ref_memory_t *lmem;
+ gs_ref_memory_t *lmem_stable;
if (dict_find_string(systemdict, "userdict", &puserdict) <= 0 ||
!r_has_type(puserdict, t_dictionary)
@@ -491,17 +490,20 @@ do_fork(os_ptr op, const ref * pstdin, const ref * pstdout, uint mcount,
return_error(e_Fatal);
old_userdict = *puserdict;
userdict_size = dict_maxlength(&old_userdict);
- lmem = ialloc_alloc_state(iimemory_local->parent,
- iimemory_local->chunk_size);
- if (lmem == 0)
+ lmem = ialloc_alloc_state(parent, iimemory_local->chunk_size);
+ lmem_stable = ialloc_alloc_state(parent, iimemory_local->chunk_size);
+ if (lmem == 0 || lmem_stable == 0) {
+ gs_free_object(parent, lmem_stable, "do_fork");
+ gs_free_object(parent, lmem, "do_fork");
return_error(e_VMerror);
- lmem->global = dmem.space_global;
-
+ }
lmem->space = avm_local;
+ lmem_stable->space = avm_local;
+ lmem->stable_memory = (gs_memory_t *)lmem_stable;
dmem.space_local = lmem;
code = context_create(psched, &pctx, &dmem, &pcur->state, false);
if (code < 0) {
-/****** FREE lmem ******/
+ /****** FREE lmem ******/
return code;
}
/*
@@ -511,14 +513,14 @@ do_fork(os_ptr op, const ref * pstdin, const ref * pstdout, uint mcount,
code = dict_alloc(lmem, userdict_size, &new_userdict);
if (code < 0) {
context_destroy(pctx);
-/****** FREE lmem ******/
+ /****** FREE lmem ******/
return code;
}
} else {
/* Share global and local VM. */
code = context_create(psched, &pctx, &dmem, &pcur->state, false);
if (code < 0) {
-/****** FREE lmem ******/
+ /****** FREE lmem ******/
return code;
}
/*
@@ -624,8 +626,8 @@ private int
fork_done(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
- gs_scheduler_t *psched = the_gs_scheduler;
- gs_context *pcur = psched->current;
+ gs_context *pcur = (gs_context *)i_ctx_p;
+ gs_scheduler_t *psched = pcur->scheduler;
if_debug2('\'', "[']done %ld%s\n", pcur->index,
(pcur->detach ? ", detached" : ""));
@@ -643,7 +645,7 @@ fork_done(i_ctx_t *i_ctx_p)
* until there aren't. An invalidrestore is possible and will
* result in an error termination.
*/
- if (gs_imemory.save_level) {
+ if (iimemory_local->save_level) {
ref *prestore;
if (dict_find_string(systemdict, "restore", &prestore) <= 0) {
@@ -699,7 +701,8 @@ private int
zjoin(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
- gs_scheduler_t *psched = the_gs_scheduler;
+ gs_context *current = (gs_context *)i_ctx_p;
+ gs_scheduler_t *psched = current->scheduler;
gs_context *pctx;
int code;
@@ -712,12 +715,12 @@ zjoin(i_ctx_t *i_ctx_p)
* the context being joined must share both global and local VM with
* the current context.
*/
- if (pctx->joiner != 0 || pctx->detach || pctx == psched->current ||
+ if (pctx->joiner != 0 || pctx->detach || pctx == current ||
pctx->state.memory.space_global !=
- psched->current->state.memory.space_global ||
+ current->state.memory.space_global ||
pctx->state.memory.space_local !=
- psched->current->state.memory.space_local ||
- gs_imemory.save_level != 0
+ current->state.memory.space_local ||
+ iimemory_local->save_level != 0
)
return_error(e_invalidcontext);
switch (pctx->status) {
@@ -731,7 +734,7 @@ zjoin(i_ctx_t *i_ctx_p)
check_estack(2);
push_op_estack(finish_join);
push_op_estack(reschedule_now);
- pctx->joiner = psched->current;
+ pctx->joiner = current;
return o_push_estack;
case cs_done:
{
@@ -757,7 +760,8 @@ private int
finish_join(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
- gs_scheduler_t *psched = the_gs_scheduler;
+ gs_context *current = (gs_context *)i_ctx_p;
+ gs_scheduler_t *psched = current->scheduler;
gs_context *pctx;
int code;
@@ -765,7 +769,7 @@ finish_join(i_ctx_t *i_ctx_p)
return code;
if_debug2('\'', "[']finish_join %ld, status = %d\n",
pctx->index, pctx->status);
- if (pctx->joiner != psched->current)
+ if (pctx->joiner != current)
return_error(e_invalidcontext);
pctx->joiner = 0;
return zjoin(i_ctx_p);
@@ -782,12 +786,13 @@ reschedule_now(i_ctx_t *i_ctx_p)
private int
zyield(i_ctx_t *i_ctx_p)
{
- gs_scheduler_t *psched = the_gs_scheduler;
+ gs_context *current = (gs_context *)i_ctx_p;
+ gs_scheduler_t *psched = current->scheduler;
if (psched->active.head == 0)
return 0;
if_debug0('"', "[\"]yield\n");
- add_last(&psched->active, psched->current);
+ add_last(&psched->active, current);
return o_reschedule;
}
@@ -806,7 +811,7 @@ zcondition(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
gs_condition *pcond =
- ialloc_struct(gs_condition, &st_condition, "zcondition");
+ ialloc_struct(gs_condition, &st_condition, "zcondition");
if (pcond == 0)
return_error(e_VMerror);
@@ -836,6 +841,7 @@ zlock(i_ctx_t *i_ctx_p)
private int
zmonitor(i_ctx_t *i_ctx_p)
{
+ gs_context *current = (gs_context *)i_ctx_p;
os_ptr op = osp;
gs_lock *plock;
gs_context *pctx;
@@ -847,12 +853,10 @@ zmonitor(i_ctx_t *i_ctx_p)
pctx = plock->holder;
if_debug1('\'', "[']monitor 0x%lx\n", (ulong) plock);
if (pctx != 0) {
- gs_scheduler_t *psched = pctx->scheduler;
-
- if (pctx == psched->current ||
- (gs_imemory.save_level != 0 &&
+ if (pctx == current ||
+ (iimemory_local->save_level != 0 &&
pctx->state.memory.space_local ==
- psched->current->state.memory.space_local)
+ current->state.memory.space_local)
)
return_error(e_invalidcontext);
}
@@ -865,7 +869,7 @@ zmonitor(i_ctx_t *i_ctx_p)
* The procedure to execute
*/
check_estack(4);
- code = lock_acquire(op - 1, the_gs_scheduler->current);
+ code = lock_acquire(op - 1, current);
if (code != 0) { /* We didn't acquire the lock. Re-execute this later. */
push_op_estack(zmonitor);
return code; /* o_reschedule */
@@ -929,7 +933,7 @@ zwait(i_ctx_t *i_ctx_p)
(ulong) plock, (ulong) pcond);
pctx = plock->holder;
if (pctx == 0 || pctx != pctx->scheduler->current ||
- (gs_imemory.save_level != 0 &&
+ (iimemory_local->save_level != 0 &&
(r_space(op - 1) == avm_local || r_space(op) == avm_local))
)
return_error(e_invalidcontext);
@@ -943,8 +947,9 @@ zwait(i_ctx_t *i_ctx_p)
private int
await_lock(i_ctx_t *i_ctx_p)
{
+ gs_context *current = (gs_context *)i_ctx_p;
os_ptr op = osp;
- int code = lock_acquire(op - 1, the_gs_scheduler->current);
+ int code = lock_acquire(op - 1, current);
if (code == 0) {
pop(2);
@@ -977,20 +982,21 @@ activate_waiting(ctx_list * pcl)
private int
zusertime_context(i_ctx_t *i_ctx_p)
{
+ gs_context *current = (gs_context *)i_ctx_p;
+ gs_scheduler_t *psched = current->scheduler;
os_ptr op = osp;
long utime = context_usertime();
- gs_scheduler_t *psched = the_gs_scheduler;
push(1);
- if (!psched->current->state.keep_usertime) {
+ if (!current->state.keep_usertime) {
/*
* This is the first time this context has executed usertime:
* we must track its execution time from now on.
*/
psched->usertime_initial = utime;
- psched->current->state.keep_usertime = true;
+ current->state.keep_usertime = true;
}
- make_int(op, psched->current->state.usertime_total + utime -
+ make_int(op, current->state.usertime_total + utime -
psched->usertime_initial);
return 0;
}
@@ -1018,12 +1024,11 @@ context_create(gs_scheduler_t * psched, gs_context ** ppctx,
} else {
gs_context_state_t *pctx_st = &pctx->state;
- code = context_state_alloc(&pctx_st, dmem);
+ code = context_state_alloc(&pctx_st, systemdict, dmem);
if (code < 0) {
gs_free_object((gs_memory_t *) mem, pctx, "context_create");
return code;
}
- pctx_st->dict_stack.system_dict = *systemdict;
}
ctx_index = gs_next_ids(1);
pctx->scheduler = psched;
diff --git a/gs/src/zcontrol.c b/gs/src/zcontrol.c
index 750e98080..9d81a5e00 100644
--- a/gs/src/zcontrol.c
+++ b/gs/src/zcontrol.c
@@ -28,9 +28,6 @@
#include "iutil.h"
#include "store.h"
-/* Make an invalid file object. */
-extern void make_invalid_file(P1(ref *)); /* in zfile.c */
-
/* Forward references */
private int no_cleanup(P1(i_ctx_t *));
private uint count_exec_stack(P2(i_ctx_t *, bool));
@@ -119,7 +116,7 @@ zexec(i_ctx_t *i_ctx_p)
}
/* <obj1> ... <objn> <n> .execn - */
-int
+private int
zexecn(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
diff --git a/gs/src/zcrd.c b/gs/src/zcrd.c
index 064e99354..5737b9325 100644
--- a/gs/src/zcrd.c
+++ b/gs/src/zcrd.c
@@ -98,7 +98,7 @@ zbuilddevicecolorrendering1(i_ctx_t *i_ctx_p)
int code;
check_type(*op, t_dictionary);
- code = dict_param_list_read(&list, op, NULL, false);
+ code = dict_param_list_read(&list, op, NULL, false, iimemory);
if (code < 0)
return code;
code = gs_cie_render1_build(&pcrd, mem, ".builddevicecolorrendering1");
diff --git a/gs/src/zdevice.c b/gs/src/zdevice.c
index 2ac3846d1..1c55fa98c 100644
--- a/gs/src/zdevice.c
+++ b/gs/src/zdevice.c
@@ -67,7 +67,7 @@ zcurrentdevice(i_ctx_t *i_ctx_p)
}
/* <device> .devicename <string> */
-int
+private int
zdevicename(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
@@ -219,7 +219,7 @@ zget_device_params(i_ctx_t *i_ctx_p, bool is_hardware)
rkeys = *op;
dev = op[-1].value.pdevice;
pop(1);
- stack_param_list_write(&list, &o_stack, &rkeys);
+ stack_param_list_write(&list, &o_stack, &rkeys, iimemory);
code = gs_get_device_or_hardware_params(dev, (gs_param_list *) & list,
is_hardware);
if (code < 0) {
@@ -361,7 +361,7 @@ zputdeviceparams(i_ctx_t *i_ctx_p)
check_write_type_only(*pdev, t_device);
dev = pdev->value.pdevice;
code = stack_param_list_read(&list, &o_stack, 0, ppolicy,
- prequire_all->value.boolval);
+ prequire_all->value.boolval, iimemory);
if (code < 0)
return code;
old_width = dev->width;
diff --git a/gs/src/zdevice2.c b/gs/src/zdevice2.c
index ab0182923..fbae5e8f7 100644
--- a/gs/src/zdevice2.c
+++ b/gs/src/zdevice2.c
@@ -28,6 +28,7 @@
#include "idparam.h"
#include "igstate.h"
#include "iname.h"
+#include "iutil.h"
#include "store.h"
#include "gxdevice.h"
#include "gsstate.h"
@@ -264,17 +265,13 @@ restore_page_device(const gs_state * pgs_old, const gs_state * pgs_new)
if (dev_t1 != dev_t2)
return true;
}
- /* The current implementation of setpagedevice just sets new */
- /* parameters in the same device object, so we have to check */
- /* whether the page device dictionaries are the same. */
- {
- const ref *ppd1 = &gs_int_gstate(pgs_old)->pagedevice;
- const ref *ppd2 = &gs_int_gstate(pgs_new)->pagedevice;
-
- return (r_type(ppd1) != r_type(ppd2) ||
- (r_has_type(ppd1, t_dictionary) &&
- ppd1->value.pdict != ppd2->value.pdict));
- }
+ /*
+ * The current implementation of setpagedevice just sets new
+ * parameters in the same device object, so we have to check
+ * whether the page device dictionaries are the same.
+ */
+ return !obj_eq(&gs_int_gstate(pgs_old)->pagedevice,
+ &gs_int_gstate(pgs_new)->pagedevice);
}
/* - grestore - */
diff --git a/gs/src/zdict.c b/gs/src/zdict.c
index 0095b95d1..a6dbac2e5 100644
--- a/gs/src/zdict.c
+++ b/gs/src/zdict.c
@@ -320,7 +320,8 @@ zdictstack(i_ctx_t *i_ctx_p)
check_write_type(*op, t_array);
if (!level2_enabled)
count--; /* see dstack.h */
- return ref_stack_store(&d_stack, op, count, 0, 0, true, "dictstack");
+ return ref_stack_store(&d_stack, op, count, 0, 0, true, idmemory,
+ "dictstack");
}
/* - cleardictstack - */
@@ -408,7 +409,7 @@ zforceput(i_ctx_t *i_ctx_p)
check_type(*odp, t_dictionary);
if (odp->value.pdict == systemdict->value.pdict ||
- !ialloc_is_in_save()
+ !imemory_save_level(iimemory)
) {
uint space = r_space(odp);
diff --git a/gs/src/zdpnext.c b/gs/src/zdpnext.c
index 5c1ced905..93b79a1ce 100644
--- a/gs/src/zdpnext.c
+++ b/gs/src/zdpnext.c
@@ -34,6 +34,7 @@
#include "ialloc.h"
#include "igstate.h"
#include "iimage.h"
+#include "iimage2.h"
#include "store.h"
/* ------ alpha channel ------ */
@@ -79,9 +80,6 @@ zsetalpha(i_ctx_t *i_ctx_p)
/* Imported procedures */
int zimage_multiple(P2(i_ctx_t *i_ctx_p, bool has_alpha)); /* in zcolor1.c */
-int process_non_source_image(P3(i_ctx_t *i_ctx_p,
- const gs_image_common_t * pim,
- client_name_t cname)); /* in zdps.c */
/*
* Define the operand and bookeeping structure for a compositing operation.
diff --git a/gs/src/zdps.c b/gs/src/zdps.c
index c8f3d129a..12d000694 100644
--- a/gs/src/zdps.c
+++ b/gs/src/zdps.c
@@ -30,11 +30,12 @@
#include "iddict.h"
#include "idparam.h"
#include "igstate.h"
+#include "iimage2.h"
#include "iname.h"
#include "store.h"
/* Import the procedure for constructing user paths. */
-extern int make_upath(P4(ref *, const gs_state *, gx_path *, bool));
+extern int make_upath(P5(i_ctx_t *, ref *, const gs_state *, gx_path *, bool));
/* ------ Graphics state ------ */
@@ -88,20 +89,6 @@ zcurrentscreenphase(i_ctx_t *i_ctx_p)
/* ------ Device-source images ------ */
-/* Process an image that has no explicit source data. */
-/* We export this for composite images. */
-int
-process_non_source_image(i_ctx_t *i_ctx_p, const gs_image_common_t * pic,
- client_name_t cname)
-{
- gx_image_enum_common_t *pie;
- int code = gs_image_begin_typed(pic, igs, false /****** WRONG ******/ ,
- &pie);
-
- /* We didn't pass any data, so there's nothing to clean up. */
- return code;
-}
-
/* <dict> .image2 - */
private int
zimage2(i_ctx_t *i_ctx_p)
@@ -158,7 +145,8 @@ zimage2(i_ctx_t *i_ctx_p)
if (gx_path_is_null(image.UnpaintedPath))
make_null(&rupath);
else
- code = make_upath(&rupath, igs, image.UnpaintedPath, false);
+ code = make_upath(i_ctx_p, &rupath, igs, image.UnpaintedPath,
+ false);
gx_path_free(image.UnpaintedPath, ".image2 UnpaintedPath");
if (code < 0)
return code;
@@ -250,7 +238,7 @@ zdefineusername(i_ctx_t *i_ctx_p)
return code;
}
refcpy_to_new(new_array.value.refs, user_names_p->value.refs,
- old_size);
+ old_size, idmemory);
refset_null(new_array.value.refs + old_size,
new_size - old_size);
ifree_ref_array(user_names_p, "defineusername(old)");
diff --git a/gs/src/zdps1.c b/gs/src/zdps1.c
index 6985749ec..66254af71 100644
--- a/gs/src/zdps1.c
+++ b/gs/src/zdps1.c
@@ -32,7 +32,7 @@
#include "ibnum.h"
/* Forward references */
-private int gstate_unshare(P1(os_ptr));
+private int gstate_unshare(P1(i_ctx_t *));
/* Structure descriptors */
public_st_igstate_obj();
@@ -143,7 +143,7 @@ zcopy_gstate(i_ctx_t *i_ctx_p)
check_stype(*op, st_igstate_obj);
check_stype(*op1, st_igstate_obj);
check_write(*op);
- code = gstate_unshare(op);
+ code = gstate_unshare(i_ctx_p);
if (code < 0)
return code;
pgs = igstate_ptr(op);
@@ -178,7 +178,7 @@ zcurrentgstate(i_ctx_t *i_ctx_p)
check_stype(*op, st_igstate_obj);
check_write(*op);
- code = gstate_unshare(op);
+ code = gstate_unshare(i_ctx_p);
if (code < 0)
return code;
pgs = igstate_ptr(op);
@@ -228,8 +228,8 @@ typedef struct local_rects_s {
} local_rects_t;
/* Forward references */
-private int rect_get(P2(local_rects_t *, os_ptr));
-private void rect_release(P1(local_rects_t *));
+private int rect_get(P3(local_rects_t *, os_ptr, gs_memory_t *));
+private void rect_release(P2(local_rects_t *, gs_memory_t *));
/* <x> <y> <width> <height> .rectappend - */
/* <numarray|numstring> .rectappend - */
@@ -238,13 +238,13 @@ zrectappend(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
local_rects_t lr;
- int npop = rect_get(&lr, op);
+ int npop = rect_get(&lr, op, imemory);
int code;
if (npop < 0)
return npop;
code = gs_rectappend(igs, lr.pr, lr.count);
- rect_release(&lr);
+ rect_release(&lr, imemory);
if (code < 0)
return code;
pop(npop);
@@ -258,13 +258,13 @@ zrectclip(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
local_rects_t lr;
- int npop = rect_get(&lr, op);
+ int npop = rect_get(&lr, op, imemory);
int code;
if (npop < 0)
return npop;
code = gs_rectclip(igs, lr.pr, lr.count);
- rect_release(&lr);
+ rect_release(&lr, imemory);
if (code < 0)
return code;
pop(npop);
@@ -278,13 +278,13 @@ zrectfill(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
local_rects_t lr;
- int npop = rect_get(&lr, op);
+ int npop = rect_get(&lr, op, imemory);
int code;
if (npop < 0)
return npop;
code = gs_rectfill(igs, lr.pr, lr.count);
- rect_release(&lr);
+ rect_release(&lr, imemory);
if (code < 0)
return code;
pop(npop);
@@ -303,19 +303,19 @@ zrectstroke(i_ctx_t *i_ctx_p)
if (read_matrix(op, &mat) >= 0) {
/* Concatenate the matrix to the CTM just before stroking the path. */
- npop = rect_get(&lr, op - 1);
+ npop = rect_get(&lr, op - 1, imemory);
if (npop < 0)
return npop;
code = gs_rectstroke(igs, lr.pr, lr.count, &mat);
npop++;
} else {
/* No matrix. */
- npop = rect_get(&lr, op);
+ npop = rect_get(&lr, op, imemory);
if (npop < 0)
return npop;
code = gs_rectstroke(igs, lr.pr, lr.count, (gs_matrix *) 0);
}
- rect_release(&lr);
+ rect_release(&lr, imemory);
if (code < 0)
return code;
pop(npop);
@@ -327,7 +327,7 @@ zrectstroke(i_ctx_t *i_ctx_p)
/* Get rectangles from the stack. */
/* Return the number of elements to pop (>0) if OK, <0 if error. */
private int
-rect_get(local_rects_t * plr, os_ptr op)
+rect_get(local_rects_t * plr, os_ptr op, gs_memory_t *mem)
{
int format, code;
uint n, count;
@@ -362,8 +362,8 @@ rect_get(local_rects_t * plr, os_ptr op)
if (count <= MAX_LOCAL_RECTS)
pr = plr->rl;
else {
- pr = (gs_rect *) ialloc_byte_array(count, sizeof(gs_rect),
- "rect_get");
+ pr = (gs_rect *)gs_alloc_byte_array(mem, count, sizeof(gs_rect),
+ "rect_get");
if (pr == 0)
return_error(e_VMerror);
}
@@ -394,10 +394,10 @@ rect_get(local_rects_t * plr, os_ptr op)
/* Release the rectangle list if needed. */
private void
-rect_release(local_rects_t * plr)
+rect_release(local_rects_t * plr, gs_memory_t *mem)
{
if (plr->pr != plr->rl)
- ifree_object(plr->pr, "rect_release");
+ gs_free_object(mem, plr->pr, "rect_release");
}
/* ------ Graphics state ------ */
@@ -447,8 +447,9 @@ const op_def zdps1_l2_op_defs[] =
/* Ensure that a gstate is not shared with an outer save level. */
/* *op is of type t_astruct(igstate_obj). */
private int
-gstate_unshare(os_ptr op)
+gstate_unshare(i_ctx_t *i_ctx_p)
{
+ os_ptr op = osp;
ref *pgsref = &r_ptr(op, igstate_obj)->gstate;
gs_state *pgs = r_ptr(pgsref, gs_state);
gs_state *pnew;
diff --git a/gs/src/zfcmap.c b/gs/src/zfcmap.c
index 7429d6410..63f450b02 100644
--- a/gs/src/zfcmap.c
+++ b/gs/src/zfcmap.c
@@ -301,7 +301,8 @@ cid_system_info_compatible(const gs_cid_system_info * psi1,
/* Get the CodeMap from a Type 0 font, and check the CIDSystemInfo of */
/* its subsidiary fonts. */
int
-ztype0_get_cmap(const gs_cmap **ppcmap, const ref *pfdepvector, const ref *op)
+ztype0_get_cmap(const gs_cmap **ppcmap, const ref *pfdepvector, const ref *op,
+ gs_memory_t *imem)
{
ref *prcmap;
ref *pcodemap;
@@ -313,7 +314,7 @@ ztype0_get_cmap(const gs_cmap **ppcmap, const ref *pfdepvector, const ref *op)
if (dict_find_string(op, "CMap", &prcmap) <= 0 ||
!r_has_type(prcmap, t_dictionary) ||
dict_find_string(prcmap, "CodeMap", &pcodemap) <= 0 ||
- !r_has_stype(pcodemap, imemory, st_cmap)
+ !r_has_stype(pcodemap, imem, st_cmap)
)
return_error(e_invalidfont);
pcmap = r_ptr(pcodemap, gs_cmap);
diff --git a/gs/src/zfdctd.c b/gs/src/zfdctd.c
index 1045d9b41..5ee75e8eb 100644
--- a/gs/src/zfdctd.c
+++ b/gs/src/zfdctd.c
@@ -67,7 +67,7 @@ zDCTD(i_ctx_t *i_ctx_p)
npop = 1, dop = op, dspace = r_space(op);
else
npop = 0, dop = 0, dspace = 0;
- if ((code = dict_param_list_read(&list, dop, NULL, false)) < 0)
+ if ((code = dict_param_list_read(&list, dop, NULL, false, iimemory)) < 0)
goto fail;
if ((code = s_DCTD_put_params((gs_param_list *) & list, &state)) < 0)
goto rel;
diff --git a/gs/src/zfdcte.c b/gs/src/zfdcte.c
index e7398c7a5..824617526 100644
--- a/gs/src/zfdcte.c
+++ b/gs/src/zfdcte.c
@@ -72,7 +72,7 @@ zDCTE(i_ctx_t *i_ctx_p)
npop = 1, dop = op, dspace = r_space(op);
else
npop = 0, dop = 0, dspace = 0;
- if ((code = dict_param_list_read(&list, dop, NULL, false)) < 0)
+ if ((code = dict_param_list_read(&list, dop, NULL, false, iimemory)) < 0)
goto fail;
if ((code = s_DCTE_put_params((gs_param_list *) & list, &state)) < 0)
goto rel;
@@ -120,7 +120,7 @@ zdcteparams(i_ctx_t *i_ctx_p)
/* The DCT filters copy the template.... */
if (s->state->template->process != s_DCTE_template.process)
return_error(e_rangecheck);
- code = dict_param_list_write(&list, op - 2, NULL);
+ code = dict_param_list_write(&list, op - 2, NULL, iimemory);
if (code < 0)
return code;
code = s_DCTE_get_params((gs_param_list *) & list,
diff --git a/gs/src/zfdecode.c b/gs/src/zfdecode.c
index a5c1dfde3..90d01382f 100644
--- a/gs/src/zfdecode.c
+++ b/gs/src/zfdecode.c
@@ -39,6 +39,8 @@
#include "spdiffx.h"
#include "spngpx.h"
#include "ifilter.h"
+#include "ifilter2.h"
+#include "ifrpred.h"
/* ------ ASCII85 filters ------ */
@@ -66,15 +68,15 @@ zA85D(i_ctx_t *i_ctx_p)
/* Common setup for encoding and decoding filters. */
extern stream_state_proc_put_params(s_CF_put_params, stream_CF_state);
int
-zcf_setup(os_ptr op, stream_CF_state * pcfs)
+zcf_setup(os_ptr op, stream_CF_state *pcfs, gs_ref_memory_t *imem)
{
dict_param_list list;
- int code = dict_param_list_read(&list, op, NULL, false);
+ int code = dict_param_list_read(&list, op, NULL, false, imem);
if (code < 0)
return code;
s_CF_set_defaults_inline(pcfs);
- code = s_CF_put_params((gs_param_list *) & list, pcfs);
+ code = s_CF_put_params((gs_param_list *)&list, pcfs);
iparam_list_release(&list);
return code;
}
@@ -94,18 +96,14 @@ zCFD(i_ctx_t *i_ctx_p)
dop = op;
} else
dop = 0;
- code = zcf_setup(dop, (stream_CF_state *) & cfs);
+ code = zcf_setup(dop, (stream_CF_state *)&cfs, iimemory);
if (code < 0)
return code;
- return filter_read(i_ctx_p, 0, &s_CFD_template, (stream_state *) & cfs, 0);
+ return filter_read(i_ctx_p, 0, &s_CFD_template, (stream_state *)&cfs, 0);
}
/* ------ Common setup for possibly pixel-oriented decoding filters ------ */
-/* Forward declarations */
-int zpd_setup(P2(os_ptr op, stream_PDiff_state * ppds));
-int zpp_setup(P2(os_ptr op, stream_PNGP_state * ppps));
-
int
filter_read_predictor(i_ctx_t *i_ctx_p, int npop,
const stream_template * template, stream_state * st)
diff --git a/gs/src/zfile.c b/gs/src/zfile.c
index 414694bd5..af38d19ef 100644
--- a/gs/src/zfile.c
+++ b/gs/src/zfile.c
@@ -23,6 +23,7 @@
#include "ghost.h"
#include "gscdefs.h" /* for gx_io_device_table */
#include "gp.h"
+#include "gsfname.h"
#include "gsstruct.h" /* for registering root */
#include "gxalloc.h" /* for streams */
#include "oper.h"
@@ -36,25 +37,25 @@
#include "strimpl.h"
#include "sfilter.h"
#include "gxiodev.h" /* must come after stream.h */
- /* and before files.h */
-#include "files.h" /* ditto */
-#include "fname.h" /* ditto */
+ /* and before files.h */
+#include "files.h"
#include "main.h" /* for gs_lib_paths */
#include "store.h"
-/* Import the file_open routine for %os%, which is the default. */
-extern iodev_proc_open_file(iodev_os_open_file);
-
/* Import the IODevice table. */
extern_gx_io_device_table();
/* Import the dtype of the stdio IODevices. */
extern const char iodev_dtype_stdio[];
-/* Forward references: file opening. */
-int file_open(P6(const byte *, uint, const char *, uint, ref *, stream **));
+/* Forward references: file name parsing. */
+private int parse_file_name(P2(const ref * op, gs_parsed_file_name_t * pfn));
+private int parse_real_file_name(P4(const ref * op,
+ gs_parsed_file_name_t * pfn,
+ gs_memory_t *mem, client_name_t cname));
/* Forward references: other. */
+private iodev_proc_open_file(iodev_os_open_file);
private int execfile_finish(P1(i_ctx_t *));
private int execfile_cleanup(P1(i_ctx_t *));
@@ -129,12 +130,12 @@ make_invalid_file(ref * fp)
}
/* <name_string> <access_string> file <file> */
-int
+private int
zfile(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
char file_access[3];
- parsed_file_name pname;
+ gs_parsed_file_name_t pname;
const byte *astr;
int code;
stream *s;
@@ -208,13 +209,13 @@ private int
zdeletefile(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
- parsed_file_name pname;
- int code = parse_real_file_name(op, &pname, "deletefile");
+ gs_parsed_file_name_t pname;
+ int code = parse_real_file_name(op, &pname, imemory, "deletefile");
if (code < 0)
return code;
code = (*pname.iodev->procs.delete_file)(pname.iodev, pname.fname);
- free_file_name(&pname, "deletefile");
+ gs_free_file_name(&pname, "deletefile");
if (code < 0)
return code;
pop(1);
@@ -289,13 +290,14 @@ private int
zrenamefile(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
- parsed_file_name pname1, pname2;
- int code = parse_real_file_name(op - 1, &pname1, "renamefile(from)");
+ gs_parsed_file_name_t pname1, pname2;
+ int code = parse_real_file_name(op - 1, &pname1, imemory,
+ "renamefile(from)");
if (code < 0)
return code;
pname2.fname = 0;
- code = parse_real_file_name(op, &pname2, "renamefile(to)");
+ code = parse_real_file_name(op, &pname2, imemory, "renamefile(to)");
if (code < 0 || pname1.iodev != pname2.iodev ||
(code = (*pname1.iodev->procs.rename_file)(pname1.iodev,
pname1.fname, pname2.fname)) < 0
@@ -303,8 +305,8 @@ zrenamefile(i_ctx_t *i_ctx_p)
if (code >= 0)
code = gs_note_error(e_invalidfileaccess);
}
- free_file_name(&pname2, "renamefile(to)");
- free_file_name(&pname1, "renamefile(from)");
+ gs_free_file_name(&pname2, "renamefile(to)");
+ gs_free_file_name(&pname1, "renamefile(from)");
if (code < 0)
return code;
pop(2);
@@ -329,13 +331,13 @@ zstatus(i_ctx_t *i_ctx_p)
return 0;
case t_string:
{
- parsed_file_name pname;
+ gs_parsed_file_name_t pname;
struct stat fstat;
int code = parse_file_name(op, &pname);
if (code < 0)
return code;
- code = terminate_file_name(&pname, "status");
+ code = gs_terminate_file_name(&pname, imemory, "status");
if (code < 0)
return code;
code = (*pname.iodev->procs.file_status)(pname.iodev,
@@ -373,7 +375,7 @@ zstatus(i_ctx_t *i_ctx_p)
make_bool(op, 0);
code = 0;
}
- free_file_name(&pname, "status");
+ gs_free_file_name(&pname, "status");
return code;
}
default:
@@ -415,7 +417,7 @@ execfile_cleanup(i_ctx_t *i_ctx_p)
}
/* <dir> <name> .filenamedirseparator <string> */
-int
+private int
zfilenamedirseparator(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
@@ -435,7 +437,7 @@ zfilenamedirseparator(i_ctx_t *i_ctx_p)
}
/* - .filenamelistseparator <string> */
-int
+private int
zfilenamelistseparator(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
@@ -447,7 +449,7 @@ zfilenamelistseparator(i_ctx_t *i_ctx_p)
}
/* <name> .filenamesplit <dir> <base> <extension> */
-int
+private int
zfilenamesplit(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
@@ -459,7 +461,7 @@ zfilenamesplit(i_ctx_t *i_ctx_p)
/* <string> findlibfile <found_string> <file> true */
/* <string> findlibfile <string> false */
-int
+private int
zfindlibfile(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
@@ -467,7 +469,7 @@ zfindlibfile(i_ctx_t *i_ctx_p)
#define MAX_CNAME 200
byte cname[MAX_CNAME];
uint clen;
- parsed_file_name pname;
+ gs_parsed_file_name_t pname;
stream *s;
check_ostack(2);
@@ -494,7 +496,7 @@ zfindlibfile(i_ctx_t *i_ctx_p)
byte *cstr;
code = lib_file_open(pname.fname, pname.len, cname, MAX_CNAME,
- &clen, op + 1);
+ &clen, op + 1, imemory);
if (code == e_VMerror)
return code;
if (code < 0) {
@@ -533,8 +535,44 @@ const op_def zfile_op_defs[] =
op_def_end(zfile_init)
};
+/* ------ File name parsing ------ */
+
+/* Parse a file name into device and individual name. */
+/* See gsfname.c for details. */
+private int
+parse_file_name(const ref * op, gs_parsed_file_name_t * pfn)
+{
+ check_read_type(*op, t_string);
+ return gs_parse_file_name(pfn, (const char *)op->value.const_bytes,
+ r_size(op));
+}
+
+/* Parse a real (non-device) file name and convert to a C string. */
+/* See gsfname.c for details. */
+private int
+parse_real_file_name(const ref *op, gs_parsed_file_name_t *pfn,
+ gs_memory_t *mem, client_name_t cname)
+{
+ check_read_type(*op, t_string);
+ return gs_parse_real_file_name(pfn, (const char *)op->value.const_bytes,
+ r_size(op), mem, cname);
+}
+
/* ------ Stream opening ------ */
+/*
+ * Define the file_open procedure for the %os% IODevice (also used, as the
+ * default, for %pipe% and possibly others).
+ */
+private int
+iodev_os_open_file(gx_io_device * iodev, const char *fname, uint len,
+ const char *file_access, stream ** ps, gs_memory_t * mem)
+{
+ return file_open_stream(fname, len, file_access,
+ file_default_buffer_size, ps,
+ iodev->procs.fopen, mem);
+}
+
/* Make a t_file reference to a stream. */
void
make_stream_file(ref * pfile, stream * s, const char *access)
@@ -625,11 +663,11 @@ lib_fopen(const char *bname)
/* The startup code calls this to open the initialization file gs_init.ps. */
int
lib_file_open(const char *fname, uint len, byte * cname, uint max_clen,
- uint * pclen, ref * pfile)
+ uint * pclen, ref * pfile, gs_memory_t *mem)
{
stream *s;
- int code = file_open_stream(fname, len, "r",
- file_default_buffer_size, &s, lib_file_fopen);
+ int code = file_open_stream(fname, len, "r", file_default_buffer_size,
+ &s, lib_file_fopen, mem);
char *bname;
uint blen;
@@ -652,18 +690,16 @@ lib_file_open(const char *fname, uint len, byte * cname, uint max_clen,
/* (This is currently used only by the ccinit feature.) */
/* The string must be allocated in non-garbage-collectable (foreign) space. */
int
-file_read_string(const byte * str, uint len, ref * pfile)
+file_read_string(const byte *str, uint len, ref *pfile, gs_ref_memory_t *imem)
{
- stream *s = file_alloc_stream(imemory, "file_read_string");
- int space;
+ stream *s = file_alloc_stream((gs_memory_t *)imem, "file_read_string");
if (s == 0)
return_error(e_VMerror);
- space = icurrent_space;
sread_string(s, str, len);
s->foreign = 1;
s->write_id = 0;
- make_file(pfile, a_readonly | space, s->read_id, s);
+ make_file(pfile, a_readonly | imemory_space(imem), s->read_id, s);
s->save_close = s->procs.close;
s->procs.close = file_close_disable;
return 0;
@@ -676,7 +712,8 @@ file_read_string(const byte * str, uint len, ref * pfile)
/* but don't open an OS file or initialize the stream. */
int
file_open_stream(const char *fname, uint len, const char *file_access,
- uint buffer_size, stream ** ps, iodev_proc_fopen_t fopen_proc)
+ uint buffer_size, stream ** ps, iodev_proc_fopen_t fopen_proc,
+ gs_memory_t *mem)
{
byte *buffer;
register stream *s;
@@ -687,11 +724,11 @@ file_open_stream(const char *fname, uint len, const char *file_access,
return_error(e_limitcheck);
/* Allocate the stream first, since it persists */
/* even after the file has been closed. */
- s = file_alloc_stream(imemory, "file_open_stream");
+ s = file_alloc_stream(mem, "file_open_stream");
if (s == 0)
return_error(e_VMerror);
/* Allocate the buffer. */
- buffer = ialloc_bytes(buffer_size, "file_open(buffer)");
+ buffer = gs_alloc_bytes(mem, buffer_size, "file_open_stream(buffer)");
if (buffer == 0)
return_error(e_VMerror);
if (fname != 0) {
@@ -710,7 +747,7 @@ file_open_stream(const char *fname, uint len, const char *file_access,
code = (*fopen_proc)(iodev_default, file_name, fmode, &file,
(char *)buffer, buffer_size);
if (code < 0) {
- ifree_object(buffer, "file_open(buffer)");
+ gs_free_object(mem, buffer, "file_open_stream(buffer)");
return code;
}
/* Set up the stream. */
@@ -758,7 +795,7 @@ filter_report_error(stream_state * st, const char *str)
int
filter_open(const char *file_access, uint buffer_size, ref * pfile,
const stream_procs * procs, const stream_template * template,
- const stream_state * st)
+ const stream_state * st, gs_memory_t *mem)
{
stream *s;
uint ssize = gs_struct_type_size(template->stype);
@@ -766,15 +803,14 @@ filter_open(const char *file_access, uint buffer_size, ref * pfile,
int code;
if (template->stype != &st_stream_state) {
- sst = s_alloc_state(imemory, template->stype,
- "filter_open(stream_state)");
+ sst = s_alloc_state(mem, template->stype, "filter_open(stream_state)");
if (sst == 0)
return_error(e_VMerror);
}
code = file_open_stream((char *)0, 0, file_access,
- buffer_size, &s, (iodev_proc_fopen_t) 0);
+ buffer_size, &s, (iodev_proc_fopen_t)0, mem);
if (code < 0) {
- ifree_object(sst, "filter_open(stream_state)");
+ gs_free_object(mem, sst, "filter_open(stream_state)");
return code;
}
s_std_init(s, s->cbuf, s->bsize, procs,
@@ -790,13 +826,13 @@ filter_open(const char *file_access, uint buffer_size, ref * pfile,
memcpy(sst, st, ssize);
s->state = sst;
sst->template = template;
- sst->memory = imemory;
+ sst->memory = mem;
sst->report_error = filter_report_error;
if (template->init != 0) {
code = (*template->init)(sst);
if (code < 0) {
- ifree_object(sst, "filter_open(stream_state)");
- ifree_object(s->cbuf, "filter_open(buffer)");
+ gs_free_object(mem, sst, "filter_open(stream_state)");
+ gs_free_object(mem, s->cbuf, "filter_open(buffer)");
return code;
}
}
@@ -815,21 +851,14 @@ file_alloc_stream(gs_memory_t * mem, client_name_t cname)
gs_ref_memory_t *imem = 0;
/*
- * HACK: Figure out whether this is a gs_ref_memory_t we know
- * about. Avoiding this hack would require rippling a change
+ * HACK: Figure out whether this is a gs_ref_memory_t.
+ * Avoiding this hack would require rippling a change
* from gs_memory_t to gs_ref_memory_t into the open_file and
* open_device procedures of gx_io_device, which in turn would
* impact other things we don't want to change.
*/
- {
- int i;
-
- for (i = 0; i < countof(gs_imemory.spaces_indexed); ++i)
- if (mem == (gs_memory_t *) gs_imemory.spaces_indexed[i]) {
- imem = (gs_ref_memory_t *) mem;
- break;
- }
- }
+ if (mem->procs.free_object == gs_ref_memory_procs.free_object)
+ imem = (gs_ref_memory_t *) mem;
if (imem) {
/* Look first for a free stream allocated at this level. */
diff --git a/gs/src/zfileio.c b/gs/src/zfileio.c
index 03b9eb3c0..60d2f7806 100644
--- a/gs/src/zfileio.c
+++ b/gs/src/zfileio.c
@@ -52,7 +52,7 @@ zclosefile(i_ctx_t *i_ctx_p)
if (file_is_valid(s, op)) { /* closing a closed file is a no-op */
int status = sclose(s);
- if (status != 0) {
+ if (status != 0 && status != EOFC) {
if (s_is_writing(s))
return handle_write_status(i_ctx_p, status, op, NULL,
zclosefile);
@@ -499,7 +499,7 @@ zflushfile(i_ctx_t *i_ctx_p)
return 0;
}
status = sflush(s);
- if (status == 0) {
+ if (status == 0 || status == EOFC) {
pop(1);
return 0;
}
@@ -632,7 +632,7 @@ zwritecvp_at(i_ctx_t *i_ctx_p, os_ptr op, uint start, bool first)
check_write_file(s, op - 2);
check_type(*op, t_integer);
code = obj_cvp(op - 1, str, sizeof(str), &len, (int)op->value.intval,
- start);
+ start, imemory);
if (code == e_rangecheck) {
code = obj_string_data(op - 1, &data, &len);
if (len < start)
diff --git a/gs/src/zfilter.c b/gs/src/zfilter.c
index e4f9a34e3..c1b414026 100644
--- a/gs/src/zfilter.c
+++ b/gs/src/zfilter.c
@@ -169,7 +169,7 @@ zSFD(i_ctx_t *i_ctx_p)
/* ------ Utilities ------ */
/* Forward references */
-private int filter_ensure_buf(P3(stream **, uint, bool));
+private int filter_ensure_buf(P4(stream **, uint, gs_ref_memory_t *, bool));
/* Set up an input filter. */
int
@@ -215,7 +215,7 @@ filter_read(i_ctx_t *i_ctx_p, int npop, const stream_template * template,
default:
check_proc(*sop);
ialloc_set_space(idmemory, max(space, r_space(sop)));
- code = sread_proc(sop, &sstrm);
+ code = sread_proc(sop, &sstrm, iimemory);
if (code < 0)
goto out;
sstrm->is_temp = 2;
@@ -223,7 +223,7 @@ filter_read(i_ctx_t *i_ctx_p, int npop, const stream_template * template,
code = filter_ensure_buf(&sstrm,
template->min_in_size +
sstrm->state->template->min_out_size,
- false);
+ iimemory, false);
if (code < 0)
goto out;
break;
@@ -231,7 +231,7 @@ filter_read(i_ctx_t *i_ctx_p, int npop, const stream_template * template,
if (min_size < 128)
min_size = file_default_buffer_size;
code = filter_open("r", min_size, (ref *) sop,
- &s_filter_read_procs, template, st);
+ &s_filter_read_procs, template, st, imemory);
if (code < 0)
goto out;
s = fptr(sop);
@@ -292,7 +292,7 @@ filter_write(i_ctx_t *i_ctx_p, int npop, const stream_template * template,
default:
check_proc(*sop);
ialloc_set_space(idmemory, max(space, r_space(sop)));
- code = swrite_proc(sop, &sstrm);
+ code = swrite_proc(sop, &sstrm, iimemory);
if (code < 0)
goto out;
sstrm->is_temp = 2;
@@ -300,7 +300,7 @@ filter_write(i_ctx_t *i_ctx_p, int npop, const stream_template * template,
code = filter_ensure_buf(&sstrm,
template->min_out_size +
sstrm->state->template->min_in_size,
- true);
+ iimemory, true);
if (code < 0)
goto out;
break;
@@ -308,7 +308,7 @@ filter_write(i_ctx_t *i_ctx_p, int npop, const stream_template * template,
if (min_size < 128)
min_size = file_default_buffer_size;
code = filter_open("w", min_size, (ref *) sop,
- &s_filter_write_procs, template, st);
+ &s_filter_write_procs, template, st, imemory);
if (code < 0)
goto out;
s = fptr(sop);
@@ -338,15 +338,15 @@ s_Null1D_process(stream_state * st, stream_cursor_read * pr,
*++(pw->ptr) = *++(pr->ptr);
return 1;
}
-private const stream_template s_Null1D_template =
-{
+private const stream_template s_Null1D_template = {
&st_stream_state, NULL, s_Null1D_process, 1, 1
};
/* Ensure a minimum buffer size for a filter. */
/* This may require creating an intermediate stream. */
private int
-filter_ensure_buf(stream ** ps, uint min_buf_size, bool writing)
+filter_ensure_buf(stream ** ps, uint min_buf_size, gs_ref_memory_t *imem,
+ bool writing)
{
stream *s = *ps;
uint min_size = min_buf_size + max_min_left;
@@ -361,7 +361,8 @@ filter_ensure_buf(stream ** ps, uint min_buf_size, bool writing)
/* This is a newly created procedure stream. */
/* Just allocate a buffer for it. */
uint len = max(min_size, 128);
- byte *buf = ialloc_bytes(len, "filter_ensure_buf");
+ byte *buf = gs_alloc_bytes((gs_memory_t *)imem, len,
+ "filter_ensure_buf");
if (buf == 0)
return_error(e_VMerror);
@@ -374,10 +375,10 @@ filter_ensure_buf(stream ** ps, uint min_buf_size, bool writing)
/* Allocate an intermediate stream. */
if (writing)
code = filter_open("w", min_size, &bsop, &s_filter_write_procs,
- &s_NullE_template, NULL);
+ &s_NullE_template, NULL, (gs_memory_t *)imem);
else
code = filter_open("r", min_size, &bsop, &s_filter_read_procs,
- &s_Null1D_template, NULL);
+ &s_Null1D_template, NULL, (gs_memory_t *)imem);
if (code < 0)
return code;
bs = fptr(&bsop);
@@ -398,8 +399,7 @@ filter_mark_temp(const ref * fop, int is_temp)
/* ------ Initialization procedure ------ */
-const op_def zfilter_op_defs[] =
-{
+const op_def zfilter_op_defs[] = {
/* We enter PSStringEncode and SubFileDecode (only) */
/* as separate operators. */
{"1.psstringencode", zPSSE},
diff --git a/gs/src/zfilter2.c b/gs/src/zfilter2.c
index cc5e17a10..f45e44b64 100644
--- a/gs/src/zfilter2.c
+++ b/gs/src/zfilter2.c
@@ -33,12 +33,8 @@
#include "spdiffx.h"
#include "spngpx.h"
#include "ifilter.h"
-
-/* Import setup code from zfdecode.c */
-int zcf_setup(P2(os_ptr op, stream_CF_state * pcfs));
-int zlz_setup(P2(os_ptr op, stream_LZW_state * plzs));
-int zpd_setup(P2(os_ptr op, stream_PDiff_state * ppds));
-int zpp_setup(P2(os_ptr op, stream_PNGP_state * ppps));
+#include "ifilter2.h"
+#include "ifwpred.h"
/* ------ CCITTFaxEncode filter ------ */
@@ -52,7 +48,7 @@ zCFE(i_ctx_t *i_ctx_p)
check_type(*op, t_dictionary);
check_dict_read(*op);
- code = zcf_setup(op, (stream_CF_state *)&cfs);
+ code = zcf_setup(op, (stream_CF_state *)&cfs, iimemory);
if (code < 0)
return code;
return filter_write(i_ctx_p, 0, &s_CFE_template, (stream_state *)&cfs, 0);
diff --git a/gs/src/zfont.c b/gs/src/zfont.c
index 701e5855f..2732b875d 100644
--- a/gs/src/zfont.c
+++ b/gs/src/zfont.c
@@ -23,7 +23,6 @@
#include "gsstruct.h" /* for registering root */
#include "gzstate.h" /* must precede gxdevice */
#include "gxdevice.h" /* must precede gxfont */
-#include "gschar.h"
#include "gxfont.h"
#include "gxfcache.h"
#include "bfont.h"
@@ -231,12 +230,14 @@ font_param(const ref * pfdict, gs_font ** ppfont)
/* Add the FID entry to a font dictionary. */
/* Note that i_ctx_p may be NULL. */
int
-add_FID(i_ctx_t *i_ctx_p, ref * fp /* t_dictionary */ , gs_font * pfont)
+add_FID(i_ctx_t *i_ctx_p, ref * fp /* t_dictionary */ , gs_font * pfont,
+ gs_ref_memory_t *imem)
{
ref fid;
- make_tav_new(&fid, t_fontID, a_readonly | icurrent_space,
- pstruct, (void *)pfont);
+ make_tav(&fid, t_fontID,
+ a_readonly | imemory_space(imem) | imemory_new_mask(imem),
+ pstruct, (void *)pfont);
return (i_ctx_p ? idict_put_string(fp, "FID", &fid) :
dict_put_string(fp, "FID", &fid, NULL));
}
@@ -318,6 +319,9 @@ zdefault_make_font(gs_font_dir * pdir, const gs_font * oldfont,
const gs_matrix * pmat, gs_font ** ppfont)
{
gs_font *newfont = *ppfont;
+ gs_memory_t *mem = newfont->memory;
+ /* HACK: we know this font was allocated by the interpreter. */
+ gs_ref_memory_t *imem = (gs_ref_memory_t *)mem;
ref *fp = pfont_dict(oldfont);
font_data *pdata;
ref newdict, newmat, scalemat;
@@ -327,20 +331,21 @@ zdefault_make_font(gs_font_dir * pdir, const gs_font * oldfont,
if (dlen < mlen)
dlen = mlen;
- if ((pdata = ialloc_struct(font_data, &st_font_data,
- "make_font(font_data)")) == 0
+ if ((pdata = gs_alloc_struct(mem, font_data, &st_font_data,
+ "make_font(font_data)")) == 0
)
return_error(e_VMerror);
/*
* This dictionary is newly created: it's safe to pass NULL as the
* dstack pointer to dict_copy and dict_put_string.
*/
- if ((code = dict_create(dlen, &newdict)) < 0 ||
+ if ((code = dict_alloc(imem, dlen, &newdict)) < 0 ||
(code = dict_copy(fp, &newdict, NULL)) < 0 ||
- (code = ialloc_ref_array(&newmat, a_all, 12, "make_font(matrices)")) < 0
+ (code = gs_alloc_ref_array(imem, &newmat, a_all, 12,
+ "make_font(matrices)")) < 0
)
return code;
- refset_null(newmat.value.refs, 12);
+ refset_null_new(newmat.value.refs, 12, imemory_new_mask(imem));
ref_assign(&scalemat, &newmat);
r_set_size(&scalemat, 6);
scalemat.value.refs += 6;
@@ -361,16 +366,16 @@ zdefault_make_font(gs_font_dir * pdir, const gs_font * oldfont,
gs_matrix_multiply(pmat, &prev_scale, &scale) >= 0)
)
scale = *pmat;
- write_matrix(&scalemat, &scale);
+ write_matrix_new(&scalemat, &scale, imem);
}
r_clear_attrs(&scalemat, a_write);
r_set_size(&newmat, 6);
- write_matrix(&newmat, &newfont->FontMatrix);
+ write_matrix_new(&newmat, &newfont->FontMatrix, imem);
r_clear_attrs(&newmat, a_write);
if ((code = dict_put_string(&newdict, "FontMatrix", &newmat, NULL)) < 0 ||
(code = dict_put_string(&newdict, "OrigFont", pfont_dict(oldfont->base), NULL)) < 0 ||
(code = dict_put_string(&newdict, "ScaleMatrix", &scalemat, NULL)) < 0 ||
- (code = add_FID(NULL, &newdict, newfont)) < 0
+ (code = add_FID(NULL, &newdict, newfont, imem)) < 0
)
return code;
newfont->client_data = pdata;
diff --git a/gs/src/zfont0.c b/gs/src/zfont0.c
index b6709c1c8..4f08a823a 100644
--- a/gs/src/zfont0.c
+++ b/gs/src/zfont0.c
@@ -32,7 +32,6 @@
#include "gxmatrix.h"
#include "gzstate.h" /* must precede gxdevice */
#include "gxdevice.h" /* must precede gxfont */
-#include "gschar.h"
#include "gxfcmap.h"
#include "gxfont.h"
#include "gxfont0.h"
@@ -44,15 +43,9 @@
#include "iname.h"
#include "store.h"
-/* Composite font procedures */
-extern font_proc_init_fstack(gs_type0_init_fstack);
-extern font_proc_define_font(gs_type0_define_font);
-extern font_proc_make_font(gs_type0_make_font);
-extern font_proc_next_glyph(gs_type0_next_glyph);
-
/* Imported from zfcmap.c */
-int ztype0_get_cmap(P3(const gs_cmap ** ppcmap, const ref * pfdepvector,
- const ref * op));
+int ztype0_get_cmap(P4(const gs_cmap ** ppcmap, const ref * pfdepvector,
+ const ref * op, gs_memory_t *imem));
/* Forward references */
private font_proc_define_font(ztype0_define_font);
@@ -151,7 +144,7 @@ zbuildfont0(i_ctx_t *i_ctx_p)
} break;
case fmap_CMap: /* need CMap */
code = ztype0_get_cmap(&data.CMap, (const ref *)&fdepvector,
- (const ref *)op);
+ (const ref *)op, imemory);
break;
default:
;
@@ -186,10 +179,9 @@ zbuildfont0(i_ctx_t *i_ctx_p)
return code;
/* Fill in the rest of the basic font data. */
pfont->procs.init_fstack = gs_type0_init_fstack;
- pfont->procs.next_char = 0; /* superseded by next_glyph */
pfont->procs.define_font = ztype0_define_font;
pfont->procs.make_font = ztype0_make_font;
- pfont->procs.next_glyph = gs_type0_next_glyph;
+ pfont->procs.next_char_glyph = gs_type0_next_char_glyph;
if (dict_find_string(op, "PrefEnc", &pprefenc) <= 0) {
ref nul;
@@ -263,20 +255,24 @@ fail:
private int
ztype0_adjust_FDepVector(gs_font_type0 * pfont)
{
+ gs_memory_t *mem = pfont->memory;
+ /* HACK: We know the font was allocated by the interpreter. */
+ gs_ref_memory_t *imem = (gs_ref_memory_t *)mem;
gs_font **pdep = pfont->data.FDepVector;
ref newdep;
uint fdep_size = pfont->data.fdep_size;
ref *prdep;
uint i;
- int code = ialloc_ref_array(&newdep, a_readonly, fdep_size,
- "ztype0_adjust_matrix");
+ int code = gs_alloc_ref_array(imem, &newdep, a_readonly, fdep_size,
+ "ztype0_adjust_matrix");
if (code < 0)
return code;
for (prdep = newdep.value.refs, i = 0; i < fdep_size; i++, prdep++) {
const ref *pdict = pfont_dict(pdep[i]);
- ref_assign_new(prdep, pdict);
+ ref_assign(prdep, pdict);
+ r_set_attrs(prdep, imemory_new_mask(imem));
}
/*
* The FDepVector is an existing key in the parent's dictionary,
diff --git a/gs/src/zfont1.c b/gs/src/zfont1.c
index 2ab768ee0..b985fbe37 100644
--- a/gs/src/zfont1.c
+++ b/gs/src/zfont1.c
@@ -23,25 +23,26 @@
#include "gxfixed.h"
#include "gsmatrix.h"
#include "gxdevice.h"
-#include "gschar.h"
#include "gxfont.h"
#include "gxfont1.h"
#include "bfont.h"
#include "ialloc.h"
+#include "icharout.h"
#include "idict.h"
#include "idparam.h"
#include "ifont1.h"
+#include "iname.h" /* for name_index in enumerate_glyph */
#include "store.h"
-/*#define TEST*/
-
-/* Type 1 auxiliary procedures (defined in zchar1.c) */
+/* Type 1 font procedures (defined in zchar1.c) */
extern const gs_type1_data_procs_t z1_data_procs;
+font_proc_glyph_outline(zcharstring_glyph_outline);
/* Default value of lenIV */
#define DEFAULT_LENIV_1 4
-/* Private utilities */
+/* ------ Private utilities ------ */
+
private void
find_zone_height(float *pmax_height, int count, const float *values)
{
@@ -53,6 +54,20 @@ find_zone_height(float *pmax_height, int count, const float *values)
*pmax_height = zone_height;
}
+/* ------ Font procedures ------ */
+
+private int
+z1_enumerate_glyph(gs_font * pfont, int *pindex, gs_glyph_space_t ignored,
+ gs_glyph * pglyph)
+{
+ const gs_font_type1 *const pfont1 = (gs_font_type1 *)pfont;
+ const ref *pcsdict = &pfont_data(pfont1)->CharStrings;
+
+ return zchar_enumerate_glyph(pcsdict, pindex, pglyph);
+}
+
+/* ------ Public procedures ------ */
+
/* Extract pointers to internal structures. */
int
charstring_font_get_refs(os_ptr op, charstring_font_refs_t *pfr)
@@ -175,9 +190,13 @@ build_charstring_font(i_ctx_t *i_ctx_p, os_ptr op, build_proc_refs *pbuild,
ref_assign(&pdata->u.type1.GlobalSubrs, pfr->GlobalSubrs);
pfont->data.procs = &z1_data_procs;
pfont->data.proc_data = (char *)pdata;
+ pfont->procs.enumerate_glyph = z1_enumerate_glyph;
+ pfont->procs.glyph_outline = zcharstring_glyph_outline;
return define_gs_font((gs_font *)pfont);
}
+/* ------ Operators ------ */
+
/* Build a Type 1 or Type 4 font. */
private int
buildfont1or4(i_ctx_t *i_ctx_p, os_ptr op, build_proc_refs * pbuild,
@@ -226,40 +245,11 @@ zbuildfont4(i_ctx_t *i_ctx_p)
return buildfont1or4(i_ctx_p, op, &build, ft_disk_based, bf_options_none);
}
-#ifdef TEST
-
-#include "igstate.h"
-#include "stream.h"
-#include "files.h"
-
-/* <file> .printfont1 - */
-private int
-zprintfont1(i_ctx_t *i_ctx_p)
-{
- os_ptr op = osp;
- const gs_font *pfont = gs_currentfont(igs);
- stream *s;
- int code;
-
- if (pfont->FontType != ft_encrypted)
- return_error(e_rangecheck);
- check_write_file(s, op);
- code = psdf_embed_type1_font(s, (gs_font_type1 *) pfont);
- if (code >= 0)
- pop(1);
- return code;
-}
-
-#endif
-
/* ------ Initialization procedure ------ */
const op_def zfont1_op_defs[] =
{
{"2.buildfont1", zbuildfont1},
{"2.buildfont4", zbuildfont4},
-#ifdef TEST
- {"2.printfont1", zprintfont1},
-#endif
op_def_end(0)
};
diff --git a/gs/src/zfont32.c b/gs/src/zfont32.c
index 4338733d9..8ee3de2dc 100644
--- a/gs/src/zfont32.c
+++ b/gs/src/zfont32.c
@@ -23,15 +23,13 @@
#include "gsccode.h" /* for gxfont.h */
#include "gsmatrix.h"
#include "gsutil.h"
-#include "gxfixed.h" /* for gxchar.h */
-#include "gxchar.h"
#include "gxfont.h"
#include "bfont.h"
#include "store.h"
/* The encode_char procedure of a Type 32 font should never be called. */
private gs_glyph
-zfont_no_encode_char(gs_show_enum * penum, gs_font * pfont, gs_char * pchr)
+zfont_no_encode_char(gs_font *pfont, gs_char chr, gs_glyph_space_t ignored)
{
return gs_no_glyph;
}
diff --git a/gs/src/zfont42.c b/gs/src/zfont42.c
index ed6183550..bef0a659b 100644
--- a/gs/src/zfont42.c
+++ b/gs/src/zfont42.c
@@ -26,13 +26,20 @@
#include "gxfont.h"
#include "gxfont42.h"
#include "bfont.h"
+#include "icharout.h"
#include "idict.h"
#include "idparam.h"
+#include "iname.h"
#include "store.h"
/* Forward references */
private int z42_string_proc(P4(gs_font_type42 *, ulong, uint, const byte **));
private int z42_gdir_get_outline(P3(gs_font_type42 *, uint, gs_const_string *));
+private font_proc_enumerate_glyph(z42_enumerate_glyph);
+private font_proc_enumerate_glyph(z42_gdir_enumerate_glyph);
+private font_proc_encode_char(z42_encode_char);
+private font_proc_glyph_info(z42_glyph_info);
+private font_proc_glyph_outline(z42_glyph_outline);
/* <string|name> <font_dict> .buildfont11/42 <string|name> <font> */
/* Build a type 11 (TrueType CID-keyed) or 42 (TrueType) font. */
@@ -86,29 +93,22 @@ build_gs_TrueType_font(i_ctx_t *i_ctx_p, os_ptr op, font_type ftype,
if (code < 0)
return code;
/*
- * Some versions of the Adobe PostScript Windows driver have a bug
- * that causes them to output the FontBBox for Type 42 fonts in the
- * 2048- or 4096-unit character space rather than a 1-unit space.
- * Work around this here.
+ * If the font has a GlyphDictionary, this replaces loca and glyf for
+ * accessing character outlines. In this case, we use alternate
+ * get_outline and enumerate_glyph procedures.
*/
- if (pfont->FontBBox.q.x - pfont->FontBBox.p.x > 100 ||
- pfont->FontBBox.q.y - pfont->FontBBox.p.y > 100
- ) {
- float upem = pfont->data.unitsPerEm;
-
- pfont->FontBBox.p.x /= upem;
- pfont->FontBBox.p.y /= upem;
- pfont->FontBBox.q.x /= upem;
- pfont->FontBBox.q.y /= upem;
- }
+ if (!r_has_type(&GlyphDirectory, t_null)) {
+ pfont->data.get_outline = z42_gdir_get_outline;
+ pfont->procs.enumerate_glyph = z42_gdir_enumerate_glyph;
+ } else
+ pfont->procs.enumerate_glyph = z42_enumerate_glyph;
/*
- * Apparently Adobe versions 2015 and later use an alternate
- * method of accessing character outlines: instead of loca and glyf,
- * they use a dictionary called GlyphDirectory. In this case,
- * we use an alternate get_outline procedure.
+ * The procedures that access glyph information must accept either
+ * glyph names or glyph indexes.
*/
- if (!r_has_type(&GlyphDirectory, t_null))
- pfont->data.get_outline = z42_gdir_get_outline;
+ pfont->procs.encode_char = z42_encode_char;
+ pfont->procs.glyph_info = z42_glyph_info;
+ pfont->procs.glyph_outline = z42_glyph_outline;
return define_gs_font((gs_font *) pfont);
}
private int
@@ -151,6 +151,82 @@ z42_gdir_get_outline(gs_font_type42 * pfont, uint glyph_index,
return 0;
}
+/* Reduce a glyph name to a glyph index if needed. */
+private gs_glyph
+glyph_to_index(const gs_font *font, gs_glyph glyph)
+{
+ ref gref;
+ ref *pcstr;
+
+ if (glyph >= gs_min_cid_glyph)
+ return glyph;
+ name_index_ref(glyph, &gref);
+ if (dict_find(&pfont_data(font)->CharStrings, &gref, &pcstr) > 0 &&
+ r_has_type(pcstr, t_integer)
+ ) {
+ gs_glyph index_glyph = pcstr->value.intval + gs_min_cid_glyph;
+
+ if (index_glyph >= gs_min_cid_glyph && index_glyph <= gs_max_glyph)
+ return index_glyph;
+ }
+ return gs_min_cid_glyph; /* glyph 0 is notdef */
+}
+
+/* Enumerate glyphs from CharStrings or loca / glyf. */
+private int
+z42_enumerate_glyph(gs_font *font, int *pindex, gs_glyph_space_t glyph_space,
+ gs_glyph *pglyph)
+{
+ if (glyph_space == GLYPH_SPACE_INDEX)
+ return gs_type42_enumerate_glyph(font, pindex, glyph_space, pglyph);
+ else {
+ const ref *pcsdict = &pfont_data(font)->CharStrings;
+
+ return zchar_enumerate_glyph(pcsdict, pindex, pglyph);
+ }
+}
+
+/* Enumerate glyphs (keys) from GlyphDirectory instead of loca / glyf. */
+private int
+z42_gdir_enumerate_glyph(gs_font *font, int *pindex,
+ gs_glyph_space_t glyph_space, gs_glyph *pglyph)
+{
+ const ref *pgdict;
+
+ if (glyph_space == GLYPH_SPACE_INDEX)
+ pgdict = &pfont_data(font)->u.type42.GlyphDirectory;
+ else
+ pgdict = &pfont_data(font)->CharStrings;
+ return zchar_enumerate_glyph(pgdict, pindex, pglyph);
+}
+
+/*
+ * Define font procedures that accept either a character name or a glyph
+ * index as the glyph.
+ */
+private gs_glyph
+z42_encode_char(gs_font *font, gs_char chr, gs_glyph_space_t glyph_space)
+{
+ gs_glyph glyph = zfont_encode_char(font, chr, glyph_space);
+
+ return (glyph_space == GLYPH_SPACE_INDEX && glyph != gs_no_glyph ?
+ glyph_to_index(font, glyph) : glyph);
+}
+private int
+z42_glyph_outline(gs_font *font, gs_glyph glyph, const gs_matrix *pmat,
+ gx_path *ppath)
+{
+ return gs_type42_glyph_outline(font, glyph_to_index(font, glyph),
+ pmat, ppath);
+}
+private int
+z42_glyph_info(gs_font *font, gs_glyph glyph, const gs_matrix *pmat,
+ int members, gs_glyph_info_t *info)
+{
+ return gs_type42_glyph_info(font, glyph_to_index(font, glyph),
+ pmat, members, info);
+}
+
/* Procedure for accessing the sfnts array. */
private int
z42_string_proc(gs_font_type42 * pfont, ulong offset, uint length,
diff --git a/gs/src/zfproc.c b/gs/src/zfproc.c
index 754ec0029..9b52f1152 100644
--- a/gs/src/zfproc.c
+++ b/gs/src/zfproc.c
@@ -34,28 +34,27 @@
/* ---------------- Generic ---------------- */
/* GC procedures */
-#define pptr ((stream_proc_state *)vptr)
private
CLEAR_MARKS_PROC(sproc_clear_marks)
{
+ stream_proc_state *const pptr = vptr;
+
r_clear_attrs(&pptr->proc, l_mark);
r_clear_attrs(&pptr->data, l_mark);
}
private
-ENUM_PTRS_BEGIN(sproc_enum_ptrs) return 0;
-
+ENUM_PTRS_WITH(sproc_enum_ptrs, stream_proc_state *pptr) return 0;
case 0:
ENUM_RETURN_REF(&pptr->proc);
case 1:
ENUM_RETURN_REF(&pptr->data);
ENUM_PTRS_END
-private RELOC_PTRS_BEGIN(sproc_reloc_ptrs);
+private RELOC_PTRS_WITH(sproc_reloc_ptrs, stream_proc_state *pptr);
RELOC_REF_VAR(pptr->proc);
r_clear_attrs(&pptr->proc, l_mark);
RELOC_REF_VAR(pptr->data);
r_clear_attrs(&pptr->data, l_mark);
RELOC_PTRS_END
-#undef pptr
/* Structure type for procedure-based streams. */
private_st_stream_proc_state();
@@ -64,22 +63,23 @@ private_st_stream_proc_state();
/* The caller must have checked that *sop is a procedure. */
private int
s_proc_init(ref * sop, stream ** psstrm, uint mode,
- const stream_template * temp, const stream_procs * procs)
+ const stream_template * temp, const stream_procs * procs,
+ gs_ref_memory_t *imem)
{
- stream *sstrm = file_alloc_stream(imemory, "s_proc_init(stream)");
- stream_proc_state *state =
- (stream_proc_state *) s_alloc_state(imemory, &st_sproc_state,
- "s_proc_init(state)");
+ gs_memory_t *const mem = (gs_memory_t *)imem;
+ stream *sstrm = file_alloc_stream(mem, "s_proc_init(stream)");
+ stream_proc_state *state = (stream_proc_state *)
+ s_alloc_state(mem, &st_sproc_state, "s_proc_init(state)");
if (sstrm == 0 || state == 0) {
- ifree_object(state, "s_proc_init(state)");
- /*ifree_object(sstrm, "s_proc_init(stream)"); *//* just leave it on the file list */
+ gs_free_object(mem, state, "s_proc_init(state)");
+ /*gs_free_object(mem, sstrm, "s_proc_init(stream)"); *//* just leave it on the file list */
return_error(e_VMerror);
}
s_std_init(sstrm, NULL, 0, procs, mode);
sstrm->procs.process = temp->process;
state->template = temp;
- state->memory = imemory;
+ state->memory = mem;
state->eof = 0;
state->proc = *sop;
make_empty_string(&state->data, a_all);
@@ -116,6 +116,15 @@ s_handle_intc(i_ctx_t *i_ctx_p, const ref *pstate, int nstate,
return o_push_estack;
}
+/* Set default parameter values (actually, just clear pointers). */
+private void
+s_proc_set_defaults(stream_state * st)
+{
+ stream_proc_state *const ss = (stream_proc_state *) st;
+
+ make_null(&ss->proc);
+ make_null(&ss->data);
+}
/* ---------------- Read streams ---------------- */
@@ -125,7 +134,8 @@ private int s_proc_read_continue(P1(i_ctx_t *));
/* Stream templates */
private const stream_template s_proc_read_template = {
- &st_sproc_state, NULL, s_proc_read_process, 1, 1, NULL
+ &st_sproc_state, NULL, s_proc_read_process, 1, 1,
+ NULL, s_proc_set_defaults
};
private const stream_procs s_proc_read_procs = {
s_std_noavailable, s_std_noseek, s_std_read_reset,
@@ -135,11 +145,11 @@ private const stream_procs s_proc_read_procs = {
/* Allocate and open a procedure-based read stream. */
/* The caller must have checked that *sop is a procedure. */
int
-sread_proc(ref * sop, stream ** psstrm)
+sread_proc(ref * sop, stream ** psstrm, gs_ref_memory_t *imem)
{
int code =
s_proc_init(sop, psstrm, s_mode_read, &s_proc_read_template,
- &s_proc_read_procs);
+ &s_proc_read_procs, imem);
if (code < 0)
return code;
@@ -234,7 +244,8 @@ private int s_proc_write_continue(P1(i_ctx_t *));
/* Stream templates */
private const stream_template s_proc_write_template = {
- &st_sproc_state, NULL, s_proc_write_process, 1, 1, NULL
+ &st_sproc_state, NULL, s_proc_write_process, 1, 1,
+ NULL, s_proc_set_defaults
};
private const stream_procs s_proc_write_procs = {
s_std_noavailable, s_std_noseek, s_std_write_reset,
@@ -244,10 +255,10 @@ private const stream_procs s_proc_write_procs = {
/* Allocate and open a procedure-based write stream. */
/* The caller must have checked that *sop is a procedure. */
int
-swrite_proc(ref * sop, stream ** psstrm)
+swrite_proc(ref * sop, stream ** psstrm, gs_ref_memory_t *imem)
{
return s_proc_init(sop, psstrm, s_mode_write, &s_proc_write_template,
- &s_proc_write_procs);
+ &s_proc_write_procs, imem);
}
/* Handle an output request. */
diff --git a/gs/src/zfreuse.c b/gs/src/zfreuse.c
index 494b149c4..346aae1a9 100644
--- a/gs/src/zfreuse.c
+++ b/gs/src/zfreuse.c
@@ -114,8 +114,9 @@ zrsdparams(i_ctx_t *i_ctx_p)
* source;
* - A reusable stream.
*/
-private int make_rss(P7(os_ptr op, const byte * data, uint size, long offset,
- long length, bool is_bytestring, bool close_source));
+private int make_rss(P8(i_ctx_t *i_ctx_p, os_ptr op, const byte * data,
+ uint size, long offset, long length,
+ bool is_bytestring, bool close_source));
private int
zreusablestream(i_ctx_t *i_ctx_p)
{
@@ -138,7 +139,7 @@ zreusablestream(i_ctx_t *i_ctx_p)
uint size = r_size(source_op);
check_read(*source_op);
- code = make_rss(source_op, source_op->value.const_bytes,
+ code = make_rss(i_ctx_p, source_op, source_op->value.const_bytes,
size, 0L, (length < 0 ? size : length), false,
close_source);
} else if (r_has_type(source_op, t_astruct)) {
@@ -147,9 +148,9 @@ zreusablestream(i_ctx_t *i_ctx_p)
if (gs_object_type(imemory, source_op->value.pstruct) != &st_bytes)
return_error(e_rangecheck);
check_read(*source_op);
- code = make_rss(source_op, (const byte *)source_op->value.pstruct,
- size, 0L, (length < 0 ? size : length), true,
- close_source);
+ code = make_rss(i_ctx_p, source_op,
+ (const byte *)source_op->value.pstruct, size, 0L,
+ (length < 0 ? size : length), true, close_source);
} else {
long offset = 0;
stream *source;
@@ -164,7 +165,7 @@ rs:
savailable(source, &avail);
if (avail < 0)
avail = 0;
- code = make_rss(source_op, source->cbuf_string.data,
+ code = make_rss(i_ctx_p, source_op, source->cbuf_string.data,
source->cbuf_string.size, offset, avail, false,
close_source);
} else if (source->file != 0) {
@@ -199,8 +200,8 @@ rs:
/* Make a reusable string stream. */
private int
-make_rss(os_ptr op, const byte * data, uint size, long offset,
- long length, bool is_bytestring, bool close_source)
+make_rss(i_ctx_t *i_ctx_p, os_ptr op, const byte * data, uint size,
+ long offset, long length, bool is_bytestring, bool close_source)
{
stream *s;
diff --git a/gs/src/zfunc.c b/gs/src/zfunc.c
index dd910b4c7..df77d30d3 100644
--- a/gs/src/zfunc.c
+++ b/gs/src/zfunc.c
@@ -57,7 +57,7 @@ zbuildfunction(i_ctx_t *i_ctx_p)
".buildfunction");
if (code < 0)
return code;
- code = fn_build_function(op, &pfn);
+ code = fn_build_function(op, &pfn, imemory);
if (code < 0) {
ifree_ref_array(&cref, ".buildfunction");
return code;
@@ -128,7 +128,13 @@ zexecfunction(i_ctx_t *i_ctx_p)
/* Build a function structure from a PostScript dictionary. */
int
-fn_build_sub_function(const ref * op, gs_function_t ** ppfn, int depth)
+fn_build_function(const ref * op, gs_function_t ** ppfn, gs_memory_t *mem)
+{
+ return fn_build_sub_function(op, ppfn, 0, mem);
+}
+int
+fn_build_sub_function(const ref * op, gs_function_t ** ppfn, int depth,
+ gs_memory_t *mem)
{
int code, type, i;
gs_function_params_t params;
@@ -147,33 +153,35 @@ fn_build_sub_function(const ref * op, gs_function_t ** ppfn, int depth)
/* Collect parameters common to all function types. */
params.Domain = 0;
params.Range = 0;
- code = fn_build_float_array(op, "Domain", true, true, &params.Domain);
+ code = fn_build_float_array(op, "Domain", true, true, &params.Domain, mem);
if (code < 0)
goto fail;
params.m = code >> 1;
- code = fn_build_float_array(op, "Range", false, true, &params.Range);
+ code = fn_build_float_array(op, "Range", false, true, &params.Range, mem);
if (code < 0)
goto fail;
params.n = code >> 1;
/* Finish building the function. */
/* If this fails, it will free all the parameters. */
- return (*build_function_type_table[i].proc)(op, &params, depth + 1, ppfn);
+ return (*build_function_type_table[i].proc)
+ (op, &params, depth + 1, ppfn, mem);
fail:
- ifree_const_object(params.Range, "Range");
- ifree_const_object(params.Domain, "Domain");
+ gs_free_const_object(mem, params.Range, "Range");
+ gs_free_const_object(mem, params.Domain, "Domain");
return code;
}
/* Allocate an array of function objects. */
int
-ialloc_function_array(uint count, gs_function_t *** pFunctions)
+alloc_function_array(uint count, gs_function_t *** pFunctions,
+ gs_memory_t *mem)
{
gs_function_t **ptr;
if (count == 0)
return_error(e_rangecheck);
- ptr = ialloc_struct_array(count, gs_function_t *,
- &st_function_ptr_element, "Functions");
+ ptr = gs_alloc_struct_array(mem, count, gs_function_t *,
+ &st_function_ptr_element, "Functions");
if (ptr == 0)
return_error(e_VMerror);
memset(ptr, 0, sizeof(*ptr) * count);
@@ -189,7 +197,7 @@ ialloc_function_array(uint count, gs_function_t *** pFunctions)
*/
int
fn_build_float_array(const ref * op, const char *kstr, bool required,
- bool even, const float **pparray)
+ bool even, const float **pparray, gs_memory_t *mem)
{
ref *par;
int code;
@@ -201,13 +209,14 @@ fn_build_float_array(const ref * op, const char *kstr, bool required,
return_error(e_typecheck);
{
uint size = r_size(par);
- float *ptr = (float *)ialloc_byte_array(size, sizeof(float), kstr);
+ float *ptr = (float *)
+ gs_alloc_byte_array(mem, size, sizeof(float), kstr);
if (ptr == 0)
return_error(e_VMerror);
code = dict_float_array_param(op, kstr, size, ptr, NULL);
if (code < 0 || (even && (code & 1) != 0)) {
- ifree_object(ptr, kstr);
+ gs_free_object(mem, ptr, kstr);
return(code < 0 ? code : gs_note_error(e_rangecheck));
}
*pparray = ptr;
diff --git a/gs/src/zfunc0.c b/gs/src/zfunc0.c
index 89cc7c033..c1701f0f9 100644
--- a/gs/src/zfunc0.c
+++ b/gs/src/zfunc0.c
@@ -31,10 +31,13 @@
#include "idparam.h"
#include "ifunc.h"
+/* Check prototype */
+build_function_proc(gs_build_function_0);
+
/* Finish building a FunctionType 0 (Sampled) function. */
int
gs_build_function_0(const ref *op, const gs_function_params_t * mnDR,
- int depth, gs_function_t ** ppfn)
+ int depth, gs_function_t ** ppfn, gs_memory_t *mem)
{
gs_function_Sd_params_t params;
ref *pDataSource;
@@ -68,12 +71,13 @@ gs_build_function_0(const ref *op, const gs_function_params_t * mnDR,
if ((code = dict_int_param(op, "Order", 1, 3, 1, &params.Order)) < 0 ||
(code = dict_int_param(op, "BitsPerSample", 1, 32, 0,
&params.BitsPerSample)) < 0 ||
- ((code = fn_build_float_array(op, "Encode", false, true, &params.Encode)) != 2 * params.m && (code != 0 || params.Encode != 0)) ||
- ((code = fn_build_float_array(op, "Decode", false, true, &params.Decode)) != 2 * params.n && (code != 0 || params.Decode != 0))
+ ((code = fn_build_float_array(op, "Encode", false, true, &params.Encode, mem)) != 2 * params.m && (code != 0 || params.Encode != 0)) ||
+ ((code = fn_build_float_array(op, "Decode", false, true, &params.Decode, mem)) != 2 * params.n && (code != 0 || params.Decode != 0))
) {
goto fail;
} {
- int *ptr = (int *)ialloc_byte_array(params.m, sizeof(int), "Size");
+ int *ptr = (int *)
+ gs_alloc_byte_array(mem, params.m, sizeof(int), "Size");
if (ptr == 0) {
code = gs_note_error(e_VMerror);
@@ -84,10 +88,10 @@ gs_build_function_0(const ref *op, const gs_function_params_t * mnDR,
if (code != params.m)
goto fail;
}
- code = gs_function_Sd_init(ppfn, &params, imemory);
+ code = gs_function_Sd_init(ppfn, &params, mem);
if (code >= 0)
return 0;
fail:
- gs_function_Sd_free_params(&params, imemory);
+ gs_function_Sd_free_params(&params, mem);
return (code < 0 ? code : gs_note_error(e_rangecheck));
}
diff --git a/gs/src/zfunc3.c b/gs/src/zfunc3.c
index c9d3cbb6b..c55b73fab 100644
--- a/gs/src/zfunc3.c
+++ b/gs/src/zfunc3.c
@@ -31,12 +31,14 @@
#include "ifunc.h"
#include "store.h"
-/* Define the available Function types. */
+/* Check prototypes */
+build_function_proc(gs_build_function_2);
+build_function_proc(gs_build_function_3);
/* Finish building a FunctionType 2 (ExponentialInterpolation) function. */
int
gs_build_function_2(const ref *op, const gs_function_params_t * mnDR,
- int depth, gs_function_t ** ppfn)
+ int depth, gs_function_t ** ppfn, gs_memory_t *mem)
{
gs_function_ElIn_params_t params;
int code, n0, n1;
@@ -45,8 +47,8 @@ gs_build_function_2(const ref *op, const gs_function_params_t * mnDR,
params.C0 = 0;
params.C1 = 0;
if ((code = dict_float_param(op, "N", 0.0, &params.N)) != 0 ||
- (code = n0 = fn_build_float_array(op, "C0", false, false, &params.C0)) < 0 ||
- (code = n1 = fn_build_float_array(op, "C1", false, false, &params.C1)) < 0
+ (code = n0 = fn_build_float_array(op, "C0", false, false, &params.C0, mem)) < 0 ||
+ (code = n1 = fn_build_float_array(op, "C1", false, false, &params.C1, mem)) < 0
)
goto fail;
if (params.C0 == 0)
@@ -57,18 +59,18 @@ gs_build_function_2(const ref *op, const gs_function_params_t * mnDR,
params.n = n0; /* either one will do */
if (n0 != n1 || n0 != params.n)
goto fail;
- code = gs_function_ElIn_init(ppfn, &params, imemory);
+ code = gs_function_ElIn_init(ppfn, &params, mem);
if (code >= 0)
return 0;
fail:
- gs_function_ElIn_free_params(&params, imemory);
+ gs_function_ElIn_free_params(&params, mem);
return (code < 0 ? code : gs_note_error(e_rangecheck));
}
/* Finish building a FunctionType 3 (1-Input Stitching) function. */
int
gs_build_function_3(const ref *op, const gs_function_params_t * mnDR,
- int depth, gs_function_t ** ppfn)
+ int depth, gs_function_t ** ppfn, gs_memory_t *mem)
{
gs_function_1ItSg_params_t params;
int code;
@@ -86,7 +88,7 @@ gs_build_function_3(const ref *op, const gs_function_params_t * mnDR,
return (code < 0 ? code : gs_note_error(e_rangecheck));
check_array_only(*pFunctions);
params.k = r_size(pFunctions);
- code = ialloc_function_array(params.k, &ptr);
+ code = alloc_function_array(params.k, &ptr, mem);
if (code < 0)
return code;
params.Functions = (const gs_function_t * const *)ptr;
@@ -94,21 +96,21 @@ gs_build_function_3(const ref *op, const gs_function_params_t * mnDR,
ref subfn;
array_get(pFunctions, (long)i, &subfn);
- code = fn_build_sub_function(&subfn, &ptr[i], depth);
+ code = fn_build_sub_function(&subfn, &ptr[i], depth, mem);
if (code < 0)
goto fail;
}
}
- if ((code = fn_build_float_array(op, "Bounds", true, false, &params.Bounds)) != params.k - 1 ||
- (code = fn_build_float_array(op, "Encode", true, true, &params.Encode)) != 2 * params.k
+ if ((code = fn_build_float_array(op, "Bounds", true, false, &params.Bounds, mem)) != params.k - 1 ||
+ (code = fn_build_float_array(op, "Encode", true, true, &params.Encode, mem)) != 2 * params.k
)
goto fail;
if (params.Range == 0)
params.n = params.Functions[0]->params.n;
- code = gs_function_1ItSg_init(ppfn, &params, imemory);
+ code = gs_function_1ItSg_init(ppfn, &params, mem);
if (code >= 0)
return 0;
fail:
- gs_function_1ItSg_free_params(&params, imemory);
+ gs_function_1ItSg_free_params(&params, mem);
return (code < 0 ? code : gs_note_error(e_rangecheck));
}
diff --git a/gs/src/zfunc4.c b/gs/src/zfunc4.c
new file mode 100644
index 000000000..3b908ee62
--- /dev/null
+++ b/gs/src/zfunc4.c
@@ -0,0 +1,299 @@
+/* Copyright (C) 1999 Aladdin Enterprises. All rights reserved.
+
+ This file is part of Aladdin Ghostscript.
+
+ Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
+ or distributor accepts any responsibility for the consequences of using it,
+ or for whether it serves any particular purpose or works at all, unless he
+ or she says so in writing. Refer to the Aladdin Ghostscript Free Public
+ License (the "License") for full details.
+
+ Every copy of Aladdin Ghostscript must include a copy of the License,
+ normally in a plain ASCII text file named PUBLIC. The License grants you
+ the right to copy, modify and redistribute Aladdin Ghostscript, but only
+ under certain conditions described in the License. Among other things, the
+ License requires that the copyright notice and this notice be preserved on
+ all copies.
+ */
+
+
+/* PostScript language support for FunctionType 4 (PS Calculator) Functions */
+#include "memory_.h"
+#include "ghost.h"
+#include "oper.h"
+#include "opextern.h"
+#include "gsfunc.h"
+#include "stream.h" /* for files.h */
+#include "files.h"
+#include "ialloc.h"
+#include "idict.h"
+#include "idparam.h"
+#include "ifunc.h"
+#include "istkparm.h"
+#include "istruct.h"
+#include "store.h"
+
+/*
+ * FunctionType 4 functions are not defined in the PostScript language.
+ * We provide support for them because they are needed for PDF 1.3.
+ * In addition to the standard FunctionType, Domain, and Range keys,
+ * they have a Function key whose value is a procedure in a restricted
+ * subset of the PostScript language. Specifically, the procedure must
+ * (recursively) contain only integer, real, Boolean, and procedure
+ * constants, and operators chosen from the set given below. Note that
+ * names are not allowed: the procedure must be 'bound'.
+ *
+ * The following list is taken directly from the PDF 1.3 documentation.
+ */
+#define XOP(zfn) int zfn(P1(i_ctx_t *))
+XOP(zabs); XOP(zand); XOP(zatan); XOP(zbitshift);
+XOP(zceiling); XOP(zcos); XOP(zcvi); XOP(zcvr);
+XOP(zdiv); XOP(zexp); XOP(zfloor); XOP(zidiv);
+XOP(zln); XOP(zlog); XOP(zmod); XOP(zmul);
+XOP(zneg); XOP(znot); XOP(zor); XOP(zround);
+XOP(zsin); XOP(zsqrt); XOP(ztruncate); XOP(zxor);
+XOP(zeq); XOP(zge); XOP(zgt); XOP(zle); XOP(zlt); XOP(zne);
+#undef XOP
+/*
+ * Define operators for true and false, so we don't have to treat them
+ * as special cases but can bind them.
+ */
+private int
+ztrue(i_ctx_t *i_ctx_p)
+{
+ os_ptr op = osp;
+
+ push(1);
+ make_true(op);
+ return 0;
+}
+private int
+zfalse(i_ctx_t *i_ctx_p)
+{
+ os_ptr op = osp;
+
+ push(1);
+ make_false(op);
+ return 0;
+}
+static const op_proc_t calc_ops[] = {
+ /* Arithmetic operators */
+ zabs, zadd, zand, zatan, zbitshift, zceiling, zcos, zcvi, zcvr, zdiv, zexp,
+ zfloor, zidiv, zln, zlog, zmod, zmul, zneg, znot, zor, zround,
+ zsin, zsqrt, zsub, ztruncate, zxor,
+
+ /* Boolean operators */
+ /*zand,*/ zeq, zge, zgt, zif, zifelse, zle, zlt, zne, /*znot, zor,*/
+ ztrue, zfalse,
+
+ /* Stack operators */
+ zcopy, zdup, zexch, zindex, zpop, zroll
+};
+
+/* Define a trivial structure that holds a ref pointer. */
+typedef struct ref_ptr_s {
+ ref *pref;
+} ref_ptr_t;
+gs_private_st_composite(st_ref_ptr, ref_ptr_t, "ref_ptr_t",
+ ref_ptr_enum_ptrs, ref_ptr_reloc_ptrs);
+private
+ENUM_PTRS_WITH(ref_ptr_enum_ptrs, ref_ptr_t *prp) return 0;
+case 0: ENUM_RETURN_REF(prp->pref);
+ENUM_PTRS_END
+private
+RELOC_PTRS_WITH(ref_ptr_reloc_ptrs, ref_ptr_t *prp)
+RELOC_REF_VAR(prp->pref);
+RELOC_PTRS_END
+
+/*
+ * Evaluate a PostScript Calculator function. This is a very stripped-down
+ * version of the PostScript interpreter loop. Note that the check we
+ * made when constructing the function bounds the recursion depth of
+ * psc_interpret.
+ */
+private int
+psc_interpret(i_ctx_t *i_ctx_p, const ref *proc)
+{
+ uint i;
+ int code = 0;
+
+ for (i = 0; i < r_size(proc) && code >= 0; ++i) {
+ ref elt;
+
+ array_get(proc, (long)i, &elt);
+ if (r_btype(&elt) == t_operator) {
+ if (elt.value.opproc == zif) {
+ if (!(r_has_type(osp - 1, t_boolean) && r_is_proc(osp)))
+ return_error(e_typecheck);
+ osp -= 2;
+ if (osp[1].value.boolval) {
+ ref_assign(&elt, osp + 2);
+ code = psc_interpret(i_ctx_p, &elt);
+ }
+ } else if (elt.value.opproc == zifelse) {
+ if (!(r_has_type(osp - 2, t_boolean) && r_is_proc(osp - 1) &&
+ r_is_proc(osp))
+ )
+ return_error(e_typecheck);
+ osp -= 3;
+ ref_assign(&elt, (osp[1].value.boolval ? osp + 2 : osp + 3));
+ code = psc_interpret(i_ctx_p, &elt);
+ } else {
+ code = elt.value.opproc(i_ctx_p);
+ }
+ } else {
+ if (osp >= ostop)
+ return_error(e_rangecheck);
+ ++osp;
+ ref_assign(osp, &elt);
+ }
+ }
+ return code;
+}
+private int
+fn_psc_evaluate(const gs_function_t * pfn_common, const float *in, float *out)
+{
+ const gs_function_Va_t *const pfn =
+ (const gs_function_Va_t *)pfn_common;
+ const ref *const pref = ((const ref_ptr_t *)pfn->params.eval_data)->pref;
+ /*
+ * Although operators take an i_ctx_t * (a.k.a. gs_context_state_t *)
+ * as their operand, the only operators that we can call here use
+ * only the operand stack. We can get away with fabricating a context
+ * state out of whole cloth and only filling in its operand stack.
+ */
+#define MAX_OSTACK 100 /* per PDF 1.3 spec */
+#define OS_GUARD 10
+ ref values[OS_GUARD + MAX_OSTACK + OS_GUARD];
+ i_ctx_t context;
+ i_ctx_t *const i_ctx_p = &context;
+ ref_stack_t *const pos = &context.op_stack.stack;
+ ref_stack_params_t params;
+ ref osref;
+ int i;
+ int code;
+
+ /* Create the operand stack. */
+ make_array(&osref, a_all, countof(values), values);
+ ref_stack_init(pos, &osref, OS_GUARD, OS_GUARD, NULL, NULL, &params);
+ ref_stack_set_error_codes(pos, e_rangecheck, e_rangecheck);
+ ref_stack_set_max_count(pos, MAX_OSTACK);
+ ref_stack_allow_expansion(pos, false);
+
+ /* Push the input values on the stack. */
+ for (i = 0; i < pfn->params.m; ++i) {
+ ++osp;
+ make_real(osp, in[i]);
+ }
+
+ /* Execute the procedure. */
+ code = psc_interpret(&context, pref);
+ if (code < 0)
+ return code;
+
+ /* Pop the results from the stack. */
+ if (ref_stack_count_inline(pos) != pfn->params.n)
+ return_error(e_rangecheck);
+ for (i = pfn->params.n; --i >= 0; --osp) {
+ switch (r_type(osp)) {
+ case t_real:
+ out[i] = osp->value.realval;
+ break;
+ case t_integer:
+ out[i] = osp->value.intval;
+ break;
+ default:
+ return_error(e_typecheck);
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Check a calculator function for validity. Note that we arbitrarily
+ * limit the depth of procedure nesting.
+ */
+#define MAX_PSC_FUNCTION_NESTING 6
+private int
+check_psc_function(const ref *pref, int depth)
+{
+ long i;
+ ref elt;
+
+ switch (r_btype(pref)) {
+ case t_integer: case t_real: case t_boolean:
+ return 0;
+ case t_operator:
+ for (i = 0; i < countof(calc_ops); ++i)
+ if (pref->value.opproc == calc_ops[i])
+ return 0;
+ return_error(e_rangecheck);
+ default:
+ if (!r_is_proc(pref))
+ return_error(e_typecheck);
+ if (depth == MAX_PSC_FUNCTION_NESTING)
+ return_error(e_limitcheck);
+ break;
+ }
+ for (i = r_size(pref); --i >= 0;) {
+ int code;
+
+ array_get(pref, i, &elt);
+ code = check_psc_function(&elt, depth + 1);
+ if (code < 0)
+ return code;
+ }
+ return 0;
+}
+#undef MAX_PSC_FUNCTION_NESTING
+
+/* Check prototype */
+build_function_proc(gs_build_function_4);
+
+/* Finish building a FunctionType 4 (PostScript Calculator) function. */
+int
+gs_build_function_4(const ref *op, const gs_function_params_t * mnDR,
+ int depth, gs_function_t ** ppfn, gs_memory_t *mem)
+{
+ gs_function_Va_params_t params;
+ int code = 0;
+ ref_ptr_t *prp;
+ ref *proc;
+
+ *(gs_function_params_t *)&params = *mnDR;
+ params.eval_data = 0; /* in case of error */
+ if (dict_find_string(op, "Function", &proc) <= 0)
+ goto fail;
+ code = check_psc_function(proc, 0);
+ if (code < 0)
+ goto fail;
+ params.eval_proc = fn_psc_evaluate;
+ /*
+ * We would like to simply set eval_data = proc. Unfortunately,
+ * eval_data is an ordinary pointer, not a ref pointer.
+ * We allocate an extra level of indirection to handle this.
+ */
+ prp = gs_alloc_struct(mem, ref_ptr_t, &st_ref_ptr, "gs_build_function_4");
+ if (prp == 0) {
+ code = gs_note_error(e_VMerror);
+ goto fail;
+ }
+ prp->pref = proc;
+ params.eval_data = prp;
+ code = gs_function_Va_init(ppfn, &params, mem);
+ if (code >= 0)
+ return 0;
+fail:
+ gs_function_Va_free_params(&params, mem);
+ return (code < 0 ? code : gs_note_error(e_rangecheck));
+}
+
+/* ------ Initialization procedure ------ */
+
+const op_def zfunc4_op_defs[] =
+{
+ {"0.true", ztrue},
+ {"0.false", zfalse},
+ op_def_end(0)
+};
diff --git a/gs/src/zfzlib.c b/gs/src/zfzlib.c
index 26e1b8945..26fed95d3 100644
--- a/gs/src/zfzlib.c
+++ b/gs/src/zfzlib.c
@@ -26,14 +26,8 @@
#include "spngpx.h"
#include "szlibx.h"
#include "ifilter.h"
-
-/* Import the Predictor machinery from zfdecode.c and zfilter2.c. */
-int filter_read_predictor(P4(i_ctx_t *i_ctx_p, int npop,
- const stream_template * template,
- stream_state * st));
-int filter_write_predictor(P4(i_ctx_t *i_ctx_p, int npop,
- const stream_template * template,
- stream_state * st));
+#include "ifrpred.h"
+#include "ifwpred.h"
/* <source> zlibEncode/filter <file> */
/* <source> <dict> zlibEncode/filter <file> */
diff --git a/gs/src/zgeneric.c b/gs/src/zgeneric.c
index ebddb1c50..29fdc421a 100644
--- a/gs/src/zgeneric.c
+++ b/gs/src/zgeneric.c
@@ -37,13 +37,10 @@
/* See the comment in opdef.h for an invariant which allows */
/* more efficient implementation of forall. */
-/* Imported operators */
-extern int zcopy_dict(P1(i_ctx_t *));
-
/* Forward references */
private int zcopy_integer(P1(i_ctx_t *));
private int zcopy_interval(P1(i_ctx_t *));
-private int copy_interval(P4(os_ptr, uint, os_ptr, client_name_t));
+private int copy_interval(P5(i_ctx_t *, os_ptr, uint, os_ptr, client_name_t));
/* <various1> <various2> copy <various> */
/* <obj1> ... <objn> <int> copy <obj1> ... <objn> <obj1> ... <objn> */
@@ -105,7 +102,7 @@ zcopy_interval(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
os_ptr op1 = op - 1;
- int code = copy_interval(op, 0, op1, "copy");
+ int code = copy_interval(i_ctx_p, op, 0, op1, "copy");
if (code < 0)
return code;
@@ -313,8 +310,8 @@ zputinterval(i_ctx_t *i_ctx_p)
case t_string:
check_write(*opto);
check_int_leu(*opindex, r_size(opto));
- code = copy_interval(opto, (uint)(opindex->value.intval), op,
- "putinterval");
+ code = copy_interval(i_ctx_p, opto, (uint)(opindex->value.intval),
+ op, "putinterval");
break;
case t_astruct: {
uint dsize, ssize, index;
@@ -511,7 +508,8 @@ const op_def zgeneric_op_defs[] =
/* and the starting index is known to be less than or equal to */
/* its length; nothing else has been checked. */
private int
-copy_interval(os_ptr prto, uint index, os_ptr prfrom, client_name_t cname)
+copy_interval(i_ctx_t *i_ctx_p /* for ref_assign_old */, os_ptr prto,
+ uint index, os_ptr prfrom, client_name_t cname)
{
int fromtype = r_type(prfrom);
uint fromsize = r_size(prfrom);
@@ -530,7 +528,7 @@ copy_interval(os_ptr prto, uint index, os_ptr prfrom, client_name_t cname)
{ /* We have to worry about aliasing, */
/* but refcpy_to_old takes care of it for us. */
return refcpy_to_old(prto, index, prfrom->value.refs,
- fromsize, cname);
+ fromsize, idmemory, cname);
}
case t_string:
{ /* memmove takes care of aliasing. */
diff --git a/gs/src/zgstate.c b/gs/src/zgstate.c
index 94df353f2..5c28b93fd 100644
--- a/gs/src/zgstate.c
+++ b/gs/src/zgstate.c
@@ -323,6 +323,34 @@ zcurrentaccuratecurves(i_ctx_t *i_ctx_p)
return 0;
}
+/* <join_int|-1> .setcurvejoin - */
+private int
+zsetcurvejoin(i_ctx_t *i_ctx_p)
+{
+ os_ptr op = osp;
+ int code;
+
+ check_type(*op, t_integer);
+ if (op->value.intval < -1 || op->value.intval > max_int)
+ return_error(e_rangecheck);
+ code = gs_setcurvejoin(igs, (int)op->value.intval);
+ if (code < 0)
+ return code;
+ pop(1);
+ return 0;
+}
+
+/* - .currentcurvejoin <join_int|-1> */
+private int
+zcurrentcurvejoin(i_ctx_t *i_ctx_p)
+{
+ os_ptr op = osp;
+
+ push(1);
+ make_int(op, gs_currentcurvejoin(igs));
+ return 0;
+}
+
/* <adjust.x> <adjust.y> .setfilladjust2 - */
private int
zsetfilladjust2(i_ctx_t *i_ctx_p)
@@ -426,6 +454,7 @@ zdotorientation(i_ctx_t *i_ctx_p)
/* We need to split the table because of the 16-element limit. */
const op_def zgstate1_op_defs[] = {
{"0.currentaccuratecurves", zcurrentaccuratecurves},
+ {"0.currentcurvejoin", zcurrentcurvejoin},
{"0currentdash", zcurrentdash},
{"0.currentdashadapt", zcurrentdashadapt},
{"0.currentdotlength", zcurrentdotlength},
@@ -439,11 +468,12 @@ const op_def zgstate1_op_defs[] = {
{"0grestore", zgrestore},
{"0grestoreall", zgrestoreall},
{"0gsave", zgsave},
- {"0initgraphics", zinitgraphics},
op_def_end(0)
};
const op_def zgstate2_op_defs[] = {
+ {"0initgraphics", zinitgraphics},
{"1.setaccuratecurves", zsetaccuratecurves},
+ {"1.setcurvejoin", zsetcurvejoin},
{"2setdash", zsetdash},
{"1.setdashadapt", zsetdashadapt},
{"2.setdotlength", zsetdotlength},
diff --git a/gs/src/zht1.c b/gs/src/zht1.c
index caa46545a..04917a6b6 100644
--- a/gs/src/zht1.c
+++ b/gs/src/zht1.c
@@ -34,7 +34,7 @@
#include "store.h"
/* Dummy spot function */
-float
+private float
spot_dummy(floatp x, floatp y)
{
return (x + y) / 2;
diff --git a/gs/src/zht2.c b/gs/src/zht2.c
index 57e1714c4..5b4cf338f 100644
--- a/gs/src/zht2.c
+++ b/gs/src/zht2.c
@@ -36,13 +36,19 @@
private int dict_spot_params(P4(const ref *, gs_spot_halftone *,
ref *, ref *));
private int dict_spot_results(P3(i_ctx_t *, ref *, const gs_spot_halftone *));
-private int dict_threshold_params(P3(const ref *,
- gs_threshold_halftone *, ref *));
-private int dict_threshold2_params(P3(const ref *,
- gs_threshold2_halftone *, ref *));
+private int dict_threshold_params(P3(const ref *, gs_threshold_halftone *,
+ ref *));
+private int dict_threshold2_params(P4(const ref *, gs_threshold2_halftone *,
+ ref *, gs_memory_t *));
+
+/* Dummy spot function */
+private float
+spot1_dummy(floatp x, floatp y)
+{
+ return (x + y) / 2;
+}
/* <dict> <dict5> .sethalftone5 - */
-float spot_dummy(P2(floatp, floatp)); /* in zht1.c */
private int sethalftone_finish(P1(i_ctx_t *));
private int sethalftone_cleanup(P1(i_ctx_t *));
private int
@@ -113,8 +119,7 @@ zsethalftone5(i_ctx_t *i_ctx_p)
code = dict_spot_params(pvalue,
&pc->params.spot, sprocs + j,
tprocs + j);
- pc->params.spot.screen.spot_function =
- spot_dummy;
+ pc->params.spot.screen.spot_function = spot1_dummy;
pc->type = ht_type_spot;
break;
case 3:
@@ -124,7 +129,8 @@ zsethalftone5(i_ctx_t *i_ctx_p)
break;
case 7:
code = dict_threshold2_params(pvalue,
- &pc->params.threshold2, tprocs + j);
+ &pc->params.threshold2, tprocs + j,
+ imemory);
pc->type = ht_type_threshold2;
break;
}
@@ -377,7 +383,7 @@ dict_threshold_params(const ref * pdict, gs_threshold_halftone * ptp,
/* BitsPerSample. */
private int
dict_threshold2_params(const ref * pdict, gs_threshold2_halftone * ptp,
- ref * ptproc)
+ ref * ptproc, gs_memory_t *mem)
{
ref *tstring;
int code =
@@ -408,9 +414,9 @@ dict_threshold2_params(const ref * pdict, gs_threshold2_halftone * ptp,
size);
break;
case t_astruct:
- if (gs_object_type(imemory, tstring->value.pstruct) != &st_bytes)
+ if (gs_object_type(mem, tstring->value.pstruct) != &st_bytes)
return_error(e_typecheck);
- size = gs_object_size(imemory, tstring->value.pstruct);
+ size = gs_object_size(mem, tstring->value.pstruct);
gs_bytestring_from_bytes(&ptp->thresholds, r_ptr(tstring, byte),
0, size);
break;
diff --git a/gs/src/zimage.c b/gs/src/zimage.c
index 484836a88..3ad45ce34 100644
--- a/gs/src/zimage.c
+++ b/gs/src/zimage.c
@@ -26,7 +26,6 @@
#include "igstate.h"
#include "ilevel.h"
#include "store.h"
-#include "gschar.h" /* for in_cachedevice */
#include "gscspace.h"
#include "gscssub.h"
#include "gsmatrix.h"
@@ -65,6 +64,46 @@ zimagemask(i_ctx_t *i_ctx_p)
return image_setup(i_ctx_p, op, &image, NULL, 5);
}
+/* Setup for [color|alpha]image. This code isn't used for Level 1, */
+/* but it's simpler to include it here. */
+int
+zimage_multiple(i_ctx_t *i_ctx_p, bool has_alpha)
+{
+ os_ptr op = osp;
+ int spp; /* samples per pixel */
+ int npop = 7;
+ os_ptr procp = op - 2;
+ const gs_color_space *pcs;
+ bool multi = false;
+
+ check_int_leu(*op, 4); /* ncolors */
+ check_type(op[-1], t_boolean); /* multiproc */
+ switch ((spp = (int)(op->value.intval))) {
+ case 1:
+ pcs = gs_current_DeviceGray_space(igs);
+ break;
+ case 3:
+ pcs = gs_current_DeviceRGB_space(igs);
+ goto color;
+ case 4:
+ pcs = gs_current_DeviceCMYK_space(igs);
+color:
+ if (op[-1].value.boolval) { /* planar format */
+ if (has_alpha)
+ ++spp;
+ npop += spp - 1;
+ procp -= spp - 1;
+ multi = true;
+ }
+ break;
+ default:
+ return_error(e_rangecheck);
+ }
+ return zimage_opaque_setup(i_ctx_p, procp, multi,
+ (has_alpha ? gs_image_alpha_last : gs_image_alpha_none),
+ pcs, npop);
+}
+
/* Common setup for [color|alpha]image. */
/* Fills in format, BitsPerComponent, Alpha. */
int
diff --git a/gs/src/zimage2.c b/gs/src/zimage2.c
index b153814b0..d2991662c 100644
--- a/gs/src/zimage2.c
+++ b/gs/src/zimage2.c
@@ -22,7 +22,6 @@
#include "memory_.h"
#include "ghost.h"
#include "oper.h"
-#include "gschar.h" /* for in_cachedevice */
#include "gscolor.h"
#include "gscspace.h"
#include "gscolor2.h"
@@ -147,6 +146,23 @@ zimagemask1(i_ctx_t *i_ctx_p)
true, 1);
}
+/*
+ * Process an image that has no explicit source data. This isn't used by
+ * standard Level 2, but it's a very small procedure and is needed by
+ * both zdps.c and zdpnext.c.
+ */
+int
+process_non_source_image(i_ctx_t *i_ctx_p, const gs_image_common_t * pic,
+ client_name_t cname)
+{
+ gx_image_enum_common_t *pie;
+ int code = gs_image_begin_typed(pic, igs, false /****** WRONG ******/ ,
+ &pie);
+
+ /* We didn't pass any data, so there's nothing to clean up. */
+ return code;
+}
+
/* ------ Initialization procedure ------ */
const op_def zimage2_l2_op_defs[] =
diff --git a/gs/src/ziodev.c b/gs/src/ziodev.c
index f76fe4540..a3bcd5dff 100644
--- a/gs/src/ziodev.c
+++ b/gs/src/ziodev.c
@@ -35,17 +35,6 @@
#include "scanchar.h" /* for char_EOL */
#include "store.h"
-/* Complete the definition of the %os% device. */
-/* The open_file routine is exported for pipes and for %null. */
-int
-iodev_os_open_file(gx_io_device * iodev, const char *fname, uint len,
- const char *file_access, stream ** ps, gs_memory_t * mem)
-{
- return file_open_stream(fname, len, file_access,
- file_default_buffer_size, ps,
- iodev->procs.fopen);
-}
-
/* Define the special devices. */
const char iodev_dtype_stdio[] = "Special";
#define iodev_special(dname, init, open) {\
@@ -160,9 +149,9 @@ s_stdin_read_process(stream_state * st, stream_cursor_read * ignore_pr,
return (ferror(file) ? ERRC : feof(file) ? EOFC : count == wcount ? 1 : 0);
}
-int
-iodev_stdin_open(gx_io_device * iodev, const char *access, stream ** ps,
- gs_memory_t * mem)
+private int
+stdin_open(gx_io_device * iodev, const char *access, stream ** ps,
+ gs_memory_t * mem)
{
i_ctx_t *i_ctx_p = (i_ctx_t *)iodev->state; /* see above */
stream *s;
@@ -193,14 +182,6 @@ iodev_stdin_open(gx_io_device * iodev, const char *access, stream ** ps,
*ps = s;
return 0;
}
-private int
-stdin_open(gx_io_device * iodev, const char *access, stream ** ps,
- gs_memory_t * mem)
-{
- int code = iodev_stdin_open(iodev, access, ps, mem);
-
- return min(code, 0);
-}
/* This is the public routine for getting the stdin stream. */
int
zget_stdin(i_ctx_t *i_ctx_p, stream ** ps)
@@ -217,7 +198,7 @@ zget_stdin(i_ctx_t *i_ctx_p, stream ** ps)
iodev->state = i_ctx_p;
code = (*iodev->procs.open_device)(iodev, "r", ps, imemory_system);
iodev->state = NULL;
- return code;
+ return min(code, 0);
}
/* Test whether a stream is stdin. */
bool
@@ -226,9 +207,9 @@ zis_stdin(const stream *s)
return (s_is_valid(s) && s->procs.process == s_stdin_read_process);
}
-int
-iodev_stdout_open(gx_io_device * iodev, const char *access, stream ** ps,
- gs_memory_t * mem)
+private int
+stdout_open(gx_io_device * iodev, const char *access, stream ** ps,
+ gs_memory_t * mem)
{
i_ctx_t *i_ctx_p = (i_ctx_t *)iodev->state; /* see above */
stream *s;
@@ -253,14 +234,6 @@ iodev_stdout_open(gx_io_device * iodev, const char *access, stream ** ps,
*ps = s;
return 0;
}
-private int
-stdout_open(gx_io_device * iodev, const char *access, stream ** ps,
- gs_memory_t * mem)
-{
- int code = iodev_stdout_open(iodev, access, ps, mem);
-
- return min(code, 0);
-}
/* This is the public routine for getting the stdout stream. */
int
zget_stdout(i_ctx_t *i_ctx_p, stream ** ps)
@@ -277,12 +250,12 @@ zget_stdout(i_ctx_t *i_ctx_p, stream ** ps)
iodev->state = i_ctx_p;
code = (*iodev->procs.open_device)(iodev, "w", ps, imemory_system);
iodev->state = NULL;
- return code;
+ return min(code, 0);
}
-int
-iodev_stderr_open(gx_io_device * iodev, const char *access, stream ** ps,
- gs_memory_t * mem)
+private int
+stderr_open(gx_io_device * iodev, const char *access, stream ** ps,
+ gs_memory_t * mem)
{
i_ctx_t *i_ctx_p = (i_ctx_t *)iodev->state; /* see above */
stream *s;
@@ -307,14 +280,6 @@ iodev_stderr_open(gx_io_device * iodev, const char *access, stream ** ps,
*ps = s;
return 0;
}
-private int
-stderr_open(gx_io_device * iodev, const char *access, stream ** ps,
- gs_memory_t * mem)
-{
- int code = iodev_stderr_open(iodev, access, ps, mem);
-
- return min(code, 0);
-}
/* This is the public routine for getting the stderr stream. */
int
zget_stderr(i_ctx_t *i_ctx_p, stream ** ps)
@@ -331,7 +296,7 @@ zget_stderr(i_ctx_t *i_ctx_p, stream ** ps)
iodev->state = i_ctx_p;
code = (*iodev->procs.open_device)(iodev, "w", ps, imemory_system);
iodev->state = NULL;
- return code;
+ return min(code, 0);
}
/* ------ %lineedit and %statementedit ------ */
@@ -379,6 +344,7 @@ rd:
/* HACK: set %stdin's state so that GNU readline can retrieve it. */
indev->state = i_ctx_p;
code = zreadline_from(ins, buf, mem, &count, &in_eol);
+ buf->size++; /* restore correct size */
indev->state = 0;
switch (code) {
case EOFC:
@@ -462,16 +428,20 @@ private int
lineedit_open(gx_io_device * iodev, const char *access, stream ** ps,
gs_memory_t * mem)
{
- return line_collect(iodev, access, ps, mem,
- LINEEDIT_BUF_SIZE, false);
+ int code = line_collect(iodev, access, ps, mem,
+ LINEEDIT_BUF_SIZE, false);
+
+ return (code < 0 ? code : 1);
}
private int
statementedit_open(gx_io_device * iodev, const char *access, stream ** ps,
gs_memory_t * mem)
{
- return line_collect(iodev, access, ps, mem,
- STATEMENTEDIT_BUF_SIZE, true);
+ int code = line_collect(iodev, access, ps, mem,
+ STATEMENTEDIT_BUF_SIZE, true);
+
+ return (code < 0 ? code : 1);
}
/* ------ Initialization procedure ------ */
diff --git a/gs/src/ziodev2.c b/gs/src/ziodev2.c
index 10fc6fc53..4b56b51e3 100644
--- a/gs/src/ziodev2.c
+++ b/gs/src/ziodev2.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1994, 1996, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1993, 1994, 1996, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -54,7 +54,7 @@ null_open(gx_io_device * iodev, const char *access, stream ** ps,
return file_open_stream(gp_null_file_name,
strlen(gp_null_file_name),
access, 256 /* arbitrary */ , ps,
- iodev->procs.fopen);
+ iodev->procs.fopen, mem);
}
/* ------ %ram% ------ */
@@ -88,7 +88,7 @@ zgetdevparams(i_ctx_t *i_ctx_p)
iodev = gs_findiodevice(op->value.bytes, r_size(op));
if (iodev == 0)
return_error(e_undefinedfilename);
- stack_param_list_write(&list, &o_stack, NULL);
+ stack_param_list_write(&list, &o_stack, NULL, iimemory);
if ((code = gs_getdevparams(iodev, plist)) < 0) {
ref_stack_pop(&o_stack, list.count * 2);
return code;
@@ -113,7 +113,7 @@ zputdevparams(i_ctx_t *i_ctx_p)
iodev = gs_findiodevice(op->value.bytes, r_size(op));
if (iodev == 0)
return_error(e_undefinedfilename);
- code = stack_param_list_read(&list, &o_stack, 1, NULL, false);
+ code = stack_param_list_read(&list, &o_stack, 1, NULL, false, iimemory);
if (code < 0)
return code;
code = dict_read_password(&system_params_password, systemdict,
diff --git a/gs/src/zlib.mak b/gs/src/zlib.mak
index fb73f3186..99854a678 100644
--- a/gs/src/zlib.mak
+++ b/gs/src/zlib.mak
@@ -45,13 +45,11 @@ ZGEN=$(ZGENDIR)$(D)
ZOBJ=$(ZOBJDIR)$(D)
ZO_=$(O_)$(ZOBJ)
-# Because the Watcom C runtime (and compiler) substitute space for = in
-# command lines (!), we can't have a -D whose argument begins with -,
-# since this will cause the argument to be interpreted as a switch (!!).
-# We need D_, _D_, and _D because the OpenVMS and Watcom compilers use
-# different syntax.
+# We need D_, _D_, and _D because the OpenVMS compiler uses different
+# syntax from other compilers.
# ZI_ and ZF_ are defined in gs.mak.
-ZCC=$(CC_) $(I_)$(ZI_)$(_I) $(ZF_) $(D_)verbose$(_D_)0-1$(_D)
+ZCCFLAGS=$(I_)$(ZI_)$(_I) $(ZF_) $(D_)verbose$(_D_)-1$(_D)
+ZCC=$(CC_) $(ZCCFLAGS)
# Define the name of this makefile.
ZLIB_MAK=$(GLSRC)zlib.mak
@@ -110,8 +108,10 @@ $(ZGEN)crc32_1.dev : $(TOP_MAKEFILES) $(ZLIB_MAK) $(ECHOGS_XE)
$(ZGEN)crc32_0.dev : $(ZLIB_MAK) $(ECHOGS_XE) $(ZOBJ)crc32.$(OBJ)
$(SETMOD) $(ZGEN)crc32_0 $(ZOBJ)crc32.$(OBJ)
+# We have to compile crc32 without warnings, because it defines 32-bit
+# constants that produces gcc warnings with -Wtraditional.
$(ZOBJ)crc32.$(OBJ) : $(ZSRC)crc32.c $(ZDEP)
- $(ZCC) $(ZO_)crc32.$(OBJ) $(C_) $(ZSRC)crc32.c
+ $(CC_NO_WARN) $(ZCCFLAGS) $(ZO_)crc32.$(OBJ) $(C_) $(ZSRC)crc32.c
# Decoding (decompression) code.
diff --git a/gs/src/zmath.c b/gs/src/zmath.c
index 4962ff88e..73c9c8d0a 100644
--- a/gs/src/zmath.c
+++ b/gs/src/zmath.c
@@ -25,6 +25,11 @@
#include "store.h"
/*
+ * Many of the procedures in this file are public only so they can be
+ * called from the FunctionType 4 interpreter (zfunc4.c).
+ */
+
+/*
* Define the current state of random number generator for operators. We
* have to implement this ourselves because the Unix rand doesn't provide
* anything equivalent to rrand. Note that the value always lies in the
@@ -37,17 +42,13 @@
#define zrand_state (i_ctx_p->rand_state)
/* Initialize the random number generator. */
-void
-zrand_state_init(long *pstate)
-{
- *pstate = 1;
-}
+const long rand_state_initial = 1;
/****** NOTE: none of these operators currently ******/
/****** check for floating over- or underflow. ******/
/* <num> sqrt <real> */
-private int
+int
zsqrt(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
@@ -93,7 +94,7 @@ zarcsin(i_ctx_t *i_ctx_p)
}
/* <num> <denom> atan <real> */
-private int
+int
zatan(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
@@ -118,7 +119,7 @@ zatan(i_ctx_t *i_ctx_p)
}
/* <num> cos <real> */
-private int
+int
zcos(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
@@ -132,7 +133,7 @@ zcos(i_ctx_t *i_ctx_p)
}
/* <num> sin <real> */
-private int
+int
zsin(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
@@ -146,7 +147,7 @@ zsin(i_ctx_t *i_ctx_p)
}
/* <base> <exponent> exp <real> */
-private int
+int
zexp(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
@@ -168,7 +169,7 @@ zexp(i_ctx_t *i_ctx_p)
}
/* <posnum> ln <real> */
-private int
+int
zln(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
@@ -184,7 +185,7 @@ zln(i_ctx_t *i_ctx_p)
}
/* <posnum> log <real> */
-private int
+int
zlog(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
diff --git a/gs/src/zmedia2.c b/gs/src/zmedia2.c
index 17be5db45..501574840 100644
--- a/gs/src/zmedia2.c
+++ b/gs/src/zmedia2.c
@@ -277,11 +277,13 @@ zmatch_page_size(const ref * pvreq, const ref * pvmed,
int policy, int orient, bool roll,
float *best_mismatch, gs_matrix * pmat, gs_point * pmsize)
{
- uint nm;
+ uint nr, nm;
check_array(*pvreq);
+ nr = r_size(pvreq);
check_array(*pvmed);
- if (!(r_size(pvreq) == 2 && ((nm = r_size(pvmed)) == 2 || nm == 4)))
+ nm = r_size(pvmed);
+ if (!((nm == 2 || nm == 4) && (nr == 2 || nr == nm)))
return_error(e_rangecheck);
{
ref rv[6];
diff --git a/gs/src/zmisc.c b/gs/src/zmisc.c
index 2b9a59679..93984f7a4 100644
--- a/gs/src/zmisc.c
+++ b/gs/src/zmisc.c
@@ -70,15 +70,16 @@ zbind(i_ctx_t *i_ctx_p)
* Here are the invariants for the following loop:
* `depth' elements have been pushed on the ostack;
* For i < depth, p = ref_stack_index(&o_stack, i):
- * *p is an array (or packedarray) ref. */
+ * *p is an array (or packedarray) ref.
+ */
while (depth) {
while (r_size(bsp)) {
- ref *tp = bsp->value.refs;
+ ref_packed *const tpp = (ref_packed *)bsp->value.packed; /* break const */
r_dec_size(bsp, 1);
- if (r_is_packed(tp)) {
+ if (r_is_packed(tpp)) {
/* Check for a packed executable name */
- ushort elt = *(ushort *) tp;
+ ushort elt = *tpp;
if (r_packed_is_exec_name(&elt)) {
ref nref;
@@ -94,15 +95,16 @@ zbind(i_ctx_t *i_ctx_p)
* Always save the change, since this can only
* happen once.
*/
- ref_do_save(bsp, tp, "bind");
- *(ushort *) tp =
- pt_tag(pt_executable_operator) +
+ ref_do_save(bsp, tpp, "bind");
+ *tpp = pt_tag(pt_executable_operator) +
op_index(pvalue);
}
}
- bsp->value.refs = (ref *) ((ref_packed *) tp + 1);
- } else
- switch (bsp->value.refs++, r_type(tp)) {
+ bsp->value.packed = tpp + 1;
+ } else {
+ ref *const tp = bsp->value.refs++;
+
+ switch (r_type(tp)) {
case t_name: /* bind the name if an operator */
if (r_has_attr(tp, a_executable)) {
ref *pvalue;
@@ -142,6 +144,7 @@ zbind(i_ctx_t *i_ctx_p)
depth++;
}
}
+ }
}
bsp--;
depth--;
diff --git a/gs/src/zpacked.c b/gs/src/zpacked.c
index 117e1db39..b3e273f2f 100644
--- a/gs/src/zpacked.c
+++ b/gs/src/zpacked.c
@@ -56,7 +56,7 @@ zpackedarray(i_ctx_t *i_ctx_p)
return_error(e_rangecheck);
osp--;
code = make_packed_array(&parr, &o_stack, (uint) op->value.intval,
- "packedarray");
+ idmemory, "packedarray");
osp++;
if (code >= 0)
*osp = parr;
@@ -81,9 +81,10 @@ zsetpacking(i_ctx_t *i_ctx_p)
/* Make a packed array. See the comment in packed.h about */
/* ensuring that refs in mixed arrays are properly aligned. */
+#undef idmemory /****** NOTA BENE ******/
int
make_packed_array(ref * parr, ref_stack_t * pstack, uint size,
- client_name_t cname)
+ gs_dual_memory_t *idmemory, client_name_t cname)
{
uint i;
const ref *pref;
@@ -92,7 +93,8 @@ make_packed_array(ref * parr, ref_stack_t * pstack, uint size,
ref_packed *pdest;
ref_packed *pshort; /* points to start of */
/* last run of short elements */
- uint space = ialloc_space(idmemory);
+ gs_ref_memory_t *imem = idmemory->current;
+ uint space = imemory_space(imem);
int skip = 0, pad;
ref rtemp;
int code;
@@ -154,8 +156,8 @@ make_packed_array(ref * parr, ref_stack_t * pstack, uint size,
/* Now we can allocate the array. */
- code = ialloc_ref_array(&rtemp, 0, (idest + pad) / packed_per_ref,
- cname);
+ code = gs_alloc_ref_array(imem, &rtemp, 0, (idest + pad) / packed_per_ref,
+ cname);
if (code < 0)
return code;
pbody = (ref_packed *) rtemp.value.refs;
diff --git a/gs/src/zpath1.c b/gs/src/zpath1.c
index 4c10a29b0..ce2fc725a 100644
--- a/gs/src/zpath1.c
+++ b/gs/src/zpath1.c
@@ -21,6 +21,7 @@
#include "memory_.h"
#include "ghost.h"
#include "oper.h"
+#include "oparc.h" /* for prototypes */
#include "estack.h" /* for pathforall */
#include "ialloc.h"
#include "igstate.h"
diff --git a/gs/src/zpcolor.c b/gs/src/zpcolor.c
index a382f4ba1..7c312b044 100644
--- a/gs/src/zpcolor.c
+++ b/gs/src/zpcolor.c
@@ -64,10 +64,10 @@ zpcolor_init(i_ctx_t *i_ctx_p)
/* Create an interpreter pattern structure. */
int
-int_pattern_alloc(int_pattern **ppdata, const ref *op)
+int_pattern_alloc(int_pattern **ppdata, const ref *op, gs_memory_t *mem)
{
int_pattern *pdata =
- ialloc_struct(int_pattern, &st_int_pattern, "int_pattern");
+ gs_alloc_struct(mem, int_pattern, &st_int_pattern, "int_pattern");
if (pdata == 0)
return_error(e_VMerror);
@@ -109,7 +109,7 @@ zbuildpattern1(i_ctx_t *i_ctx_p)
template.BBox.q.x = BBox[2];
template.BBox.q.y = BBox[3];
template.PaintProc = zPaintProc;
- code = int_pattern_alloc(&pdata, op1);
+ code = int_pattern_alloc(&pdata, op1, imemory);
if (code < 0)
return code;
template.client_data = pdata;
diff --git a/gs/src/zrelbit.c b/gs/src/zrelbit.c
index bea34275b..f6fd429fc 100644
--- a/gs/src/zrelbit.c
+++ b/gs/src/zrelbit.c
@@ -24,6 +24,11 @@
#include "idict.h"
#include "store.h"
+/*
+ * Many of the procedures in this file are public only so they can be
+ * called from the FunctionType 4 interpreter (zfunc4.c).
+ */
+
/* ------ Standard operators ------ */
/* Define the type test for eq and its relatives. */
@@ -40,7 +45,7 @@
private int obj_le(P2(os_ptr, os_ptr));
/* <obj1> <obj2> eq <bool> */
-private int
+int
zeq(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
@@ -52,7 +57,7 @@ zeq(i_ctx_t *i_ctx_p)
}
/* <obj1> <obj2> ne <bool> */
-private int
+int
zne(i_ctx_t *i_ctx_p)
{ /* We'll just be lazy and use eq. */
int code = zeq(i_ctx_p);
@@ -64,7 +69,7 @@ zne(i_ctx_t *i_ctx_p)
/* <num1> <num2> ge <bool> */
/* <str1> <str2> ge <bool> */
-private int
+int
zge(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
@@ -79,7 +84,7 @@ zge(i_ctx_t *i_ctx_p)
/* <num1> <num2> gt <bool> */
/* <str1> <str2> gt <bool> */
-private int
+int
zgt(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
@@ -94,7 +99,7 @@ zgt(i_ctx_t *i_ctx_p)
/* <num1> <num2> le <bool> */
/* <str1> <str2> le <bool> */
-private int
+int
zle(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
@@ -109,7 +114,7 @@ zle(i_ctx_t *i_ctx_p)
/* <num1> <num2> lt <bool> */
/* <str1> <str2> lt <bool> */
-private int
+int
zlt(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
@@ -158,7 +163,7 @@ zmin(i_ctx_t *i_ctx_p)
/* <bool1> <bool2> and <bool> */
/* <int1> <int2> and <int> */
-private int
+int
zand(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
@@ -181,7 +186,7 @@ zand(i_ctx_t *i_ctx_p)
/* <bool> not <bool> */
/* <int> not <int> */
-private int
+int
znot(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
@@ -201,7 +206,7 @@ znot(i_ctx_t *i_ctx_p)
/* <bool1> <bool2> or <bool> */
/* <int1> <int2> or <int> */
-private int
+int
zor(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
@@ -224,7 +229,7 @@ zor(i_ctx_t *i_ctx_p)
/* <bool1> <bool2> xor <bool> */
/* <int1> <int2> xor <int> */
-private int
+int
zxor(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
@@ -246,7 +251,7 @@ zxor(i_ctx_t *i_ctx_p)
}
/* <int> <shift> bitshift <int> */
-private int
+int
zbitshift(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
diff --git a/gs/src/zshade.c b/gs/src/zshade.c
index b529e8fc5..3b39400a5 100644
--- a/gs/src/zshade.c
+++ b/gs/src/zshade.c
@@ -105,7 +105,7 @@ zbuildshadingpattern(i_ctx_t *i_ctx_p)
if ((code = read_matrix(op - 1, &mat)) < 0 ||
(code = dict_uid_param(op2, &template.uid, 1, imemory, i_ctx_p)) != 1 ||
(code = shading_param(op, &template.Shading)) < 0 ||
- (code = int_pattern_alloc(&pdata, op2)) < 0
+ (code = int_pattern_alloc(&pdata, op2, imemory)) < 0
)
return_error((code < 0 ? code : e_rangecheck));
template.client_data = pdata;
@@ -144,9 +144,9 @@ shading_param(const_os_ptr op, const gs_shading_t ** ppsh)
extern_st(st_color_space);
-typedef int (*build_shading_proc_t)(P3(const ref *op,
- const gs_shading_params_t *params,
- gs_shading_t **ppsh));
+typedef int (*build_shading_proc_t)
+ (P4(const ref *op, const gs_shading_params_t *params,
+ gs_shading_t **ppsh, gs_memory_t *mem));
/* Operators */
@@ -210,23 +210,24 @@ build_shading(i_ctx_t *i_ctx_p, build_shading_proc_t proc)
if (code < 0)
goto fail;
/* Finish building the shading. */
- code = (*proc) (op, &params, &psh);
+ code = (*proc)(op, &params, &psh, imemory);
if (code < 0)
goto fail;
make_istruct_new(op, 0, psh);
return code;
fail:
- ifree_object(params.Background, "Background");
+ gs_free_object(imemory, params.Background, "Background");
if (params.ColorSpace) {
gs_cspace_release(params.ColorSpace);
- ifree_object(params.ColorSpace, "ColorSpace");
+ gs_free_object(imemory, params.ColorSpace, "ColorSpace");
}
return (code < 0 ? code : gs_note_error(e_rangecheck));
}
/* Collect a Function value. */
private int
-build_shading_function(const ref * op, gs_function_t ** ppfn, int num_inputs)
+build_shading_function(const ref * op, gs_function_t ** ppfn, int num_inputs,
+ gs_memory_t *mem)
{
ref *pFunction;
@@ -243,14 +244,14 @@ build_shading_function(const ref * op, gs_function_t ** ppfn, int num_inputs)
check_read(*pFunction);
if (size == 0)
return_error(e_rangecheck);
- code = ialloc_function_array(size, &Functions);
+ code = alloc_function_array(size, &Functions, mem);
if (code < 0)
return code;
for (i = 0; i < size; ++i) {
ref rsubfn;
array_get(op, (long)i, &rsubfn);
- code = fn_build_function(&rsubfn, &Functions[i]);
+ code = fn_build_function(&rsubfn, &Functions[i], mem);
if (code < 0)
break;
}
@@ -260,12 +261,12 @@ build_shading_function(const ref * op, gs_function_t ** ppfn, int num_inputs)
params.Range = 0;
params.Functions = (const gs_function_t * const *)Functions;
if (code >= 0)
- code = gs_function_AdOt_init(ppfn, &params, imemory);
+ code = gs_function_AdOt_init(ppfn, &params, mem);
if (code < 0)
- gs_function_AdOt_free_params(&params, imemory);
+ gs_function_AdOt_free_params(&params, mem);
return code;
} else
- return fn_build_function(pFunction, ppfn);
+ return fn_build_function(pFunction, ppfn, mem);
}
/* ------ Build shadings ------ */
@@ -273,7 +274,7 @@ build_shading_function(const ref * op, gs_function_t ** ppfn, int num_inputs)
/* Build a ShadingType 1 (Function-based) shading. */
private int
build_shading_1(const ref * op, const gs_shading_params_t * pcommon,
- gs_shading_t ** ppsh)
+ gs_shading_t ** ppsh, gs_memory_t *mem)
{
gs_shading_Fb_params_t params;
int code;
@@ -285,10 +286,10 @@ build_shading_1(const ref * op, const gs_shading_params_t * pcommon,
if ((code = dict_float_array_param(op, "Domain", 4, params.Domain,
default_Domain)) != 4 ||
(code = dict_matrix_param(op, "Matrix", &params.Matrix)) < 0 ||
- (code = build_shading_function(op, &params.Function, 2)) < 0 ||
- (code = gs_shading_Fb_init(ppsh, &params, imemory)) < 0
+ (code = build_shading_function(op, &params.Function, 2, mem)) < 0 ||
+ (code = gs_shading_Fb_init(ppsh, &params, mem)) < 0
) {
- ifree_object(params.Function, "Function");
+ gs_free_object(mem, params.Function, "Function");
return (code < 0 ? code : gs_note_error(e_rangecheck));
}
return 0;
@@ -303,7 +304,8 @@ zbuildshading1(i_ctx_t *i_ctx_p)
/* Collect parameters for an Axial or Radial shading. */
private int
build_directional_shading(const ref * op, float *Coords, int num_Coords,
- float Domain[2], gs_function_t ** pFunction, bool Extend[2])
+ float Domain[2], gs_function_t ** pFunction,
+ bool Extend[2], gs_memory_t *mem)
{
int code =
dict_float_array_param(op, "Coords", num_Coords, Coords, NULL);
@@ -314,7 +316,7 @@ build_directional_shading(const ref * op, float *Coords, int num_Coords,
if (code != num_Coords ||
(code = dict_float_array_param(op, "Domain", 2, Domain,
default_Domain)) != 2 ||
- (code = build_shading_function(op, pFunction, 1)) < 0
+ (code = build_shading_function(op, pFunction, 1, mem)) < 0
)
return (code < 0 ? code : gs_note_error(e_rangecheck));
if (dict_find_string(op, "Extend", &pExtend) <= 0)
@@ -338,7 +340,7 @@ build_directional_shading(const ref * op, float *Coords, int num_Coords,
/* Build a ShadingType 2 (Axial) shading. */
private int
build_shading_2(const ref * op, const gs_shading_params_t * pcommon,
- gs_shading_t ** ppsh)
+ gs_shading_t ** ppsh, gs_memory_t *mem)
{
gs_shading_A_params_t params;
int code;
@@ -346,10 +348,10 @@ build_shading_2(const ref * op, const gs_shading_params_t * pcommon,
*(gs_shading_params_t *)&params = *pcommon;
if ((code = build_directional_shading(op, params.Coords, 4,
params.Domain, &params.Function,
- params.Extend)) < 0 ||
- (code = gs_shading_A_init(ppsh, &params, imemory)) < 0
+ params.Extend, mem)) < 0 ||
+ (code = gs_shading_A_init(ppsh, &params, mem)) < 0
) {
- ifree_object(params.Function, "Function");
+ gs_free_object(mem, params.Function, "Function");
}
return code;
}
@@ -363,7 +365,7 @@ zbuildshading2(i_ctx_t *i_ctx_p)
/* Build a ShadingType 3 (Radial) shading. */
private int
build_shading_3(const ref * op, const gs_shading_params_t * pcommon,
- gs_shading_t ** ppsh)
+ gs_shading_t ** ppsh, gs_memory_t *mem)
{
gs_shading_R_params_t params;
int code;
@@ -371,10 +373,10 @@ build_shading_3(const ref * op, const gs_shading_params_t * pcommon,
*(gs_shading_params_t *)&params = *pcommon;
if ((code = build_directional_shading(op, params.Coords, 6,
params.Domain, &params.Function,
- params.Extend)) < 0 ||
- (code = gs_shading_R_init(ppsh, &params, imemory)) < 0
+ params.Extend, mem)) < 0 ||
+ (code = gs_shading_R_init(ppsh, &params, mem)) < 0
) {
- ifree_object(params.Function, "Function");
+ gs_free_object(mem, params.Function, "Function");
}
return code;
}
@@ -388,7 +390,8 @@ zbuildshading3(i_ctx_t *i_ctx_p)
/* Collect parameters for a mesh shading. */
private int
build_mesh_shading(const ref * op, gs_shading_mesh_params_t * params,
- float **pDecode, gs_function_t ** pFunction)
+ float **pDecode, gs_function_t ** pFunction,
+ gs_memory_t *mem)
{
int code;
ref *pDataSource;
@@ -400,15 +403,15 @@ build_mesh_shading(const ref * op, gs_shading_mesh_params_t * params,
if (r_is_array(pDataSource)) {
uint size = r_size(pDataSource);
float *data =
- (float *)ialloc_byte_array(size, sizeof(float),
- "build_mesh_shading");
+ (float *)gs_alloc_byte_array(mem, size, sizeof(float),
+ "build_mesh_shading");
int code;
if (data == 0)
return_error(e_VMerror);
code = float_params(pDataSource->value.refs + size - 1, size, data);
if (code < 0) {
- ifree_object(data, "build_mesh_shading");
+ gs_free_object(mem, data, "build_mesh_shading");
return code;
}
data_source_init_floats(&params->DataSource, data, size);
@@ -444,22 +447,22 @@ build_mesh_shading(const ref * op, gs_shading_mesh_params_t * params,
&params->BitsPerComponent)) < 0
)
return code;
- *pDecode = (float *)ialloc_byte_array(num_decode, sizeof(float),
- "build_mesh_shading");
-
+ *pDecode = (float *)
+ gs_alloc_byte_array(mem, num_decode, sizeof(float),
+ "build_mesh_shading");
if (*pDecode == 0)
return_error(e_VMerror);
code = dict_float_array_param(op, "Decode", num_decode, *pDecode,
NULL);
if (code != num_decode) {
- ifree_object(*pDecode, "build_mesh_shading");
+ gs_free_object(mem, *pDecode, "build_mesh_shading");
*pDecode = 0;
return (code < 0 ? code : gs_note_error(e_rangecheck));
}
}
- code = build_shading_function(op, pFunction, 1);
+ code = build_shading_function(op, pFunction, 1, mem);
if (code < 0) {
- ifree_object(*pDecode, "build_mesh_shading");
+ gs_free_object(mem, *pDecode, "build_mesh_shading");
*pDecode = 0;
}
return code;
@@ -481,7 +484,7 @@ flag_bits_param(const ref * op, const gs_shading_mesh_params_t * params,
/* Build a ShadingType 4 (Free-form Gouraud triangle mesh) shading. */
private int
build_shading_4(const ref * op, const gs_shading_params_t * pcommon,
- gs_shading_t ** ppsh)
+ gs_shading_t ** ppsh, gs_memory_t *mem)
{
gs_shading_FfGt_params_t params;
int code;
@@ -489,13 +492,13 @@ build_shading_4(const ref * op, const gs_shading_params_t * pcommon,
*(gs_shading_params_t *)&params = *pcommon;
if ((code =
build_mesh_shading(op, (gs_shading_mesh_params_t *)&params,
- &params.Decode, &params.Function)) < 0 ||
+ &params.Decode, &params.Function, mem)) < 0 ||
(code = flag_bits_param(op, (gs_shading_mesh_params_t *)&params,
&params.BitsPerFlag)) < 0 ||
- (code = gs_shading_FfGt_init(ppsh, &params, imemory)) < 0
+ (code = gs_shading_FfGt_init(ppsh, &params, mem)) < 0
) {
- ifree_object(params.Function, "Function");
- ifree_object(params.Decode, "Decode");
+ gs_free_object(mem, params.Function, "Function");
+ gs_free_object(mem, params.Decode, "Decode");
}
return code;
}
@@ -509,7 +512,7 @@ zbuildshading4(i_ctx_t *i_ctx_p)
/* Build a ShadingType 5 (Lattice-form Gouraud triangle mesh) shading. */
private int
build_shading_5(const ref * op, const gs_shading_params_t * pcommon,
- gs_shading_t ** ppsh)
+ gs_shading_t ** ppsh, gs_memory_t *mem)
{
gs_shading_LfGt_params_t params;
int code;
@@ -517,13 +520,13 @@ build_shading_5(const ref * op, const gs_shading_params_t * pcommon,
*(gs_shading_params_t *)&params = *pcommon;
if ((code =
build_mesh_shading(op, (gs_shading_mesh_params_t *)&params,
- &params.Decode, &params.Function)) < 0 ||
+ &params.Decode, &params.Function, mem)) < 0 ||
(code = dict_int_param(op, "VerticesPerRow", 2, max_int, 0,
&params.VerticesPerRow)) < 0 ||
- (code = gs_shading_LfGt_init(ppsh, &params, imemory)) < 0
+ (code = gs_shading_LfGt_init(ppsh, &params, mem)) < 0
) {
- ifree_object(params.Function, "Function");
- ifree_object(params.Decode, "Decode");
+ gs_free_object(mem, params.Function, "Function");
+ gs_free_object(mem, params.Decode, "Decode");
}
return code;
}
@@ -537,7 +540,7 @@ zbuildshading5(i_ctx_t *i_ctx_p)
/* Build a ShadingType 6 (Coons patch mesh) shading. */
private int
build_shading_6(const ref * op, const gs_shading_params_t * pcommon,
- gs_shading_t ** ppsh)
+ gs_shading_t ** ppsh, gs_memory_t *mem)
{
gs_shading_Cp_params_t params;
int code;
@@ -545,13 +548,13 @@ build_shading_6(const ref * op, const gs_shading_params_t * pcommon,
*(gs_shading_params_t *)&params = *pcommon;
if ((code =
build_mesh_shading(op, (gs_shading_mesh_params_t *)&params,
- &params.Decode, &params.Function)) < 0 ||
+ &params.Decode, &params.Function, mem)) < 0 ||
(code = flag_bits_param(op, (gs_shading_mesh_params_t *)&params,
&params.BitsPerFlag)) < 0 ||
- (code = gs_shading_Cp_init(ppsh, &params, imemory)) < 0
+ (code = gs_shading_Cp_init(ppsh, &params, mem)) < 0
) {
- ifree_object(params.Function, "Function");
- ifree_object(params.Decode, "Decode");
+ gs_free_object(mem, params.Function, "Function");
+ gs_free_object(mem, params.Decode, "Decode");
}
return code;
}
@@ -565,7 +568,7 @@ zbuildshading6(i_ctx_t *i_ctx_p)
/* Build a ShadingType 7 (Tensor product patch mesh) shading. */
private int
build_shading_7(const ref * op, const gs_shading_params_t * pcommon,
- gs_shading_t ** ppsh)
+ gs_shading_t ** ppsh, gs_memory_t *mem)
{
gs_shading_Tpp_params_t params;
int code;
@@ -573,13 +576,13 @@ build_shading_7(const ref * op, const gs_shading_params_t * pcommon,
*(gs_shading_params_t *)&params = *pcommon;
if ((code =
build_mesh_shading(op, (gs_shading_mesh_params_t *)&params,
- &params.Decode, &params.Function)) < 0 ||
+ &params.Decode, &params.Function, mem)) < 0 ||
(code = flag_bits_param(op, (gs_shading_mesh_params_t *)&params,
&params.BitsPerFlag)) < 0 ||
- (code = gs_shading_Tpp_init(ppsh, &params, imemory)) < 0
+ (code = gs_shading_Tpp_init(ppsh, &params, mem)) < 0
) {
- ifree_object(params.Function, "Function");
- ifree_object(params.Decode, "Decode");
+ gs_free_object(mem, params.Function, "Function");
+ gs_free_object(mem, params.Decode, "Decode");
}
return code;
}
diff --git a/gs/src/ztrap.c b/gs/src/ztrap.c
index d8df57572..551828e8a 100644
--- a/gs/src/ztrap.c
+++ b/gs/src/ztrap.c
@@ -37,7 +37,7 @@ zsettrapparams(i_ctx_t *i_ctx_p)
int code;
check_type(*op, t_dictionary);
- code = dict_param_list_read(&list, op, NULL, false);
+ code = dict_param_list_read(&list, op, NULL, false, iimemory);
if (code < 0)
return code;
code = gs_settrapparams(&i_trap_params, (gs_param_list *) & list);
diff --git a/gs/src/ztype.c b/gs/src/ztype.c
index 983faf926..0c619ad81 100644
--- a/gs/src/ztype.c
+++ b/gs/src/ztype.c
@@ -35,6 +35,11 @@
#include "dstack.h" /* for dict_set_top */
#include "store.h"
+/*
+ * Some of the procedures in this file are public only so they can be
+ * called from the FunctionType 4 interpreter (zfunc4.c).
+ */
+
/* Forward references */
private int access_check(P3(i_ctx_t *, int, bool));
private int convert_to_string(P2(os_ptr, os_ptr));
@@ -231,7 +236,7 @@ zwcheck(i_ctx_t *i_ctx_p)
/* <num> cvi <int> */
/* <string> cvi <int> */
-private int
+int
zcvi(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
@@ -290,7 +295,7 @@ zcvn(i_ctx_t *i_ctx_p)
/* <num> cvr <real> */
/* <string> cvr <real> */
-private int
+int
zcvr(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
diff --git a/gs/src/zupath.c b/gs/src/zupath.c
index 0a58f0e31..acc7074d0 100644
--- a/gs/src/zupath.c
+++ b/gs/src/zupath.c
@@ -20,6 +20,7 @@
/* Operators related to user paths */
#include "ghost.h"
#include "oper.h"
+#include "oparc.h"
#include "idict.h"
#include "dstack.h"
#include "igstate.h"
@@ -284,9 +285,6 @@ static const byte up_nargs[UPATH_MAX_OP + 1] = {
/* Declare operator procedures not declared in opextern.h. */
int zsetbbox(P1(i_ctx_t *));
-int zarc(P1(i_ctx_t *));
-int zarcn(P1(i_ctx_t *));
-int zarct(P1(i_ctx_t *));
private int zucache(P1(i_ctx_t *));
#undef zp
@@ -402,7 +400,7 @@ zustrokepath(i_ctx_t *i_ctx_p)
/* <with_ucache> upath <userpath> */
/* We do all the work in a procedure that is also used to construct */
/* the UnpaintedPath user path for ImageType 2 images. */
-int make_upath(P4(ref * rupath, gs_state * pgs, gx_path * ppath,
+int make_upath(P5(i_ctx_t *i_ctx_p, ref *rupath, gs_state *pgs, gx_path *ppath,
bool with_ucache));
private int
zupath(i_ctx_t *i_ctx_p)
@@ -410,10 +408,11 @@ zupath(i_ctx_t *i_ctx_p)
os_ptr op = osp;
check_type(*op, t_boolean);
- return make_upath(op, igs, igs->path, op->value.boolval);
+ return make_upath(i_ctx_p, op, igs, igs->path, op->value.boolval);
}
int
-make_upath(ref * rupath, gs_state * pgs, gx_path * ppath, bool with_ucache)
+make_upath(i_ctx_t *i_ctx_p, ref *rupath, gs_state *pgs, gx_path *ppath,
+ bool with_ucache)
{
int size = (with_ucache ? 6 : 5);
gs_path_enum penum;
diff --git a/gs/src/zusparam.c b/gs/src/zusparam.c
index 76f026809..dabd961c3 100644
--- a/gs/src/zusparam.c
+++ b/gs/src/zusparam.c
@@ -36,15 +36,12 @@
#include "dstack.h"
#include "iname.h"
#include "iutil2.h"
+#include "ivmem2.h"
#include "store.h"
/* The (global) font directory */
extern gs_font_dir *ifont_dir; /* in zfont.c */
-/* Import the GC parameters from zvmem2.c. */
-extern int set_vm_reclaim(P2(i_ctx_t *, long));
-extern int set_vm_threshold(P2(i_ctx_t *, long));
-
/* Define an individual user or system parameter. */
/* Eventually this will be made public. */
#define param_def_common\
@@ -107,7 +104,7 @@ zcheckpassword(i_ctx_t *i_ctx_p)
if (code < 0)
return code;
params[1] = *op;
- array_param_list_read(&list, params, 2, NULL, false);
+ array_param_list_read(&list, params, 2, NULL, false, iimemory);
if (dict_read_password(&pass, systemdict, "StartJobPassword") >= 0 &&
param_check_password(plist, &pass) == 0
)
@@ -231,7 +228,7 @@ zsetsystemparams(i_ctx_t *i_ctx_p)
password pass;
check_type(*op, t_dictionary);
- code = dict_param_list_read(&list, op, NULL, false);
+ code = dict_param_list_read(&list, op, NULL, false, iimemory);
if (code < 0)
return code;
code = dict_read_password(&pass, systemdict, "SystemParamsPassword");
@@ -470,7 +467,7 @@ set_user_params(i_ctx_t *i_ctx_p, const ref *paramdict)
int code;
check_type(*paramdict, t_dictionary);
- code = dict_param_list_read(&list, paramdict, NULL, false);
+ code = dict_param_list_read(&list, paramdict, NULL, false, iimemory);
if (code < 0)
return code;
code = setparams(i_ctx_p, (gs_param_list *)&list, &user_param_set);
@@ -582,7 +579,7 @@ current_param_list(i_ctx_t *i_ctx_p, const param_set * pset,
gs_param_list *const plist = (gs_param_list *)&list;
int i;
- stack_param_list_write(&list, &o_stack, NULL);
+ stack_param_list_write(&list, &o_stack, NULL, iimemory);
for (i = 0; i < pset->long_count; i++) {
const char *pname = pset->long_defs[i].pname;
diff --git a/gs/src/zvmem.c b/gs/src/zvmem.c
index 82d6e0ded..b7a84e3a3 100644
--- a/gs/src/zvmem.c
+++ b/gs/src/zvmem.c
@@ -41,9 +41,6 @@ private bool I_VALIDATE_AFTER_SAVE = true;
private bool I_VALIDATE_BEFORE_RESTORE = true;
private bool I_VALIDATE_AFTER_RESTORE = true;
-/* Make an invalid file object. */
-extern void make_invalid_file(P1(ref *)); /* in zfile.c */
-
/* 'Save' structure */
typedef struct vm_save_s vm_save_t;
struct vm_save_s {
@@ -105,7 +102,7 @@ zsave(i_ctx_t *i_ctx_p)
}
/* <save> restore - */
-private int restore_check_operand(P2(os_ptr, alloc_save_t **));
+private int restore_check_operand(P3(os_ptr, alloc_save_t **, gs_dual_memory_t *));
private int restore_check_stack(P3(const ref_stack_t *, const alloc_save_t *, bool));
private void restore_fix_stack(P3(ref_stack_t *, const alloc_save_t *, bool));
int
@@ -115,7 +112,7 @@ zrestore(i_ctx_t *i_ctx_p)
alloc_save_t *asave;
bool last;
vm_save_t *vmsave;
- int code = restore_check_operand(op, &asave);
+ int code = restore_check_operand(op, &asave, idmemory);
if (code < 0)
return code;
@@ -175,7 +172,8 @@ zrestore(i_ctx_t *i_ctx_p)
}
/* Check the operand of a restore. */
private int
-restore_check_operand(os_ptr op, alloc_save_t ** pasave)
+restore_check_operand(os_ptr op, alloc_save_t ** pasave,
+ gs_dual_memory_t *idmem)
{
vm_save_t *vmsave;
ulong sid;
@@ -186,7 +184,7 @@ restore_check_operand(os_ptr op, alloc_save_t ** pasave)
if (vmsave == 0) /* invalidated save */
return_error(e_invalidrestore);
sid = op->value.saveid;
- asave = alloc_find_save(idmemory, sid);
+ asave = alloc_find_save(idmem, sid);
if (asave == 0)
return_error(e_invalidrestore);
*pasave = asave;
@@ -336,7 +334,7 @@ zvmstatus(i_ctx_t *i_ctx_p)
}
gs_memory_status(&gs_memory_default, &dstat);
push(3);
- make_int(op - 2, alloc_save_level(idmemory));
+ make_int(op - 2, imemory_save_level(iimemory_local));
make_int(op - 1, mstat.used);
make_int(op, mstat.allocated + dstat.allocated - dstat.used);
return 0;
@@ -351,7 +349,7 @@ zforgetsave(i_ctx_t *i_ctx_p)
os_ptr op = osp;
alloc_save_t *asave;
vm_save_t *vmsave;
- int code = restore_check_operand(op, &asave);
+ int code = restore_check_operand(op, &asave, idmemory);
if (code < 0)
return 0;
diff --git a/gs/src/zvmem2.c b/gs/src/zvmem2.c
index 17118f553..44d3cacb9 100644
--- a/gs/src/zvmem2.c
+++ b/gs/src/zvmem2.c
@@ -23,6 +23,7 @@
#include "estack.h"
#include "ialloc.h" /* for ivmspace.h */
#include "ivmspace.h"
+#include "ivmem2.h"
#include "store.h"
/* Garbage collector control parameters. */