From c9842eae046216fb0e646ff55f7a4cd15dcc963c Mon Sep 17 00:00:00 2001 From: msweet Date: Fri, 10 May 2013 18:56:23 +0000 Subject: [PATCH] Import cups.org releases git-svn-id: svn+ssh://src.apple.com/svn/cups/cups.org/tags/release-1.0b1@4306 a1ca3aef-8c08-0410-bb20-df032aa958be --- LICENSE.html | 269 ++ LICENSE.txt | 223 ++ Makedefs.in | 111 + Makefile | 67 + README.html | 243 ++ README.txt | 192 ++ backend/Makefile | 98 + backend/lpd.c | 394 +++ backend/parallel.c | 179 ++ backend/serial.c | 297 +++ backend/smb.c | 66 + backend/socket.c | 232 ++ berkeley/Makefile | 82 + berkeley/lpc.c | 452 ++++ berkeley/lpr.c | 232 ++ berkeley/lprm.c | 198 ++ cgi-bin/Makefile | 61 + cgi-bin/printers.c | 461 ++++ conf/Makefile | 61 + conf/classes.conf | 72 + conf/cupsd.conf | 324 +++ conf/mime.convs | 62 + conf/mime.types | 123 + conf/printers.conf | 101 + config.h.in | 95 + configure.in | 142 ++ cups.dsw | 113 + cups/Makefile | 130 + cups/cups.h | 135 + cups/debug.h | 57 + cups/emit.c | 301 +++ cups/filter.c | 329 +++ cups/http.c | 1393 +++++++++++ cups/http.h | 316 +++ cups/ipp.c | 1458 +++++++++++ cups/ipp.h | 341 +++ cups/language.c | 370 +++ cups/language.h | 188 ++ cups/mark.c | 418 ++++ cups/mime.c | 611 +++++ cups/mime.h | 137 ++ cups/options.c | 333 +++ cups/page.c | 179 ++ cups/ppd.c | 1483 +++++++++++ cups/ppd.h | 236 ++ cups/raster.c | 252 ++ cups/raster.h | 228 ++ cups/string.c | 125 + cups/string.h | 66 + cups/testhttp.c | 109 + cups/testmime.c | 199 ++ cups/testmime.dsp | 102 + cups/testppd.c | 183 ++ cups/testppd.dsp | 102 + cups/type.c | 1011 ++++++++ cups/util.c | 932 +++++++ data/HPGLprolog | 62 + data/Makefile | 56 + data/psglyphs | 1051 ++++++++ doc/Makefile | 89 + doc/cmp.html | 648 +++++ doc/cmp.pdf | 966 ++++++++ doc/cmp.shtml | 713 ++++++ doc/cups.css | 3 + doc/documentation.html | 109 + doc/figures.sc | Bin 0 -> 51020 bytes doc/idd.html | 278 +++ doc/idd.pdf | 758 ++++++ doc/idd.shtml | 381 +++ doc/images/cups-bar.gif | Bin 0 -> 1242 bytes doc/images/cups-block-diagram.gif | Bin 0 -> 3509 bytes doc/images/cups-large.gif | Bin 0 -> 7457 bytes doc/images/cups-medium.gif | Bin 0 -> 3163 bytes doc/images/cups-small.gif | Bin 0 -> 1266 bytes doc/images/draft.gif | Bin 0 -> 926 bytes doc/images/logo.gif | Bin 0 -> 1958 bytes doc/images/navbar.gif | Bin 0 -> 2251 bytes doc/images/navbar.xcf.gz | Bin 0 -> 4253 bytes doc/images/printer-idle.gif | Bin 0 -> 706 bytes doc/images/printer-processing.gif | Bin 0 -> 805 bytes doc/images/printer-stopped.gif | Bin 0 -> 794 bytes doc/index.html | 34 + doc/overview.html | 287 +++ doc/overview.pdf | Bin 0 -> 21771 bytes doc/sam.html | 69 + doc/sam.pdf | Bin 0 -> 23287 bytes doc/sam.shtml | 55 + doc/sdd.html | 470 ++++ doc/sdd.pdf | 993 ++++++++ doc/sdd.shtml | 563 +++++ doc/ssr.html | 153 ++ doc/ssr.pdf | 452 ++++ doc/ssr.shtml | 166 ++ doc/stp.html | 142 ++ doc/stp.shtml | 165 ++ doc/sum.html | 54 + doc/sum.pdf | Bin 0 -> 19057 bytes doc/sum.shtml | 45 + doc/svd.html | 146 ++ doc/svd.pdf | Bin 0 -> 21846 bytes doc/svd.shtml | 163 ++ filter/Makefile | 114 + filter/common.c | 250 ++ filter/common.h | 67 + filter/hpgl-attr.c | 405 +++ filter/hpgl-char.c | 433 ++++ filter/hpgl-config.c | 473 ++++ filter/hpgl-input.c | 232 ++ filter/hpgl-main.c | 255 ++ filter/hpgl-polygon.c | 380 +++ filter/hpgl-prolog.c | 192 ++ filter/hpgl-vector.c | 704 ++++++ filter/hpgltops.dsp | 130 + filter/hpgltops.h | 196 ++ filter/image-colorspace.c | 910 +++++++ filter/image-gif.c | 644 +++++ filter/image-jpeg.c | 190 ++ filter/image-photocd.c | 319 +++ filter/image-png.c | 205 ++ filter/image-pnm.c | 288 +++ filter/image-sgi.c | 267 ++ filter/image-sgi.h | 94 + filter/image-sgilib.c | 857 +++++++ filter/image-sun.c | 376 +++ filter/image-tiff.c | 1622 ++++++++++++ filter/image-zoom.c | 310 +++ filter/image.c | 745 ++++++ filter/image.h | 223 ++ filter/imagetops.c | 486 ++++ filter/imagetoraster.c | 3835 +++++++++++++++++++++++++++++ filter/pstops.c | 706 ++++++ filter/pstops.dsp | 107 + filter/textcommon.c | 707 ++++++ filter/textcommon.h | 88 + filter/texttops.c | 569 +++++ filter/texttops.dsp | 98 + locale/C/cups_C | 116 + locale/Makefile | 60 + locale/de/cups_de | 116 + locale/en/cups_en | 116 + locale/es/cups_es | 116 + locale/fr/cups_fr | 116 + locale/it/cups_it | 116 + locale/locale.txt | 32 + man/Makefile | 74 + man/accept.8 | 53 + man/accept.z | Bin 0 -> 896 bytes man/backend.1 | 88 + man/backend.z | Bin 0 -> 1387 bytes man/classes.conf.5 | 36 + man/classes.conf.z | Bin 0 -> 433 bytes man/cupsd.8 | 47 + man/cupsd.conf.5 | 36 + man/cupsd.conf.z | Bin 0 -> 432 bytes man/cupsd.z | Bin 0 -> 883 bytes man/enable.8 | 62 + man/enable.z | Bin 0 -> 933 bytes man/filter.1 | 95 + man/filter.z | Bin 0 -> 1683 bytes man/lp.1 | 44 + man/lp.z | Bin 0 -> 531 bytes man/lpadmin.8 | 109 + man/lpadmin.z | Bin 0 -> 2502 bytes man/lpc.8 | 79 + man/lpc.z | Bin 0 -> 1264 bytes man/lpr.1 | 41 + man/lpr.z | Bin 0 -> 451 bytes man/lprm.1 | 40 + man/lprm.z | Bin 0 -> 414 bytes man/lpstat.1 | 42 + man/lpstat.z | Bin 0 -> 536 bytes man/mime.convs.5 | 36 + man/mime.convs.z | Bin 0 -> 432 bytes man/mime.types.5 | 36 + man/mime.types.z | Bin 0 -> 432 bytes man/printers.conf.5 | 36 + man/printers.conf.z | Bin 0 -> 434 bytes pstoraster/Fontmap | 98 + pstoraster/LICENSE.txt | 482 ++++ pstoraster/Makefile | 148 ++ pstoraster/bfont.h | 54 + pstoraster/bseq.h | 66 + pstoraster/btoken.h | 65 + pstoraster/ctype_.h | 31 + pstoraster/dirent_.h | 50 + pstoraster/dstack.h | 307 +++ pstoraster/errno_.h | 35 + pstoraster/errors.h | 179 ++ pstoraster/estack.h | 137 ++ pstoraster/files.h | 142 ++ pstoraster/fname.h | 38 + pstoraster/gconf.c | 126 + pstoraster/gconfig.h | 192 ++ pstoraster/gconfigv.h | 3 + pstoraster/gdebug.h | 117 + pstoraster/gdevabuf.c | 355 +++ pstoraster/gdevcups.c | 2421 ++++++++++++++++++ pstoraster/gdevddrw.c | 470 ++++ pstoraster/gdevdflt.c | 878 +++++++ pstoraster/gdevemap.c | 64 + pstoraster/gdevht.h | 47 + pstoraster/gdevm1.c | 689 ++++++ pstoraster/gdevm16.c | 154 ++ pstoraster/gdevm2.c | 244 ++ pstoraster/gdevm24.c | 484 ++++ pstoraster/gdevm32.c | 233 ++ pstoraster/gdevm4.c | 207 ++ pstoraster/gdevm8.c | 225 ++ pstoraster/gdevmem.c | 363 +++ pstoraster/gdevmem.h | 217 ++ pstoraster/gdevmpla.c | 182 ++ pstoraster/gdevmrop.c | 1013 ++++++++ pstoraster/gdevmrop.h | 65 + pstoraster/gdevnfwd.c | 561 +++++ pstoraster/gdevpipe.c | 74 + pstoraster/gdevprn.c | 757 ++++++ pstoraster/gdevprn.h | 418 ++++ pstoraster/genarch.c | 131 + pstoraster/ghost.h | 27 + pstoraster/gp.h | 201 ++ pstoraster/gp_nofb.c | 54 + pstoraster/gp_unifn.c | 58 + pstoraster/gp_unifs.c | 424 ++++ pstoraster/gp_unix.c | 174 ++ pstoraster/gpcheck.h | 58 + pstoraster/gs_btokn.ps | 287 +++ pstoraster/gs_ccfnt.ps | 98 + pstoraster/gs_cidfn.ps | 127 + pstoraster/gs_cmap.ps | 235 ++ pstoraster/gs_cmdl.ps | 186 ++ pstoraster/gs_dbt_e.ps | 65 + pstoraster/gs_diskf.ps | 230 ++ pstoraster/gs_dps1.ps | 307 +++ pstoraster/gs_fform.ps | 115 + pstoraster/gs_fonts.ps | 797 ++++++ pstoraster/gs_init.ps | 1269 ++++++++++ pstoraster/gs_iso_e.ps | 72 + pstoraster/gs_kanji.ps | 164 ++ pstoraster/gs_ksb_e.ps | 70 + pstoraster/gs_l2img.ps | 191 ++ pstoraster/gs_lev2.ps | 332 +++ pstoraster/gs_mex_e.ps | 70 + pstoraster/gs_mro_e.ps | 63 + pstoraster/gs_pdf.ps | 575 +++++ pstoraster/gs_pdf_e.ps | 48 + pstoraster/gs_pdfwr.ps | 288 +++ pstoraster/gs_pfile.ps | 184 ++ pstoraster/gs_res.ps | 555 +++++ pstoraster/gs_setpd.ps | 633 +++++ pstoraster/gs_statd.ps | 275 +++ pstoraster/gs_std_e.ps | 79 + pstoraster/gs_sym_e.ps | 89 + pstoraster/gs_ttf.ps | 447 ++++ pstoraster/gs_typ42.ps | 47 + pstoraster/gs_type1.ps | 132 + pstoraster/gs_wan_e.ps | 48 + pstoraster/gs_wl1_e.ps | 72 + pstoraster/gs_wl2_e.ps | 72 + pstoraster/gs_wl5_e.ps | 72 + pstoraster/gsalloc.c | 1010 ++++++++ pstoraster/gsalloc.h | 58 + pstoraster/gsbitops.c | 605 +++++ pstoraster/gsbitops.h | 178 ++ pstoraster/gsbittab.c | 135 + pstoraster/gsbittab.h | 55 + pstoraster/gsccode.h | 58 + pstoraster/gsccolor.h | 51 + pstoraster/gscdef.c | 83 + pstoraster/gscdefs.h | 55 + pstoraster/gschar.c | 1353 ++++++++++ pstoraster/gschar.h | 120 + pstoraster/gschar0.c | 342 +++ pstoraster/gscie.c | 1206 +++++++++ pstoraster/gscie.h | 485 ++++ pstoraster/gscolor.c | 361 +++ pstoraster/gscolor.h | 44 + pstoraster/gscolor1.c | 231 ++ pstoraster/gscolor1.h | 49 + pstoraster/gscolor2.c | 205 ++ pstoraster/gscolor2.h | 82 + pstoraster/gscoord.c | 463 ++++ pstoraster/gscoord.h | 55 + pstoraster/gscpm.h | 38 + pstoraster/gscrypt1.h | 44 + pstoraster/gscsepr.c | 161 ++ pstoraster/gscspace.h | 194 ++ pstoraster/gsdcolor.h | 287 +++ pstoraster/gsdevice.c | 416 ++++ pstoraster/gsdevice.h | 86 + pstoraster/gsdevmem.c | 221 ++ pstoraster/gsdparam.c | 603 +++++ pstoraster/gsdps1.c | 169 ++ pstoraster/gserror.h | 33 + pstoraster/gserrors.h | 48 + pstoraster/gsexit.h | 39 + pstoraster/gsfont.c | 486 ++++ pstoraster/gsfont.h | 70 + pstoraster/gsfont0.c | 115 + pstoraster/gshsb.c | 138 ++ pstoraster/gshsb.h | 28 + pstoraster/gsht.c | 427 ++++ pstoraster/gsht.h | 81 + pstoraster/gsht1.c | 346 +++ pstoraster/gsht1.h | 42 + pstoraster/gshtscr.c | 503 ++++ pstoraster/gsimage.c | 312 +++ pstoraster/gsimage.h | 50 + pstoraster/gsimpath.c | 188 ++ pstoraster/gsinit.c | 74 + pstoraster/gsio.h | 65 + pstoraster/gsiodev.c | 270 ++ pstoraster/gsiparam.h | 238 ++ pstoraster/gslib.h | 39 + pstoraster/gsline.c | 234 ++ pstoraster/gsline.h | 60 + pstoraster/gslparam.h | 47 + pstoraster/gsmatrix.c | 418 ++++ pstoraster/gsmatrix.h | 75 + pstoraster/gsmdebug.h | 50 + pstoraster/gsmemory.c | 392 +++ pstoraster/gsmemory.h | 355 +++ pstoraster/gsmisc.c | 649 +++++ pstoraster/gspaint.c | 292 +++ pstoraster/gspaint.h | 36 + pstoraster/gsparam.c | 374 +++ pstoraster/gsparam.h | 349 +++ pstoraster/gspath.c | 259 ++ pstoraster/gspath.h | 77 + pstoraster/gspath1.c | 371 +++ pstoraster/gspath2.h | 35 + pstoraster/gspcolor.c | 743 ++++++ pstoraster/gspenum.h | 39 + pstoraster/gsrefct.h | 137 ++ pstoraster/gsrop.c | 91 + pstoraster/gsrop.h | 44 + pstoraster/gsropt.h | 180 ++ pstoraster/gsroptab.c | 342 +++ pstoraster/gsstate.c | 786 ++++++ pstoraster/gsstate.h | 68 + pstoraster/gsstruct.h | 602 +++++ pstoraster/gstype1.c | 966 ++++++++ pstoraster/gstype1.h | 174 ++ pstoraster/gstype42.c | 431 ++++ pstoraster/gstypes.h | 84 + pstoraster/gsuid.h | 72 + pstoraster/gsutil.c | 222 ++ pstoraster/gsutil.h | 66 + pstoraster/gsxfont.h | 43 + pstoraster/gx.h | 43 + pstoraster/gxacpath.c | 424 ++++ pstoraster/gxalloc.h | 351 +++ pstoraster/gxarith.h | 83 + pstoraster/gxbcache.c | 147 ++ pstoraster/gxbcache.h | 121 + pstoraster/gxbitmap.h | 133 + pstoraster/gxccache.c | 437 ++++ pstoraster/gxccman.c | 768 ++++++ pstoraster/gxchar.h | 158 ++ pstoraster/gxcht.c | 525 ++++ pstoraster/gxcindex.h | 101 + pstoraster/gxclbits.c | 593 +++++ pstoraster/gxcldev.h | 484 ++++ pstoraster/gxclfile.c | 117 + pstoraster/gxclimag.c | 626 +++++ pstoraster/gxclio.h | 70 + pstoraster/gxclip2.c | 362 +++ pstoraster/gxclip2.h | 60 + pstoraster/gxclist.c | 1138 +++++++++ pstoraster/gxclist.h | 187 ++ pstoraster/gxclpath.c | 959 ++++++++ pstoraster/gxclpath.h | 155 ++ pstoraster/gxclread.c | 1522 ++++++++++++ pstoraster/gxcmap.c | 626 +++++ pstoraster/gxcmap.h | 84 + pstoraster/gxcolor2.h | 72 + pstoraster/gxcoord.h | 38 + pstoraster/gxcpath.c | 802 ++++++ pstoraster/gxcpath.h | 123 + pstoraster/gxcspace.h | 168 ++ pstoraster/gxctable.c | 145 ++ pstoraster/gxctable.h | 63 + pstoraster/gxcvalue.h | 46 + pstoraster/gxdcconv.c | 151 ++ pstoraster/gxdcconv.h | 36 + pstoraster/gxdcolor.c | 89 + pstoraster/gxdcolor.h | 144 ++ pstoraster/gxdda.h | 118 + pstoraster/gxdevice.h | 950 +++++++ pstoraster/gxdevmem.h | 148 ++ pstoraster/gxdevrop.h | 36 + pstoraster/gxdht.h | 172 ++ pstoraster/gxdither.c | 483 ++++ pstoraster/gxdither.h | 55 + pstoraster/gxfarith.h | 134 + pstoraster/gxfcache.h | 248 ++ pstoraster/gxfill.c | 1495 +++++++++++ pstoraster/gxfixed.h | 218 ++ pstoraster/gxfmap.h | 93 + pstoraster/gxfont.h | 216 ++ pstoraster/gxfont0.h | 65 + pstoraster/gxfont1.h | 90 + pstoraster/gxfont42.h | 59 + pstoraster/gxfrac.h | 96 + pstoraster/gxhint1.c | 253 ++ pstoraster/gxhint2.c | 308 +++ pstoraster/gxhint3.c | 459 ++++ pstoraster/gxht.c | 439 ++++ pstoraster/gxht.h | 141 ++ pstoraster/gxhttile.h | 52 + pstoraster/gximage.c | 820 ++++++ pstoraster/gximage.h | 252 ++ pstoraster/gximage0.c | 283 +++ pstoraster/gximage1.c | 437 ++++ pstoraster/gximage2.c | 324 +++ pstoraster/gximage3.c | 302 +++ pstoraster/gximage4.c | 282 +++ pstoraster/gximage5.c | 168 ++ pstoraster/gxiodev.h | 177 ++ pstoraster/gxistate.h | 94 + pstoraster/gxline.h | 68 + pstoraster/gxlum.h | 44 + pstoraster/gxmatrix.h | 85 + pstoraster/gxobj.h | 214 ++ pstoraster/gxop1.h | 43 + pstoraster/gxpaint.c | 93 + pstoraster/gxpaint.h | 123 + pstoraster/gxpath.c | 543 ++++ pstoraster/gxpath.h | 149 ++ pstoraster/gxpath2.c | 407 +++ pstoraster/gxpcmap.c | 511 ++++ pstoraster/gxpcolor.h | 130 + pstoraster/gxpcopy.c | 998 ++++++++ pstoraster/gxpdash.c | 143 ++ pstoraster/gxstate.h | 63 + pstoraster/gxstroke.c | 1060 ++++++++ pstoraster/gxtmap.h | 42 + pstoraster/gxtype1.h | 222 ++ pstoraster/gxxfont.h | 172 ++ pstoraster/gzacpath.h | 44 + pstoraster/gzcpath.h | 52 + pstoraster/gzht.h | 147 ++ pstoraster/gzline.h | 33 + pstoraster/gzpath.h | 221 ++ pstoraster/gzstate.h | 154 ++ pstoraster/ialloc.c | 261 ++ pstoraster/ialloc.h | 122 + pstoraster/iastate.h | 29 + pstoraster/iastruct.h | 27 + pstoraster/ibnum.c | 213 ++ pstoraster/ibnum.h | 64 + pstoraster/iccinit0.c | 30 + pstoraster/ichar.h | 65 + pstoraster/icharout.h | 53 + pstoraster/icie.h | 77 + pstoraster/icolor.h | 54 + pstoraster/iconf.c | 73 + pstoraster/icsmap.h | 39 + pstoraster/idebug.c | 262 ++ pstoraster/idebug.h | 41 + pstoraster/idict.c | 974 ++++++++ pstoraster/idict.h | 183 ++ pstoraster/idparam.c | 348 +++ pstoraster/idparam.h | 80 + pstoraster/ifilter.h | 77 + pstoraster/ifont.h | 83 + pstoraster/igc.c | 1092 ++++++++ pstoraster/igc.h | 82 + pstoraster/igcref.c | 562 +++++ pstoraster/igcstr.c | 353 +++ pstoraster/igcstr.h | 35 + pstoraster/igstate.h | 161 ++ pstoraster/iimage.h | 35 + pstoraster/iinit.c | 475 ++++ pstoraster/ilevel.h | 29 + pstoraster/ilocate.c | 309 +++ pstoraster/imain.c | 569 +++++ pstoraster/imain.h | 271 ++ pstoraster/imemory.h | 105 + pstoraster/iminst.h | 80 + pstoraster/iname.c | 575 +++++ pstoraster/iname.h | 105 + pstoraster/inamedef.h | 212 ++ pstoraster/interp.c | 1419 +++++++++++ pstoraster/interp.h | 66 + pstoraster/ipacked.h | 128 + pstoraster/iparam.c | 822 +++++++ pstoraster/iparam.h | 103 + pstoraster/iparray.h | 36 + pstoraster/ireclaim.c | 206 ++ pstoraster/iref.h | 367 +++ pstoraster/isave.c | 989 ++++++++ pstoraster/isave.h | 111 + pstoraster/iscan.c | 1035 ++++++++ pstoraster/iscan.h | 148 ++ pstoraster/iscanbin.c | 581 +++++ pstoraster/iscannum.c | 357 +++ pstoraster/iscannum.h | 30 + pstoraster/iscantab.c | 114 + pstoraster/isstate.h | 40 + pstoraster/istack.c | 490 ++++ pstoraster/istack.h | 235 ++ pstoraster/istream.h | 37 + pstoraster/istruct.h | 60 + pstoraster/iutil.c | 536 ++++ pstoraster/iutil.h | 106 + pstoraster/iutil2.c | 100 + pstoraster/iutil2.h | 46 + pstoraster/ivmspace.h | 128 + pstoraster/main.h | 93 + pstoraster/malloc_.h | 51 + pstoraster/math_.h | 86 + pstoraster/memory_.h | 86 + pstoraster/opcheck.h | 72 + pstoraster/opdef.h | 143 ++ pstoraster/oper.h | 100 + pstoraster/opextern.h | 108 + pstoraster/ostack.h | 93 + pstoraster/pdf_2ps.ps | 270 ++ pstoraster/pdf_base.ps | 392 +++ pstoraster/pdf_draw.ps | 319 +++ pstoraster/pdf_font.ps | 374 +++ pstoraster/pdf_main.ps | 477 ++++ pstoraster/pdf_sec.ps | 58 + pstoraster/pfbtogs.ps | 117 + pstoraster/pstoraster.c | 178 ++ pstoraster/sa85x.h | 45 + pstoraster/sbcp.c | 237 ++ pstoraster/sbhc.c | 274 +++ pstoraster/sbhc.h | 90 + pstoraster/sbtx.h | 39 + pstoraster/sbwbs.c | 476 ++++ pstoraster/sbwbs.h | 71 + pstoraster/scanchar.h | 69 + pstoraster/scf.h | 173 ++ pstoraster/scfd.c | 771 ++++++ pstoraster/scfdtab.c | 938 +++++++ pstoraster/scfe.c | 490 ++++ pstoraster/scfetab.c | 161 ++ pstoraster/scfx.h | 122 + pstoraster/scommon.h | 157 ++ pstoraster/sdct.h | 97 + pstoraster/sdctc.c | 38 + pstoraster/sdctd.c | 279 +++ pstoraster/sdcte.c | 170 ++ pstoraster/seexec.c | 175 ++ pstoraster/sfile.c | 246 ++ pstoraster/sfilter.h | 129 + pstoraster/sfilter1.c | 292 +++ pstoraster/sfilter2.c | 284 +++ pstoraster/shc.c | 74 + pstoraster/shc.h | 248 ++ pstoraster/shcgen.c | 467 ++++ pstoraster/shcgen.h | 55 + pstoraster/siscale.c | 486 ++++ pstoraster/siscale.h | 136 + pstoraster/sjpeg.h | 72 + pstoraster/sjpegc.c | 272 ++ pstoraster/sjpegd.c | 89 + pstoraster/sjpege.c | 105 + pstoraster/sjpegerr.c | 85 + pstoraster/slzwc.c | 47 + pstoraster/slzwce.c | 160 ++ pstoraster/slzwd.c | 373 +++ pstoraster/slzwx.h | 71 + pstoraster/smtf.c | 171 ++ pstoraster/smtf.h | 43 + pstoraster/spcxd.c | 77 + pstoraster/spcxx.h | 30 + pstoraster/spdiff.c | 302 +++ pstoraster/spdiffx.h | 49 + pstoraster/spngp.c | 338 +++ pstoraster/spngpx.h | 55 + pstoraster/srld.c | 100 + pstoraster/srle.c | 120 + pstoraster/srlx.h | 64 + pstoraster/sstring.c | 434 ++++ pstoraster/sstring.h | 66 + pstoraster/stat_.h | 51 + pstoraster/std.h | 225 ++ pstoraster/stdio_.h | 53 + pstoraster/stdpre.h | 336 +++ pstoraster/store.h | 241 ++ pstoraster/stream.c | 792 ++++++ pstoraster/stream.h | 314 +++ pstoraster/strimpl.h | 146 ++ pstoraster/string_.h | 53 + pstoraster/szlibc.c | 45 + pstoraster/szlibd.c | 87 + pstoraster/szlibe.c | 87 + pstoraster/szlibx.h | 47 + pstoraster/time_.h | 65 + pstoraster/vmsmath.h | 42 + pstoraster/zarith.c | 296 +++ pstoraster/zarray.c | 125 + pstoraster/zbseq.c | 271 ++ pstoraster/zchar.c | 608 +++++ pstoraster/zchar1.c | 559 +++++ pstoraster/zchar2.c | 276 +++ pstoraster/zchar42.c | 171 ++ pstoraster/zcharout.c | 239 ++ pstoraster/zcie.c | 632 +++++ pstoraster/zcolor.c | 248 ++ pstoraster/zcolor1.c | 217 ++ pstoraster/zcolor2.c | 197 ++ pstoraster/zcontrol.c | 639 +++++ pstoraster/zcrd.c | 316 +++ pstoraster/zcsindex.c | 225 ++ pstoraster/zcssepr.c | 154 ++ pstoraster/zdevcal.c | 75 + pstoraster/zdevice.c | 326 +++ pstoraster/zdevice2.c | 333 +++ pstoraster/zdict.c | 490 ++++ pstoraster/zdps1.c | 450 ++++ pstoraster/zfbcp.c | 91 + pstoraster/zfdctc.c | 369 +++ pstoraster/zfdctd.c | 100 + pstoraster/zfdcte.c | 267 ++ pstoraster/zfdecode.c | 350 +++ pstoraster/zfile.c | 887 +++++++ pstoraster/zfileio.c | 778 ++++++ pstoraster/zfilter.c | 422 ++++ pstoraster/zfilter2.c | 154 ++ pstoraster/zfilterx.c | 319 +++ pstoraster/zfname.c | 111 + pstoraster/zfont.c | 405 +++ pstoraster/zfont0.c | 271 ++ pstoraster/zfont1.c | 192 ++ pstoraster/zfont2.c | 493 ++++ pstoraster/zfont42.c | 108 + pstoraster/zfproc.c | 337 +++ pstoraster/zfzlib.c | 98 + pstoraster/zgeneric.c | 495 ++++ pstoraster/zgstate.c | 329 +++ pstoraster/zhsb.c | 62 + pstoraster/zht.c | 238 ++ pstoraster/zht1.c | 143 ++ pstoraster/zht2.c | 328 +++ pstoraster/zimage2.c | 166 ++ pstoraster/ziodev.c | 401 +++ pstoraster/ziodev2.c | 133 + pstoraster/zmath.c | 247 ++ pstoraster/zmatrix.c | 325 +++ pstoraster/zmedia2.c | 442 ++++ pstoraster/zmisc.c | 313 +++ pstoraster/zmisc1.c | 127 + pstoraster/zmisc2.c | 244 ++ pstoraster/zpacked.c | 237 ++ pstoraster/zpaint.c | 484 ++++ pstoraster/zpath.c | 179 ++ pstoraster/zpath1.c | 244 ++ pstoraster/zpcolor.c | 253 ++ pstoraster/zrelbit.c | 314 +++ pstoraster/zstack.c | 267 ++ pstoraster/zstring.c | 161 ++ pstoraster/zsysvm.c | 146 ++ pstoraster/ztoken.c | 232 ++ pstoraster/ztype.c | 459 ++++ pstoraster/zupath.c | 526 ++++ pstoraster/zusparam.c | 503 ++++ pstoraster/zvmem.c | 336 +++ pstoraster/zvmem2.c | 156 ++ scheduler/Makefile | 67 + scheduler/auth.c | 570 +++++ scheduler/auth.h | 108 + scheduler/classes.c | 450 ++++ scheduler/classes.h | 43 + scheduler/client.c | 1569 ++++++++++++ scheduler/client.h | 95 + scheduler/conf.c | 1066 ++++++++ scheduler/conf.h | 100 + scheduler/cupsd.h | 139 ++ scheduler/dirsvc.c | 308 +++ scheduler/dirsvc.h | 58 + scheduler/ipp.c | 1802 ++++++++++++++ scheduler/job.c | 850 +++++++ scheduler/job.h | 74 + scheduler/main.c | 410 +++ scheduler/printers.c | 774 ++++++ scheduler/printers.h | 80 + systemv/Makefile | 97 + systemv/accept.c | 198 ++ systemv/cancel.c | 177 ++ systemv/lp.c | 243 ++ systemv/lpstat.c | 1248 ++++++++++ 684 files changed, 180536 insertions(+) create mode 100644 LICENSE.html create mode 100644 LICENSE.txt create mode 100644 Makedefs.in create mode 100644 Makefile create mode 100644 README.html create mode 100644 README.txt create mode 100644 backend/Makefile create mode 100644 backend/lpd.c create mode 100644 backend/parallel.c create mode 100644 backend/serial.c create mode 100644 backend/smb.c create mode 100644 backend/socket.c create mode 100644 berkeley/Makefile create mode 100644 berkeley/lpc.c create mode 100644 berkeley/lpr.c create mode 100644 berkeley/lprm.c create mode 100644 cgi-bin/Makefile create mode 100644 cgi-bin/printers.c create mode 100644 conf/Makefile create mode 100644 conf/classes.conf create mode 100644 conf/cupsd.conf create mode 100644 conf/mime.convs create mode 100644 conf/mime.types create mode 100644 conf/printers.conf create mode 100644 config.h.in create mode 100644 configure.in create mode 100644 cups.dsw create mode 100644 cups/Makefile create mode 100644 cups/cups.h create mode 100644 cups/debug.h create mode 100644 cups/emit.c create mode 100644 cups/filter.c create mode 100644 cups/http.c create mode 100644 cups/http.h create mode 100644 cups/ipp.c create mode 100644 cups/ipp.h create mode 100644 cups/language.c create mode 100644 cups/language.h create mode 100644 cups/mark.c create mode 100644 cups/mime.c create mode 100644 cups/mime.h create mode 100644 cups/options.c create mode 100644 cups/page.c create mode 100644 cups/ppd.c create mode 100644 cups/ppd.h create mode 100644 cups/raster.c create mode 100644 cups/raster.h create mode 100644 cups/string.c create mode 100644 cups/string.h create mode 100644 cups/testhttp.c create mode 100644 cups/testmime.c create mode 100644 cups/testmime.dsp create mode 100644 cups/testppd.c create mode 100644 cups/testppd.dsp create mode 100644 cups/type.c create mode 100644 cups/util.c create mode 100644 data/HPGLprolog create mode 100644 data/Makefile create mode 100644 data/psglyphs create mode 100644 doc/Makefile create mode 100644 doc/cmp.html create mode 100644 doc/cmp.pdf create mode 100644 doc/cmp.shtml create mode 100644 doc/cups.css create mode 100644 doc/documentation.html create mode 100644 doc/figures.sc create mode 100644 doc/idd.html create mode 100644 doc/idd.pdf create mode 100644 doc/idd.shtml create mode 100644 doc/images/cups-bar.gif create mode 100644 doc/images/cups-block-diagram.gif create mode 100644 doc/images/cups-large.gif create mode 100644 doc/images/cups-medium.gif create mode 100644 doc/images/cups-small.gif create mode 100644 doc/images/draft.gif create mode 100644 doc/images/logo.gif create mode 100644 doc/images/navbar.gif create mode 100644 doc/images/navbar.xcf.gz create mode 100644 doc/images/printer-idle.gif create mode 100644 doc/images/printer-processing.gif create mode 100644 doc/images/printer-stopped.gif create mode 100644 doc/index.html create mode 100644 doc/overview.html create mode 100644 doc/overview.pdf create mode 100644 doc/sam.html create mode 100644 doc/sam.pdf create mode 100644 doc/sam.shtml create mode 100644 doc/sdd.html create mode 100644 doc/sdd.pdf create mode 100644 doc/sdd.shtml create mode 100644 doc/ssr.html create mode 100644 doc/ssr.pdf create mode 100644 doc/ssr.shtml create mode 100644 doc/stp.html create mode 100644 doc/stp.shtml create mode 100644 doc/sum.html create mode 100644 doc/sum.pdf create mode 100644 doc/sum.shtml create mode 100644 doc/svd.html create mode 100644 doc/svd.pdf create mode 100644 doc/svd.shtml create mode 100644 filter/Makefile create mode 100644 filter/common.c create mode 100644 filter/common.h create mode 100644 filter/hpgl-attr.c create mode 100644 filter/hpgl-char.c create mode 100644 filter/hpgl-config.c create mode 100644 filter/hpgl-input.c create mode 100644 filter/hpgl-main.c create mode 100644 filter/hpgl-polygon.c create mode 100644 filter/hpgl-prolog.c create mode 100644 filter/hpgl-vector.c create mode 100644 filter/hpgltops.dsp create mode 100644 filter/hpgltops.h create mode 100644 filter/image-colorspace.c create mode 100644 filter/image-gif.c create mode 100644 filter/image-jpeg.c create mode 100644 filter/image-photocd.c create mode 100644 filter/image-png.c create mode 100644 filter/image-pnm.c create mode 100644 filter/image-sgi.c create mode 100644 filter/image-sgi.h create mode 100644 filter/image-sgilib.c create mode 100644 filter/image-sun.c create mode 100644 filter/image-tiff.c create mode 100644 filter/image-zoom.c create mode 100644 filter/image.c create mode 100644 filter/image.h create mode 100644 filter/imagetops.c create mode 100644 filter/imagetoraster.c create mode 100644 filter/pstops.c create mode 100644 filter/pstops.dsp create mode 100644 filter/textcommon.c create mode 100644 filter/textcommon.h create mode 100644 filter/texttops.c create mode 100644 filter/texttops.dsp create mode 100644 locale/C/cups_C create mode 100644 locale/Makefile create mode 100644 locale/de/cups_de create mode 100644 locale/en/cups_en create mode 100644 locale/es/cups_es create mode 100644 locale/fr/cups_fr create mode 100644 locale/it/cups_it create mode 100644 locale/locale.txt create mode 100644 man/Makefile create mode 100644 man/accept.8 create mode 100644 man/accept.z create mode 100644 man/backend.1 create mode 100644 man/backend.z create mode 100644 man/classes.conf.5 create mode 100644 man/classes.conf.z create mode 100644 man/cupsd.8 create mode 100644 man/cupsd.conf.5 create mode 100644 man/cupsd.conf.z create mode 100644 man/cupsd.z create mode 100644 man/enable.8 create mode 100644 man/enable.z create mode 100644 man/filter.1 create mode 100644 man/filter.z create mode 100644 man/lp.1 create mode 100644 man/lp.z create mode 100644 man/lpadmin.8 create mode 100644 man/lpadmin.z create mode 100644 man/lpc.8 create mode 100644 man/lpc.z create mode 100644 man/lpr.1 create mode 100644 man/lpr.z create mode 100644 man/lprm.1 create mode 100644 man/lprm.z create mode 100644 man/lpstat.1 create mode 100644 man/lpstat.z create mode 100644 man/mime.convs.5 create mode 100644 man/mime.convs.z create mode 100644 man/mime.types.5 create mode 100644 man/mime.types.z create mode 100644 man/printers.conf.5 create mode 100644 man/printers.conf.z create mode 100644 pstoraster/Fontmap create mode 100644 pstoraster/LICENSE.txt create mode 100644 pstoraster/Makefile create mode 100644 pstoraster/bfont.h create mode 100644 pstoraster/bseq.h create mode 100644 pstoraster/btoken.h create mode 100644 pstoraster/ctype_.h create mode 100644 pstoraster/dirent_.h create mode 100644 pstoraster/dstack.h create mode 100644 pstoraster/errno_.h create mode 100644 pstoraster/errors.h create mode 100644 pstoraster/estack.h create mode 100644 pstoraster/files.h create mode 100644 pstoraster/fname.h create mode 100644 pstoraster/gconf.c create mode 100644 pstoraster/gconfig.h create mode 100644 pstoraster/gconfigv.h create mode 100644 pstoraster/gdebug.h create mode 100644 pstoraster/gdevabuf.c create mode 100644 pstoraster/gdevcups.c create mode 100644 pstoraster/gdevddrw.c create mode 100644 pstoraster/gdevdflt.c create mode 100644 pstoraster/gdevemap.c create mode 100644 pstoraster/gdevht.h create mode 100644 pstoraster/gdevm1.c create mode 100644 pstoraster/gdevm16.c create mode 100644 pstoraster/gdevm2.c create mode 100644 pstoraster/gdevm24.c create mode 100644 pstoraster/gdevm32.c create mode 100644 pstoraster/gdevm4.c create mode 100644 pstoraster/gdevm8.c create mode 100644 pstoraster/gdevmem.c create mode 100644 pstoraster/gdevmem.h create mode 100644 pstoraster/gdevmpla.c create mode 100644 pstoraster/gdevmrop.c create mode 100644 pstoraster/gdevmrop.h create mode 100644 pstoraster/gdevnfwd.c create mode 100644 pstoraster/gdevpipe.c create mode 100644 pstoraster/gdevprn.c create mode 100644 pstoraster/gdevprn.h create mode 100644 pstoraster/genarch.c create mode 100644 pstoraster/ghost.h create mode 100644 pstoraster/gp.h create mode 100644 pstoraster/gp_nofb.c create mode 100644 pstoraster/gp_unifn.c create mode 100644 pstoraster/gp_unifs.c create mode 100644 pstoraster/gp_unix.c create mode 100644 pstoraster/gpcheck.h create mode 100644 pstoraster/gs_btokn.ps create mode 100644 pstoraster/gs_ccfnt.ps create mode 100644 pstoraster/gs_cidfn.ps create mode 100644 pstoraster/gs_cmap.ps create mode 100644 pstoraster/gs_cmdl.ps create mode 100644 pstoraster/gs_dbt_e.ps create mode 100644 pstoraster/gs_diskf.ps create mode 100644 pstoraster/gs_dps1.ps create mode 100644 pstoraster/gs_fform.ps create mode 100644 pstoraster/gs_fonts.ps create mode 100644 pstoraster/gs_init.ps create mode 100644 pstoraster/gs_iso_e.ps create mode 100644 pstoraster/gs_kanji.ps create mode 100644 pstoraster/gs_ksb_e.ps create mode 100644 pstoraster/gs_l2img.ps create mode 100644 pstoraster/gs_lev2.ps create mode 100644 pstoraster/gs_mex_e.ps create mode 100644 pstoraster/gs_mro_e.ps create mode 100644 pstoraster/gs_pdf.ps create mode 100644 pstoraster/gs_pdf_e.ps create mode 100644 pstoraster/gs_pdfwr.ps create mode 100644 pstoraster/gs_pfile.ps create mode 100644 pstoraster/gs_res.ps create mode 100644 pstoraster/gs_setpd.ps create mode 100644 pstoraster/gs_statd.ps create mode 100644 pstoraster/gs_std_e.ps create mode 100644 pstoraster/gs_sym_e.ps create mode 100644 pstoraster/gs_ttf.ps create mode 100644 pstoraster/gs_typ42.ps create mode 100644 pstoraster/gs_type1.ps create mode 100644 pstoraster/gs_wan_e.ps create mode 100644 pstoraster/gs_wl1_e.ps create mode 100644 pstoraster/gs_wl2_e.ps create mode 100644 pstoraster/gs_wl5_e.ps create mode 100644 pstoraster/gsalloc.c create mode 100644 pstoraster/gsalloc.h create mode 100644 pstoraster/gsbitops.c create mode 100644 pstoraster/gsbitops.h create mode 100644 pstoraster/gsbittab.c create mode 100644 pstoraster/gsbittab.h create mode 100644 pstoraster/gsccode.h create mode 100644 pstoraster/gsccolor.h create mode 100644 pstoraster/gscdef.c create mode 100644 pstoraster/gscdefs.h create mode 100644 pstoraster/gschar.c create mode 100644 pstoraster/gschar.h create mode 100644 pstoraster/gschar0.c create mode 100644 pstoraster/gscie.c create mode 100644 pstoraster/gscie.h create mode 100644 pstoraster/gscolor.c create mode 100644 pstoraster/gscolor.h create mode 100644 pstoraster/gscolor1.c create mode 100644 pstoraster/gscolor1.h create mode 100644 pstoraster/gscolor2.c create mode 100644 pstoraster/gscolor2.h create mode 100644 pstoraster/gscoord.c create mode 100644 pstoraster/gscoord.h create mode 100644 pstoraster/gscpm.h create mode 100644 pstoraster/gscrypt1.h create mode 100644 pstoraster/gscsepr.c create mode 100644 pstoraster/gscspace.h create mode 100644 pstoraster/gsdcolor.h create mode 100644 pstoraster/gsdevice.c create mode 100644 pstoraster/gsdevice.h create mode 100644 pstoraster/gsdevmem.c create mode 100644 pstoraster/gsdparam.c create mode 100644 pstoraster/gsdps1.c create mode 100644 pstoraster/gserror.h create mode 100644 pstoraster/gserrors.h create mode 100644 pstoraster/gsexit.h create mode 100644 pstoraster/gsfont.c create mode 100644 pstoraster/gsfont.h create mode 100644 pstoraster/gsfont0.c create mode 100644 pstoraster/gshsb.c create mode 100644 pstoraster/gshsb.h create mode 100644 pstoraster/gsht.c create mode 100644 pstoraster/gsht.h create mode 100644 pstoraster/gsht1.c create mode 100644 pstoraster/gsht1.h create mode 100644 pstoraster/gshtscr.c create mode 100644 pstoraster/gsimage.c create mode 100644 pstoraster/gsimage.h create mode 100644 pstoraster/gsimpath.c create mode 100644 pstoraster/gsinit.c create mode 100644 pstoraster/gsio.h create mode 100644 pstoraster/gsiodev.c create mode 100644 pstoraster/gsiparam.h create mode 100644 pstoraster/gslib.h create mode 100644 pstoraster/gsline.c create mode 100644 pstoraster/gsline.h create mode 100644 pstoraster/gslparam.h create mode 100644 pstoraster/gsmatrix.c create mode 100644 pstoraster/gsmatrix.h create mode 100644 pstoraster/gsmdebug.h create mode 100644 pstoraster/gsmemory.c create mode 100644 pstoraster/gsmemory.h create mode 100644 pstoraster/gsmisc.c create mode 100644 pstoraster/gspaint.c create mode 100644 pstoraster/gspaint.h create mode 100644 pstoraster/gsparam.c create mode 100644 pstoraster/gsparam.h create mode 100644 pstoraster/gspath.c create mode 100644 pstoraster/gspath.h create mode 100644 pstoraster/gspath1.c create mode 100644 pstoraster/gspath2.h create mode 100644 pstoraster/gspcolor.c create mode 100644 pstoraster/gspenum.h create mode 100644 pstoraster/gsrefct.h create mode 100644 pstoraster/gsrop.c create mode 100644 pstoraster/gsrop.h create mode 100644 pstoraster/gsropt.h create mode 100644 pstoraster/gsroptab.c create mode 100644 pstoraster/gsstate.c create mode 100644 pstoraster/gsstate.h create mode 100644 pstoraster/gsstruct.h create mode 100644 pstoraster/gstype1.c create mode 100644 pstoraster/gstype1.h create mode 100644 pstoraster/gstype42.c create mode 100644 pstoraster/gstypes.h create mode 100644 pstoraster/gsuid.h create mode 100644 pstoraster/gsutil.c create mode 100644 pstoraster/gsutil.h create mode 100644 pstoraster/gsxfont.h create mode 100644 pstoraster/gx.h create mode 100644 pstoraster/gxacpath.c create mode 100644 pstoraster/gxalloc.h create mode 100644 pstoraster/gxarith.h create mode 100644 pstoraster/gxbcache.c create mode 100644 pstoraster/gxbcache.h create mode 100644 pstoraster/gxbitmap.h create mode 100644 pstoraster/gxccache.c create mode 100644 pstoraster/gxccman.c create mode 100644 pstoraster/gxchar.h create mode 100644 pstoraster/gxcht.c create mode 100644 pstoraster/gxcindex.h create mode 100644 pstoraster/gxclbits.c create mode 100644 pstoraster/gxcldev.h create mode 100644 pstoraster/gxclfile.c create mode 100644 pstoraster/gxclimag.c create mode 100644 pstoraster/gxclio.h create mode 100644 pstoraster/gxclip2.c create mode 100644 pstoraster/gxclip2.h create mode 100644 pstoraster/gxclist.c create mode 100644 pstoraster/gxclist.h create mode 100644 pstoraster/gxclpath.c create mode 100644 pstoraster/gxclpath.h create mode 100644 pstoraster/gxclread.c create mode 100644 pstoraster/gxcmap.c create mode 100644 pstoraster/gxcmap.h create mode 100644 pstoraster/gxcolor2.h create mode 100644 pstoraster/gxcoord.h create mode 100644 pstoraster/gxcpath.c create mode 100644 pstoraster/gxcpath.h create mode 100644 pstoraster/gxcspace.h create mode 100644 pstoraster/gxctable.c create mode 100644 pstoraster/gxctable.h create mode 100644 pstoraster/gxcvalue.h create mode 100644 pstoraster/gxdcconv.c create mode 100644 pstoraster/gxdcconv.h create mode 100644 pstoraster/gxdcolor.c create mode 100644 pstoraster/gxdcolor.h create mode 100644 pstoraster/gxdda.h create mode 100644 pstoraster/gxdevice.h create mode 100644 pstoraster/gxdevmem.h create mode 100644 pstoraster/gxdevrop.h create mode 100644 pstoraster/gxdht.h create mode 100644 pstoraster/gxdither.c create mode 100644 pstoraster/gxdither.h create mode 100644 pstoraster/gxfarith.h create mode 100644 pstoraster/gxfcache.h create mode 100644 pstoraster/gxfill.c create mode 100644 pstoraster/gxfixed.h create mode 100644 pstoraster/gxfmap.h create mode 100644 pstoraster/gxfont.h create mode 100644 pstoraster/gxfont0.h create mode 100644 pstoraster/gxfont1.h create mode 100644 pstoraster/gxfont42.h create mode 100644 pstoraster/gxfrac.h create mode 100644 pstoraster/gxhint1.c create mode 100644 pstoraster/gxhint2.c create mode 100644 pstoraster/gxhint3.c create mode 100644 pstoraster/gxht.c create mode 100644 pstoraster/gxht.h create mode 100644 pstoraster/gxhttile.h create mode 100644 pstoraster/gximage.c create mode 100644 pstoraster/gximage.h create mode 100644 pstoraster/gximage0.c create mode 100644 pstoraster/gximage1.c create mode 100644 pstoraster/gximage2.c create mode 100644 pstoraster/gximage3.c create mode 100644 pstoraster/gximage4.c create mode 100644 pstoraster/gximage5.c create mode 100644 pstoraster/gxiodev.h create mode 100644 pstoraster/gxistate.h create mode 100644 pstoraster/gxline.h create mode 100644 pstoraster/gxlum.h create mode 100644 pstoraster/gxmatrix.h create mode 100644 pstoraster/gxobj.h create mode 100644 pstoraster/gxop1.h create mode 100644 pstoraster/gxpaint.c create mode 100644 pstoraster/gxpaint.h create mode 100644 pstoraster/gxpath.c create mode 100644 pstoraster/gxpath.h create mode 100644 pstoraster/gxpath2.c create mode 100644 pstoraster/gxpcmap.c create mode 100644 pstoraster/gxpcolor.h create mode 100644 pstoraster/gxpcopy.c create mode 100644 pstoraster/gxpdash.c create mode 100644 pstoraster/gxstate.h create mode 100644 pstoraster/gxstroke.c create mode 100644 pstoraster/gxtmap.h create mode 100644 pstoraster/gxtype1.h create mode 100644 pstoraster/gxxfont.h create mode 100644 pstoraster/gzacpath.h create mode 100644 pstoraster/gzcpath.h create mode 100644 pstoraster/gzht.h create mode 100644 pstoraster/gzline.h create mode 100644 pstoraster/gzpath.h create mode 100644 pstoraster/gzstate.h create mode 100644 pstoraster/ialloc.c create mode 100644 pstoraster/ialloc.h create mode 100644 pstoraster/iastate.h create mode 100644 pstoraster/iastruct.h create mode 100644 pstoraster/ibnum.c create mode 100644 pstoraster/ibnum.h create mode 100644 pstoraster/iccinit0.c create mode 100644 pstoraster/ichar.h create mode 100644 pstoraster/icharout.h create mode 100644 pstoraster/icie.h create mode 100644 pstoraster/icolor.h create mode 100644 pstoraster/iconf.c create mode 100644 pstoraster/icsmap.h create mode 100644 pstoraster/idebug.c create mode 100644 pstoraster/idebug.h create mode 100644 pstoraster/idict.c create mode 100644 pstoraster/idict.h create mode 100644 pstoraster/idparam.c create mode 100644 pstoraster/idparam.h create mode 100644 pstoraster/ifilter.h create mode 100644 pstoraster/ifont.h create mode 100644 pstoraster/igc.c create mode 100644 pstoraster/igc.h create mode 100644 pstoraster/igcref.c create mode 100644 pstoraster/igcstr.c create mode 100644 pstoraster/igcstr.h create mode 100644 pstoraster/igstate.h create mode 100644 pstoraster/iimage.h create mode 100644 pstoraster/iinit.c create mode 100644 pstoraster/ilevel.h create mode 100644 pstoraster/ilocate.c create mode 100644 pstoraster/imain.c create mode 100644 pstoraster/imain.h create mode 100644 pstoraster/imemory.h create mode 100644 pstoraster/iminst.h create mode 100644 pstoraster/iname.c create mode 100644 pstoraster/iname.h create mode 100644 pstoraster/inamedef.h create mode 100644 pstoraster/interp.c create mode 100644 pstoraster/interp.h create mode 100644 pstoraster/ipacked.h create mode 100644 pstoraster/iparam.c create mode 100644 pstoraster/iparam.h create mode 100644 pstoraster/iparray.h create mode 100644 pstoraster/ireclaim.c create mode 100644 pstoraster/iref.h create mode 100644 pstoraster/isave.c create mode 100644 pstoraster/isave.h create mode 100644 pstoraster/iscan.c create mode 100644 pstoraster/iscan.h create mode 100644 pstoraster/iscanbin.c create mode 100644 pstoraster/iscannum.c create mode 100644 pstoraster/iscannum.h create mode 100644 pstoraster/iscantab.c create mode 100644 pstoraster/isstate.h create mode 100644 pstoraster/istack.c create mode 100644 pstoraster/istack.h create mode 100644 pstoraster/istream.h create mode 100644 pstoraster/istruct.h create mode 100644 pstoraster/iutil.c create mode 100644 pstoraster/iutil.h create mode 100644 pstoraster/iutil2.c create mode 100644 pstoraster/iutil2.h create mode 100644 pstoraster/ivmspace.h create mode 100644 pstoraster/main.h create mode 100644 pstoraster/malloc_.h create mode 100644 pstoraster/math_.h create mode 100644 pstoraster/memory_.h create mode 100644 pstoraster/opcheck.h create mode 100644 pstoraster/opdef.h create mode 100644 pstoraster/oper.h create mode 100644 pstoraster/opextern.h create mode 100644 pstoraster/ostack.h create mode 100644 pstoraster/pdf_2ps.ps create mode 100644 pstoraster/pdf_base.ps create mode 100644 pstoraster/pdf_draw.ps create mode 100644 pstoraster/pdf_font.ps create mode 100644 pstoraster/pdf_main.ps create mode 100644 pstoraster/pdf_sec.ps create mode 100644 pstoraster/pfbtogs.ps create mode 100644 pstoraster/pstoraster.c create mode 100644 pstoraster/sa85x.h create mode 100644 pstoraster/sbcp.c create mode 100644 pstoraster/sbhc.c create mode 100644 pstoraster/sbhc.h create mode 100644 pstoraster/sbtx.h create mode 100644 pstoraster/sbwbs.c create mode 100644 pstoraster/sbwbs.h create mode 100644 pstoraster/scanchar.h create mode 100644 pstoraster/scf.h create mode 100644 pstoraster/scfd.c create mode 100644 pstoraster/scfdtab.c create mode 100644 pstoraster/scfe.c create mode 100644 pstoraster/scfetab.c create mode 100644 pstoraster/scfx.h create mode 100644 pstoraster/scommon.h create mode 100644 pstoraster/sdct.h create mode 100644 pstoraster/sdctc.c create mode 100644 pstoraster/sdctd.c create mode 100644 pstoraster/sdcte.c create mode 100644 pstoraster/seexec.c create mode 100644 pstoraster/sfile.c create mode 100644 pstoraster/sfilter.h create mode 100644 pstoraster/sfilter1.c create mode 100644 pstoraster/sfilter2.c create mode 100644 pstoraster/shc.c create mode 100644 pstoraster/shc.h create mode 100644 pstoraster/shcgen.c create mode 100644 pstoraster/shcgen.h create mode 100644 pstoraster/siscale.c create mode 100644 pstoraster/siscale.h create mode 100644 pstoraster/sjpeg.h create mode 100644 pstoraster/sjpegc.c create mode 100644 pstoraster/sjpegd.c create mode 100644 pstoraster/sjpege.c create mode 100644 pstoraster/sjpegerr.c create mode 100644 pstoraster/slzwc.c create mode 100644 pstoraster/slzwce.c create mode 100644 pstoraster/slzwd.c create mode 100644 pstoraster/slzwx.h create mode 100644 pstoraster/smtf.c create mode 100644 pstoraster/smtf.h create mode 100644 pstoraster/spcxd.c create mode 100644 pstoraster/spcxx.h create mode 100644 pstoraster/spdiff.c create mode 100644 pstoraster/spdiffx.h create mode 100644 pstoraster/spngp.c create mode 100644 pstoraster/spngpx.h create mode 100644 pstoraster/srld.c create mode 100644 pstoraster/srle.c create mode 100644 pstoraster/srlx.h create mode 100644 pstoraster/sstring.c create mode 100644 pstoraster/sstring.h create mode 100644 pstoraster/stat_.h create mode 100644 pstoraster/std.h create mode 100644 pstoraster/stdio_.h create mode 100644 pstoraster/stdpre.h create mode 100644 pstoraster/store.h create mode 100644 pstoraster/stream.c create mode 100644 pstoraster/stream.h create mode 100644 pstoraster/strimpl.h create mode 100644 pstoraster/string_.h create mode 100644 pstoraster/szlibc.c create mode 100644 pstoraster/szlibd.c create mode 100644 pstoraster/szlibe.c create mode 100644 pstoraster/szlibx.h create mode 100644 pstoraster/time_.h create mode 100644 pstoraster/vmsmath.h create mode 100644 pstoraster/zarith.c create mode 100644 pstoraster/zarray.c create mode 100644 pstoraster/zbseq.c create mode 100644 pstoraster/zchar.c create mode 100644 pstoraster/zchar1.c create mode 100644 pstoraster/zchar2.c create mode 100644 pstoraster/zchar42.c create mode 100644 pstoraster/zcharout.c create mode 100644 pstoraster/zcie.c create mode 100644 pstoraster/zcolor.c create mode 100644 pstoraster/zcolor1.c create mode 100644 pstoraster/zcolor2.c create mode 100644 pstoraster/zcontrol.c create mode 100644 pstoraster/zcrd.c create mode 100644 pstoraster/zcsindex.c create mode 100644 pstoraster/zcssepr.c create mode 100644 pstoraster/zdevcal.c create mode 100644 pstoraster/zdevice.c create mode 100644 pstoraster/zdevice2.c create mode 100644 pstoraster/zdict.c create mode 100644 pstoraster/zdps1.c create mode 100644 pstoraster/zfbcp.c create mode 100644 pstoraster/zfdctc.c create mode 100644 pstoraster/zfdctd.c create mode 100644 pstoraster/zfdcte.c create mode 100644 pstoraster/zfdecode.c create mode 100644 pstoraster/zfile.c create mode 100644 pstoraster/zfileio.c create mode 100644 pstoraster/zfilter.c create mode 100644 pstoraster/zfilter2.c create mode 100644 pstoraster/zfilterx.c create mode 100644 pstoraster/zfname.c create mode 100644 pstoraster/zfont.c create mode 100644 pstoraster/zfont0.c create mode 100644 pstoraster/zfont1.c create mode 100644 pstoraster/zfont2.c create mode 100644 pstoraster/zfont42.c create mode 100644 pstoraster/zfproc.c create mode 100644 pstoraster/zfzlib.c create mode 100644 pstoraster/zgeneric.c create mode 100644 pstoraster/zgstate.c create mode 100644 pstoraster/zhsb.c create mode 100644 pstoraster/zht.c create mode 100644 pstoraster/zht1.c create mode 100644 pstoraster/zht2.c create mode 100644 pstoraster/zimage2.c create mode 100644 pstoraster/ziodev.c create mode 100644 pstoraster/ziodev2.c create mode 100644 pstoraster/zmath.c create mode 100644 pstoraster/zmatrix.c create mode 100644 pstoraster/zmedia2.c create mode 100644 pstoraster/zmisc.c create mode 100644 pstoraster/zmisc1.c create mode 100644 pstoraster/zmisc2.c create mode 100644 pstoraster/zpacked.c create mode 100644 pstoraster/zpaint.c create mode 100644 pstoraster/zpath.c create mode 100644 pstoraster/zpath1.c create mode 100644 pstoraster/zpcolor.c create mode 100644 pstoraster/zrelbit.c create mode 100644 pstoraster/zstack.c create mode 100644 pstoraster/zstring.c create mode 100644 pstoraster/zsysvm.c create mode 100644 pstoraster/ztoken.c create mode 100644 pstoraster/ztype.c create mode 100644 pstoraster/zupath.c create mode 100644 pstoraster/zusparam.c create mode 100644 pstoraster/zvmem.c create mode 100644 pstoraster/zvmem2.c create mode 100644 scheduler/Makefile create mode 100644 scheduler/auth.c create mode 100644 scheduler/auth.h create mode 100644 scheduler/classes.c create mode 100644 scheduler/classes.h create mode 100644 scheduler/client.c create mode 100644 scheduler/client.h create mode 100644 scheduler/conf.c create mode 100644 scheduler/conf.h create mode 100644 scheduler/cupsd.h create mode 100644 scheduler/dirsvc.c create mode 100644 scheduler/dirsvc.h create mode 100644 scheduler/ipp.c create mode 100644 scheduler/job.c create mode 100644 scheduler/job.h create mode 100644 scheduler/main.c create mode 100644 scheduler/printers.c create mode 100644 scheduler/printers.h create mode 100644 systemv/Makefile create mode 100644 systemv/accept.c create mode 100644 systemv/cancel.c create mode 100644 systemv/lp.c create mode 100644 systemv/lpstat.c diff --git a/LICENSE.html b/LICENSE.html new file mode 100644 index 0000000000..5fad5148d3 --- /dev/null +++ b/LICENSE.html @@ -0,0 +1,269 @@ + + + Software License Agreement - Common UNIX Printing System + + + + +

Aladdin Free Public License

+ +

(Version 6, June 17, 1997)

+ +

Copyright © 1994, 1995, 1997 Aladdin Enterprises,

+Menlo Park, California, U.S.A. All rights reserved.

+ +
+NOTE: This License is not the same as any of the GNU Licenses published +by the Free Software Foundation. Its terms are substantially different +from those of the GNU Licenses. If you are familiar with the GNU +Licenses, please read this license with extra care. +
+ +

Aladdin Enterprises hereby grants to anyone the permission to apply +this License to their own work, as long as the entire License +(including the above notices and this paragraph) is copied with no +changes, additions, or deletions except for changing the first +paragraph of Section 0 to include a suitable description of the work to +which the license is being applied and of the person or entity that +holds the copyright in the work, and, if the License is being applied +to a work created in a country other than the United States, replacing +the first paragraph of Section 6 with an appropriate reference to the +laws of the appropriate country.

+ +

0. Subject Matter

+ +This License applies to the Common UNIX Printing System ("PROGRAM"). +The Common UNIX Printing System is a copyrighted work whose copyright +is held by Easy Software Products (the "LICENSOR"). The Common UNIX +Printing System, CUPS, and the CUPS logo are the trademark property of +Easy Software Products. + +

A "work based on the PROGRAM" means either the PROGRAM or any +derivative work of the PROGRAM, as defined in the United States +Copyright Act of 1976, such as a translation or a modification. + +

BY MODIFYING OR DISTRIBUTING THE PROGRAM (OR ANY WORK BASED ON THE +PROGRAM), YOU INDICATE YOUR ACCEPTANCE OF THIS LICENSE TO DO SO, AND +ALL ITS TERMS AND CONDITIONS FOR COPYING, DISTRIBUTING OR MODIFYING THE +PROGRAM OR WORKS BASED ON IT. NOTHING OTHER THAN THIS LICENSE GRANTS +YOU PERMISSION TO MODIFY OR DISTRIBUTE THE PROGRAM OR ITS DERIVATIVE +WORKS. THESE ACTIONS ARE PROHIBITED BY LAW. IF YOU DO NOT ACCEPT THESE +TERMS AND CONDITIONS, DO NOT MODIFY OR DISTRIBUTE THE PROGRAM. + +

1. Licenses

+ +LICENSOR hereby grants you the following rights, provided that you comply +with all of the restrictions set forth in this License and provided, +further, that you distribute an unmodified copy of this License with the +PROGRAM: + +
    + +
  1. You may copy and distribute literal (i.e., verbatim) copies + of the PROGRAM's source code as you receive it throughout the + world, in any medium.

    + +
  2. You may modify the PROGRAM, create works based on the + PROGRAM and distribute copies of such throughout the world, in + any medium.

    + +
+ +

2. Restrictions

+ +This license is subject to the following restrictions: + +
    + +
  1. Distribution of the PROGRAM or any work based on the + PROGRAM by a commercial organization to any third party is + prohibited if any payment is made in connection with such + distribution, whether directly (as in payment for a copy of the + PROGRAM) or indirectly (as in payment for some service related + to the PROGRAM, or payment for some product or service that + includes a copy of the PROGRAM "without charge"; these are only + examples, and not an exhaustive enumeration of prohibited + activities). The following methods of distribution involving + payment shall not in and of themselves be a violation of this + restriction:

    + +
      + +
    1. Posting the PROGRAM on a public access information + storage and retrieval service for which a fee is + received for retrieving information (such as an on-line + service), provided that the fee is not + content-dependent (i.e., the fee would be the same for + retrieving the same volume of information consisting of + random data) and that access to the service and to the + PROGRAM is available independent of any other product + or service. An example of a service that does not fall + under this section is an on-line service that is + operated by a company and that is only available to + customers of that company. (This is not an exhaustive + enumeration.)

      + +
    2. Distributing the PROGRAM on removable + computer-readable media, provided that the files + containing the PROGRAM are reproduced entirely and + verbatim on such media, that all information on such + media be redistributable for non-commercial purposes + without charge, and that such media are distributed by + themselves (except for accompanying documentation) + independent of any other product or service. Examples + of such media include CD-ROM, magnetic tape, and + optical storage media. (This is not intended to be an + exhaustive list.) An example of a distribution that + does not fall under this section is a CD-ROM included + in a book or magazine. (This is not an exhaustive + enumeration.)

      + +
    + +
  2. Activities other than copying, distribution and + modification of the PROGRAM are not subject to this License and + they are outside its scope. Functional use (running) of the + PROGRAM is not restricted, and any output produced through the + use of the PROGRAM is subject to this license only if its + contents constitute a work based on the PROGRAM (independent of + having been made by running the PROGRAM).

    + +
  3. You must meet all of the following conditions with respect to any work + that you distribute or publish that in whole or in part contains or is + derived from the PROGRAM or any part thereof ("the Work"):

    + +
      + +
    1. If you have modified the PROGRAM, you must cause + the Work to carry prominent notices stating that you + have modified the PROGRAM's files and the date of any + change;

      + +
    2. You must cause the Work to be licensed as a whole + and at no charge to all third parties under the terms + of this License;

      + +
    3. If the Work normally reads commands interactively + when run, you must cause it, at each time the Work + commences operation, to print or display an + announcement including an appropriate copyright notice + and a notice that there is no warranty (or else, saying + that you provide a warranty). Such notice must also + state that users may redistribute the Work only under + the conditions of this License and tell the user how to + view the copy of this License included with the Work. + (Exceptions: if the PROGRAM is interactive but normally + prints or displays such an announcement only at the + request of a user, such as in an "About box", the Work + is required to print or display the notice only under + the same circumstances; if the PROGRAM itself is + interactive but does not normally print such an + announcement, the Work is not required to print an + announcement.);

      + +
    4. You must accompany the Work with the complete + corresponding machine-readable source code, delivered + on a medium customarily used for software interchange. + The source code for a work means the preferred form of + the work for making modifications to it. For an + executable work, complete source code means all the + source code for all modules it contains, plus any + associated interface definition files, plus the scripts + used to control compilation and installation of the + executable code. If you distribute with the Work any + component that is normally distributed (in either + source or binary form) with the major components + (compiler, kernel, and so on) of the operating system + on which the executable runs, you must also distribute + the source code of that component if you have it and + are allowed to do so;

      + +
    5. If you distribute any written or printed material + at all with the Work, such material must include either + a written copy of this License, or a prominent written + indication that the Work is covered by this License and + written instructions for printing and/or displaying the + copy of the License on the distribution medium;

      + +
    6. You may not impose any further restrictions on the + recipient's exercise of the rights granted herein.

      + +
    + +
+ +If distribution of executable or object code is made by offering the +equivalent ability to copy from a designated place, then offering +equivalent ability to copy the source code from the same place counts +as distribution of the source code, even though third parties are not +compelled to copy the source code along with the object code. + +

3. Reservation of Rights

+ +No rights are granted to the PROGRAM except as expressly set forth +herein. You may not copy, modify, sublicense, or distribute the PROGRAM +except as expressly provided under this License. Any attempt otherwise +to copy, modify, sublicense or distribute the PROGRAM is void, and will +automatically terminate your rights under this License. However, +parties who have received copies, or rights, from you under this +License will not have their licenses terminated so long as such parties +remain in full compliance. + +

4. Other Restrictions

+ +If the distribution and/or use of the PROGRAM is restricted in certain +countries for any reason, LICENSOR may add an explicit geographical +distribution limitation excluding those countries, so that distribution +is permitted only in or among countries not thus excluded. In such +case, this License incorporates the limitation as if written in the +body of this License. + +

5. Limitations

+ +THE PROGRAM IS PROVIDED TO YOU "AS IS", WITHOUT WARRANTY. THERE IS NO +WARRANTY FOR THE PROGRAM, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT +NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. +THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS +WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +

IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL LICENSOR, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING +ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT +OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED +BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY +OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF +THE POSSIBILITY OF SUCH DAMAGES. + +

6. General

+ +This License is governed by the laws of the State of Maryland, U.S.A., +excluding choice of law rules. + +

If any part of this License is found to be in conflict with the law, +that part shall be interpreted in its broadest meaning consistent with +the law, and no other parts of the License shall be affected. + +

For United States Government users, the PROGRAM is provided with +RESTRICTED RIGHTS. If you are a unit or agency of the United States +Government or are acquiring the Software for any such unit or agency, +the following apply: + +

+If the unit or agency is the Department of Defense ("DOD"), the +Software and its documentation are classified as "commercial computer +software" and "commercial computer software documentation" respectively +and, pursuant to DFAR Section 227.7202, the Government is acquiring the +Software and its documentation in accordance with the terms of this +License. If the unit or agency is other than DOD, the Software and its +documentation are classified as "commercial computer software" and +"commercial computer software documentation" respectively and, pursuant +to FAR Section 12.212, the Government is acquiring the Software and its +documentation in accordance with the terms of this License. +
+ + + diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000000..20c5100834 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,223 @@ + Aladdin Free Public License + + (Version 6, June 17, 1997) + + Copyright © 1994, 1995, 1997 Aladdin Enterprises, + + Menlo Park, California, U.S.A. All rights reserved. + + NOTE: This License is not the same as any of the GNU Licenses + published by the Free Software Foundation. Its terms are + substantially different from those of the GNU Licenses. If you are + familiar with the GNU Licenses, please read this license with + extra care. + +Aladdin Enterprises hereby grants to anyone the permission to apply this +License to their own work, as long as the entire License (including the +above notices and this paragraph) is copied with no changes, additions, or +deletions except for changing the first paragraph of Section 0 to include a +suitable description of the work to which the license is being applied and +of the person or entity that holds the copyright in the work, and, if the +License is being applied to a work created in a country other than the +United States, replacing the first paragraph of Section 6 with an +appropriate reference to the laws of the appropriate country. + +0. Subject Matter + +This License applies to the Common UNIX Printing System ("PROGRAM"). The +Common UNIX Printing System is a copyrighted work whose copyright is held by +Easy Software Products (the "LICENSOR"). The Common UNIX Printing System, +CUPS, and the CUPS logo are the trademark property of Easy Software +Products. + +A "work based on the PROGRAM" means either the PROGRAM or any derivative +work of the PROGRAM, as defined in the United States Copyright Act of 1976, +such as a translation or a modification. + +BY MODIFYING OR DISTRIBUTING THE PROGRAM (OR ANY WORK BASED ON THE PROGRAM), +YOU INDICATE YOUR ACCEPTANCE OF THIS LICENSE TO DO SO, AND ALL ITS TERMS AND +CONDITIONS FOR COPYING, DISTRIBUTING OR MODIFYING THE PROGRAM OR WORKS BASED +ON IT. NOTHING OTHER THAN THIS LICENSE GRANTS YOU PERMISSION TO MODIFY OR +DISTRIBUTE THE PROGRAM OR ITS DERIVATIVE WORKS. THESE ACTIONS ARE PROHIBITED +BY LAW. IF YOU DO NOT ACCEPT THESE TERMS AND CONDITIONS, DO NOT MODIFY OR +DISTRIBUTE THE PROGRAM. + +1. Licenses + +LICENSOR hereby grants you the following rights, provided that you comply +with all of the restrictions set forth in this License and provided, +further, that you distribute an unmodified copy of this License with the +PROGRAM: + + a. You may copy and distribute literal (i.e., verbatim) copies of the + PROGRAM's source code as you receive it throughout the world, in any + medium. + + b. You may modify the PROGRAM, create works based on the PROGRAM and + distribute copies of such throughout the world, in any medium. + +2. Restrictions + +This license is subject to the following restrictions: + + a. Distribution of the PROGRAM or any work based on the PROGRAM by a + commercial organization to any third party is prohibited if any payment + is made in connection with such distribution, whether directly (as in + payment for a copy of the PROGRAM) or indirectly (as in payment for + some service related to the PROGRAM, or payment for some product or + service that includes a copy of the PROGRAM "without charge"; these are + only examples, and not an exhaustive enumeration of prohibited + activities). The following methods of distribution involving payment + shall not in and of themselves be a violation of this restriction: + + i. Posting the PROGRAM on a public access information storage and + retrieval service for which a fee is received for retrieving + information (such as an on-line service), provided that the fee is + not content-dependent (i.e., the fee would be the same for + retrieving the same volume of information consisting of random + data) and that access to the service and to the PROGRAM is + available independent of any other product or service. An example + of a service that does not fall under this section is an on-line + service that is operated by a company and that is only available + to customers of that company. (This is not an exhaustive + enumeration.) + + ii. Distributing the PROGRAM on removable computer-readable media, + provided that the files containing the PROGRAM are reproduced + entirely and verbatim on such media, that all information on such + media be redistributable for non-commercial purposes without + charge, and that such media are distributed by themselves (except + for accompanying documentation) independent of any other product + or service. Examples of such media include CD-ROM, magnetic tape, + and optical storage media. (This is not intended to be an + exhaustive list.) An example of a distribution that does not fall + under this section is a CD-ROM included in a book or magazine. + (This is not an exhaustive enumeration.) + + b. Activities other than copying, distribution and modification of the + PROGRAM are not subject to this License and they are outside its scope. + Functional use (running) of the PROGRAM is not restricted, and any + output produced through the use of the PROGRAM is subject to this + license only if its contents constitute a work based on the PROGRAM + (independent of having been made by running the PROGRAM). + + c. You must meet all of the following conditions with respect to any work + that you distribute or publish that in whole or in part contains or is + derived from the PROGRAM or any part thereof ("the Work"): + + i. If you have modified the PROGRAM, you must cause the Work to carry + prominent notices stating that you have modified the PROGRAM's + files and the date of any change; + + ii. You must cause the Work to be licensed as a whole and at no charge + to all third parties under the terms of this License; + + iii. If the Work normally reads commands interactively when run, you + must cause it, at each time the Work commences operation, to print + or display an announcement including an appropriate copyright + notice and a notice that there is no warranty (or else, saying + that you provide a warranty). Such notice must also state that + users may redistribute the Work only under the conditions of this + License and tell the user how to view the copy of this License + included with the Work. (Exceptions: if the PROGRAM is interactive + but normally prints or displays such an announcement only at the + request of a user, such as in an "About box", the Work is required + to print or display the notice only under the same circumstances; + if the PROGRAM itself is interactive but does not normally print + such an announcement, the Work is not required to print an + announcement.); + + iv. You must accompany the Work with the complete corresponding + machine-readable source code, delivered on a medium customarily + used for software interchange. The source code for a work means + the preferred form of the work for making modifications to it. For + an executable work, complete source code means all the source code + for all modules it contains, plus any associated interface + definition files, plus the scripts used to control compilation and + installation of the executable code. If you distribute with the + Work any component that is normally distributed (in either source + or binary form) with the major components (compiler, kernel, and + so on) of the operating system on which the executable runs, you + must also distribute the source code of that component if you have + it and are allowed to do so; + + v. If you distribute any written or printed material at all with the + Work, such material must include either a written copy of this + License, or a prominent written indication that the Work is + covered by this License and written instructions for printing + and/or displaying the copy of the License on the distribution + medium; + + vi. You may not impose any further restrictions on the recipient's + exercise of the rights granted herein. + +If distribution of executable or object code is made by offering the +equivalent ability to copy from a designated place, then offering equivalent +ability to copy the source code from the same place counts as distribution +of the source code, even though third parties are not compelled to copy the +source code along with the object code. + +3. Reservation of Rights + +No rights are granted to the PROGRAM except as expressly set forth herein. +You may not copy, modify, sublicense, or distribute the PROGRAM except as +expressly provided under this License. Any attempt otherwise to copy, +modify, sublicense or distribute the PROGRAM is void, and will automatically +terminate your rights under this License. However, parties who have received +copies, or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + +4. Other Restrictions + +If the distribution and/or use of the PROGRAM is restricted in certain +countries for any reason, LICENSOR may add an explicit geographical +distribution limitation excluding those countries, so that distribution is +permitted only in or among countries not thus excluded. In such case, this +License incorporates the limitation as if written in the body of this +License. + +5. Limitations + +THE PROGRAM IS PROVIDED TO YOU "AS IS", WITHOUT WARRANTY. THERE IS NO +WARRANTY FOR THE PROGRAM, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. THE ENTIRE +RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD +THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + +IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL +LICENSOR, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM +AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, +SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR +INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR +DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES +OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + +6. General + +This License is governed by the laws of the State of Maryland, U.S.A., +excluding choice of law rules. + +If any part of this License is found to be in conflict with the law, that +part shall be interpreted in its broadest meaning consistent with the law, +and no other parts of the License shall be affected. + +For United States Government users, the PROGRAM is provided with RESTRICTED +RIGHTS. If you are a unit or agency of the United States Government or are +acquiring the Software for any such unit or agency, the following apply: + + If the unit or agency is the Department of Defense ("DOD"), the + Software and its documentation are classified as "commercial + computer software" and "commercial computer software + documentation" respectively and, pursuant to DFAR Section + 227.7202, the Government is acquiring the Software and its + documentation in accordance with the terms of this License. If the + unit or agency is other than DOD, the Software and its + documentation are classified as "commercial computer software" and + "commercial computer software documentation" respectively and, + pursuant to FAR Section 12.212, the Government is acquiring the + Software and its documentation in accordance with the terms of + this License. diff --git a/Makedefs.in b/Makedefs.in new file mode 100644 index 0000000000..2e9c99fff8 --- /dev/null +++ b/Makedefs.in @@ -0,0 +1,111 @@ +# +# "$Id$" +# +# Common makefile definitions for the Common UNIX Printing System (CUPS). +# +# @configure_input@ +# +# Copyright 1997-1999 by Easy Software Products, all rights reserved. +# +# These coded instructions, statements, and computer programs are the +# property of Easy Software Products and are protected by Federal +# copyright law. Distribution and use rights are outlined in the file +# "LICENSE.txt" which should have been included with this file. If this +# file is missing or damaged please contact Easy Software Products +# at: +# +# Attn: CUPS Licensing Information +# Easy Software Products +# 44145 Airport View Drive, Suite 204 +# Hollywood, Maryland 20636-3111 USA +# +# Voice: (301) 373-9603 +# EMail: cups-info@cups.org +# WWW: http://www.cups.org +# + +# +# Programs... +# + +AR = @AR@ +AWK = @AWK@ +CC = @CC@ +CP = @CP@ +HTMLDOC = @HTMLDOC@ +LN = /bin/ln -sf +MKDIR = @MKDIR@ -p +NROFF = @GROFF@ -T ascii +RANLIB = @RANLIB@ +RM = @RM@ -f +SHELL = /bin/sh + +# +# Program options... +# +# OPTIM defines the common compiler optimization/debugging options. +# OPTIONS defines other compile-time options (currently only -dDEBUG for +# extra debug info) +# + +ARFLAGS = crvs +CFLAGS = @CFLAGS@ $(OPTIM) -I.. $(OPTIONS) +IMGLIBS = @IMGLIBS@ $(LIBS) -lm +LDFLAGS = @LDFLAGS@ $(OPTIM) +LIBS = @LIBS@ -L../cups -lcups +OPTIM = @OPTIM@ +OPTIONS = + +# +# Directories... +# +# The first section uses the GNU names (which are *extremely* +# difficult to find in a makefile because they are lowercase...) +# We have to define these first because autoconf uses ${prefix} +# and ${exec_prefix} for most of the other directories... +# +# This is immediately followed by definition in ALL CAPS for the +# needed directories... +# + +bindir = @bindir@ +datadir = @datadir@ +exec_prefix = @exec_prefix@ +includedir = @includedir@ +infodir = @infodir@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +oldincludedir = @oldincludedir@ +prefix = @prefix@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +top_srcdir = @top_srcdir@ + +BINDIR = @bindir@ +DATADIR = @CUPS_DATADIR@ +INCLUDEDIR = $(includedir)/cups +LIBDIR = $(libdir) +LOCALEDIR = @CUPS_LOCALEDIR@ +MANDIR = @mandir@ +SBINDIR = @sbindir@ +SERVERROOT = @CUPS_SERVERROOT@ + +# +# Rules... +# + +.SUFFIXES: .a .c .h .1 .2 .3 .4 .5 .6 .7 .8 .o .z +.c.o: + $(CC) $(CFLAGS) -c $< +.1.z .2.z .3.z .4.z .5.z .6.z .7.z .8.z: + $(NROFF) -man $< >t + pack -f t + mv t.z $@ + +# +# End of "$Id$" +# diff --git a/Makefile b/Makefile new file mode 100644 index 0000000000..775df8cff6 --- /dev/null +++ b/Makefile @@ -0,0 +1,67 @@ +# +# "$Id$" +# +# Top-level Makefile for the Common UNIX Printing System (CUPS). +# +# Copyright 1997-1999 by Easy Software Products, all rights reserved. +# +# These coded instructions, statements, and computer programs are the +# property of Easy Software Products and are protected by Federal +# copyright law. Distribution and use rights are outlined in the file +# "LICENSE.txt" which should have been included with this file. If this +# file is missing or damaged please contact Easy Software Products +# at: +# +# Attn: CUPS Licensing Information +# Easy Software Products +# 44145 Airport View Drive, Suite 204 +# Hollywood, Maryland 20636-3111 USA +# +# Voice: (301) 373-9603 +# EMail: cups-info@cups.org +# WWW: http://www.cups.org +# + +include Makedefs + +# +# Directories to make... +# + +DIRS = cups backend berkeley cgi-bin filter man pstoraster \ + scheduler systemv + +# +# Make all targets... +# + +all: + for dir in $(DIRS); do\ + (cd $$dir; make);\ + done + +# +# Remove object and target files... +# + +clean: + for dir in $(DIRS); do\ + (cd $$dir; make clean);\ + done + +# +# Install object and target files... +# + +install: + for dir in $(DIRS); do\ + (cd $$dir; make install);\ + done + (cd conf; make install) + (cd data; make install) + (cd doc; make install) + (cd fonts; make install) + +# +# End of "$Id$". +# diff --git a/README.html b/README.html new file mode 100644 index 0000000000..6b222b172f --- /dev/null +++ b/README.html @@ -0,0 +1,243 @@ + + + README - Common UNIX Printing System + + + +

README - CUPS v1.0b1

+ +

Contents

+ + + +

Introduction

+ +The Common UNIX Printing System provides a portable printing layer for +UNIX® operating systems. It has been developed by Easy Software +Products to promote a standard printing solution for all UNIX vendors +and users. CUPS provides the System V and Berkeley command-line +interfaces. + +

CUPS uses the Internet Printing Protocol (IETF-IPP) as the basis +for managing print jobs and queues. The Line Printer Daemon (LPD, +RFC1179), Server Message Block (SMB), and AppSocket protocols are also +supported with reduced functionality. + +

CUPS adds network printer browsing and PostScript Printer +Description ("PPD")-based printing options to support real +world applications under UNIX. + +

CUPS also includes a customized version of GNU GhostScript (currently +based off GNU GhostScript 4.03) and an image file RIP that can be used to +support non-PostScript printers. + +

Requirements

+ +You'll need an ANSI C compiler to build CUPS on your system. As its name +implies, CUPS is designed to run on the UNIX operating system, however +the CUPS interface library and most of the filters and backends supplied +with CUPS should also run under Microsoft® Windows®. + +

For the image file filters you'll need the JPEG, PNG, TIFF, and ZLIB +libraries. CUPS will build without these, but with reduced functionality. + +

If you make changes to the man pages you'll need GNU groff or another +nroff-like package. + +

The documentation is formatted using the HTMLDOC software (again, not +needed unless you make changes.) + +

Compiling CUPS

+ +CUPS uses GNU autoconf to configure the makefiles and source code for your +system. To configure CUPS for your system type: + + + +The default installation will put the CUPS software in the /usr +and /var directories on your system, which will overwrite any +existing printing commands on your system. To install the CUPS software in +another location use the --prefix option: + + + +Once you have configured things, just type: + + + +to build the software. + +

Installing the Software

+ +To install the software type: + + + +

Configuring the Software

+ +Before you run CUPS for the first time you'll need to edit the CUPS +configuration files which are normally located in /var/cups/conf. + + + +In addition to the files in the /var/cups/conf directory, you'll also need +to copy PPD files for each printer to the /var/cups/ppd directory. If you +don't have a PPD file for your printer, the drivers will still work, just +with reduced functionality. + +

Running the Software

+ +Once you have configured the software you can start the CUPS daemon by +typing: + + + +

Using the Software

+ +Once you have installed the software, you can use the normal lp or lpr +commands to print jobs. If you installed the software under /usr then +you shouldn't have to reconfigure any applications to recognize the new +printing system. + +

One of the advantages of CUPS is that you don't always have to send +PostScript or Text files to your printers. If you have a JPEG file, you +can just type "lp filename.jpg" and CUPS will handle converting it for +you! + +

You can monitor the status of jobs via the lpstat command or with your +web browser by pointing it at "http://localhost:631". + +

Known Problems

+ +The following known problems are being worked on and should be resolved for +the second beta release of CUPS: + + + +CUPS has been built and tested on the following operating systems: + + + +The client libraries and filters have been successfully compiled under +Microsoft Windows using Visual C++ 6.0. + +

Reporting Problems

+ +If you have problems, please send an email to +cups-support@cups.org. Include +your operating system and version, compiler and version, and any errors +or problems you've run into. + +

Other Resources

+ +See the CUPS web site at "http://www.cups.org" for other site links. + +

You can subscribe to the CUPS mailing list by sending a message containing +"subscribe cups" to majordomo@cups.org. +This list is provided to discuss problems, questions, and improvements to +the CUPS software. New releases of CUPS are announced to this list as well. + +

Legal Stuff

+ +CUPS is Copyright 1993-1999 by Easy Software Products. CUPS, the CUPS logo, +and the Common UNIX Printing System are the trademark property of Easy Software +Products. + +

CUPS is provided under the terms of the +Aladdin Free Public License +which is located in the files "LICENSE.html" and "LICENSE.txt". For commercial +licensing information, please contact: + +

+ +

If you're interested in a complete, commercial printing solution for UNIX, +check out our ESP Print software at +http://www.easysw.com/print.html. + + + diff --git a/README.txt b/README.txt new file mode 100644 index 0000000000..f753603854 --- /dev/null +++ b/README.txt @@ -0,0 +1,192 @@ +README - CUPS v1.0b1 + +CONTENTS + + * Introduction + * Requirements + * Compiling CUPS + * Configuring the Software + * Running the Software + * Using the Software + * Known Problems + * Reporting Problems + * Other Resources + * Legal Stuff + +INTRODUCTION + +The Common UNIX Printing System provides a portable printing layer for UNIX® +operating systems. It has been developed by Easy Software Products to +promote a standard printing solution for all UNIX vendors and users. CUPS +provides the System V and Berkeley command-line interfaces. + +CUPS uses the Internet Printing Protocol (IETF-IPP) as the basis for +managing print jobs and queues. The Line Printer Daemon (LPD, RFC1179), +Server Message Block (SMB), and AppSocket protocols are also supported with +reduced functionality. + +CUPS adds network printer browsing and PostScript Printer Description +("PPD")-based printing options to support real world applications under +UNIX. + +CUPS also includes a customized version of GNU GhostScript (currently based +off GNU GhostScript 4.03) and an image file RIP that can be used to support +non-PostScript printers. + +REQUIREMENTS + +You'll need an ANSI C compiler to build CUPS on your system. As its name +implies, CUPS is designed to run on the UNIX operating system, however the +CUPS interface library and most of the filters and backends supplied with +CUPS should also run under Microsoft® Windows®. + +For the image file filters you'll need the JPEG, PNG, TIFF, and ZLIB +libraries. CUPS will build without these, but with reduced functionality. + +If you make changes to the man pages you'll need GNU groff or another +nroff-like package. + +The documentation is formatted using the HTMLDOC software (again, not needed +unless you make changes.) + +COMPILING CUPS + +CUPS uses GNU autoconf to configure the makefiles and source code for your +system. To configure CUPS for your system type: + + % ./configure ENTER + +The default installation will put the CUPS software in the /usr and /var +directories on your system, which will overwrite any existing printing +commands on your system. To install the CUPS software in another location +use the --prefix option: + + % ./configure --prefix=/usr/local ENTER + +Once you have configured things, just type: + + % make ENTER + +to build the software. + +INSTALLING THE SOFTWARE + +To install the software type: + + % make install ENTER + +CONFIGURING THE SOFTWARE + +Before you run CUPS for the first time you'll need to edit the CUPS +configuration files which are normally located in /var/cups/conf. + + The cupsd.conf file configures all of the "global" server settings and + access control. The default settings are usually appropriate for most + environments. + + The printers.conf file configures each printer queue. You'll need to + add a listing for each printer on your system. + + The classes.conf file configures each printer class. You'll need to add + a listing for each printer class you want. + + The mime.types file defines all of the recognized file types. You don't + normally have to edit this file. + + The mime.convs file defines all of the file conversion filters. You + don't normally have to edit this file. + +In addition to the files in the /var/cups/conf directory, you'll also need +to copy PPD files for each printer to the /var/cups/ppd directory. If you +don't have a PPD file for your printer, the drivers will still work, just +with reduced functionality. + +RUNNING THE SOFTWARE + +Once you have configured the software you can start the CUPS daemon by +typing: + + % /usr/sbin/cupsd & ENTER + +USING THE SOFTWARE + +Once you have installed the software, you can use the normal lp or lpr +commands to print jobs. If you installed the software under /usr then you +shouldn't have to reconfigure any applications to recognize the new printing +system. + +One of the advantages of CUPS is that you don't always have to send +PostScript or Text files to your printers. If you have a JPEG file, you can +just type "lp filename.jpg" and CUPS will handle converting it for you! + +You can monitor the status of jobs via the lpstat command or with your web +browser by pointing it at "http://localhost:631". + +KNOWN PROBLEMS + +The following known problems are being worked on and should be resolved for +the second beta release of CUPS: + + * Documentation is not completed. + * The lpadmin command is currently not provided. + * The lpq command is currently not provided. + * The lpc command currently only supports the help and status commands. + * While both GNU GhostScript and the CUPS image RIP are provided, no + sample raster printer driver is provided. The final release of CUPS + will include a PCL printer driver. + * Automatic classing is currently not supported. + * The CUPS server should disable core dumps by filters, backends, and CGI + programs. + * The CUPS server should increase the FD limit to the maximum allowed on + the system. + * The CUPS server should close stdin, stdout, and stderr and run in the + background ("daemon" mode...) + * The class and job CGIs are currently not provided. + +CUPS has been built and tested on the following operating systems: + + * Digital UNIX 4.0d + * HP-UX 10.20 and 11.0 + * IRIX 5.3, 6.2, 6.5.3 + * Linux (RedHat 5.2) + * Solaris 2.5.1, 2.6, 2.7 (aka 7) + +The client libraries and filters have been successfully compiled under +Microsoft Windows using Visual C++ 6.0. + +REPORTING PROBLEMS + +If you have problems, please send an email to cups-support@cups.org. Include +your operating system and version, compiler and version, and any errors or +problems you've run into. + +OTHER RESOURCES + +See the CUPS web site at "http://www.cups.org" for other site links. + +You can subscribe to the CUPS mailing list by sending a message containing +"subscribe cups" to majordomo@cups.org. This list is provided to discuss +problems, questions, and improvements to the CUPS software. New releases of +CUPS are announced to this list as well. + +LEGAL STUFF + +CUPS is Copyright 1993-1999 by Easy Software Products. CUPS, the CUPS logo, +and the Common UNIX Printing System are the trademark property of Easy +Software Products. + +CUPS is provided under the terms of the Aladdin Free Public License which is +located in the files "LICENSE.html" and "LICENSE.txt". For commercial +licensing information, please contact: + + Attn: CUPS Licensing Information + Easy Software Products + 44141 Airport View Drive, Suite 204 + Hollywood, Maryland 20636-3111 USA + + Voice: +1.301.373.9603 + Email: cups-info@cups.org + WWW: http://www.cups.org + +If you're interested in a complete, commercial printing solution for UNIX, +check out our ESP Print software at http://www.easysw.com/print.html. diff --git a/backend/Makefile b/backend/Makefile new file mode 100644 index 0000000000..7cbd219f0c --- /dev/null +++ b/backend/Makefile @@ -0,0 +1,98 @@ +# +# "$Id$" +# +# Backend makefile for the Common UNIX Printing System (CUPS). +# +# Copyright 1997-1999 by Easy Software Products, all rights reserved. +# +# These coded instructions, statements, and computer programs are the +# property of Easy Software Products and are protected by Federal +# copyright law. Distribution and use rights are outlined in the file +# "LICENSE.txt" which should have been included with this file. If this +# file is missing or damaged please contact Easy Software Products +# at: +# +# Attn: CUPS Licensing Information +# Easy Software Products +# 44145 Airport View Drive, Suite 204 +# Hollywood, Maryland 20636-3111 USA +# +# Voice: (301) 373-9603 +# EMail: cups-info@cups.org +# WWW: http://www.cups.org +# + +include ../Makedefs + +TARGETS = lpd parallel serial smb socket +OBJS = lpd.o parallel.o serial.o smb.o socket.o + +# +# Make all targets... +# + +all: $(TARGETS) + +# +# Clean all object files... +# + +clean: + rm -f $(OBJS) $(TARGETS) + +# +# Install all targets... +# + +install: + -$(MKDIR) $(SERVERROOT)/backend + $(CP) $(TARGETS) $(SERVERROOT)/backend + +# +# lpd +# + +lpd: lpd.o ../cups/libcups.a + $(CC) $(LDFLAGS) -o lpd lpd.o $(LIBS) + +lpd.o: ../cups/cups.h ../Makedefs + +# +# parallel +# + +parallel: parallel.o ../cups/libcups.a + $(CC) $(LDFLAGS) -o parallel parallel.o $(LIBS) + +parallel.o: ../cups/cups.h ../Makedefs + +# +# serial +# + +serial: serial.o ../cups/libcups.a + $(CC) $(LDFLAGS) -o serial serial.o $(LIBS) + +serial.o: ../cups/cups.h ../Makedefs + +# +# smb +# + +smb: smb.o ../cups/libcups.a + $(CC) $(LDFLAGS) -o smb smb.o $(LIBS) + +smb.o: ../cups/cups.h ../Makedefs + +# +# socket +# + +socket: socket.o ../cups/libcups.a + $(CC) $(LDFLAGS) -o socket socket.o $(LIBS) + +socket.o: ../cups/cups.h ../Makedefs + +# +# End of "$Id$". +# diff --git a/backend/lpd.c b/backend/lpd.c new file mode 100644 index 0000000000..276cde3a7f --- /dev/null +++ b/backend/lpd.c @@ -0,0 +1,394 @@ +/* + * "$Id$" + * + * Line Printer Daemon backend for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-1999 by Easy Software Products, all rights reserved. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44145 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * main() - Send a file to the printer or server. + * lpd_command() - Send an LPR command sequence and wait for a reply. + * lpd_queue() - Queue a file using the Line Printer Daemon protocol. + */ + +/* + * Include necessary headers. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(WIN32) || defined(__EMX__) +# include +#else +# include +# include +# include +# include +#endif /* WIN32 || __EMX__ */ + +extern int rresvport(int *port); /* Hello? No prototype for this... */ + + +/* + * Local functions... + */ + +static int lpd_command(int lpd_fd, char *format, ...); +static int lpd_queue(char *hostname, char *printer, char *filename, + char *user, int copies); + + +/* + * 'main()' - Send a file to the printer or server. + * + * Usage: + * + * printer-uri job-id user title copies options [file] + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line arguments (6 or 7) */ + char *argv[]) /* I - Command-line arguments */ +{ + char method[255], /* Method in URI */ + hostname[1024], /* Hostname */ + username[255], /* Username info (not used) */ + resource[1024], /* Resource info (printer name) */ + filename[1024]; /* File to print */ + int port; /* Port number (not used) */ + int status; /* Status of LPD job */ + + + if (argc < 6 || argc > 7) + { + fprintf(stderr, "Usage: %s job-id user title copies options [file]\n", + argv[0]); + return (1); + } + + /* + * If we have 7 arguments, print the file named on the command-line. + * Otherwise, copy stdin to a temporary file and print the temporary + * file. + */ + + if (argc == 6) + { + /* + * Copy stdin to a temporary file... + */ + + FILE *fp; /* Temporary file */ + char buffer[8192]; /* Buffer for copying */ + int bytes; /* Number of bytes read */ + + + if ((fp = fopen(tmpnam(filename), "w")) == NULL) + { + perror("lpd: unable to create temporary file"); + return (1); + } + + while ((bytes = fread(buffer, 1, sizeof(buffer), stdin)) > 0) + if (fwrite(buffer, 1, bytes, fp) < bytes) + { + perror("lpd: unable to write to temporary file"); + fclose(fp); + unlink(filename); + return (1); + } + + fclose(fp); + } + else + strcpy(filename, argv[6]); + + /* + * Extract the hostname and printer name from the URI... + */ + + httpSeparate(argv[0], method, username, hostname, &port, resource); + + /* + * Queue the job... + */ + + status = lpd_queue(hostname, resource + 1, filename, + argv[2] /* user */, atoi(argv[4]) /* copies */); + + /* + * Remove the temporary file if necessary... + */ + + if (argc < 7) + unlink(filename); + + /* + * Return the queue status... + */ + + return (status); +} + + +/* + * 'lpd_command()' - Send an LPR command sequence and wait for a reply. + */ + +static int /* O - Status of command */ +lpd_command(int fd, /* I - Socket connection to LPD host */ + char *format, /* I - printf()-style format string */ + ...) /* I - Additional args as necessary */ +{ + va_list ap; /* Argument pointer */ + char buf[1024]; /* Output buffer */ + int bytes; /* Number of bytes to output */ + char status; /* Status from command */ + + + /* + * Format the string... + */ + + va_start(ap, format); + bytes = vsprintf(buf, format, ap); + va_end(ap); + + fprintf(stderr, "lpd: lpd_command %02.2x %s", buf[0], buf + 1); + + /* + * Send the command... + */ + + if (send(fd, buf, bytes, 0) < bytes) + return (-1); + + /* + * Read back the status from the command and return it... + */ + + if (recv(fd, &status, 1, 0) < 1) + return (-1); + + fprintf(stderr, "lpd: lpd_command returning %d\n", status); + + return (status); +} + + +/* + * 'lpd_queue()' - Queue a file using the Line Printer Daemon protocol. + */ + +static int /* O - Zero on success, non-zero on failure */ +lpd_queue(char *hostname, /* I - Host to connect to */ + char *printer, /* I - Printer/queue name */ + char *filename, /* I - File to print */ + char *user, /* I - Requesting user */ + int copies) /* I - Number of copies */ +{ + FILE *fp; /* Job file */ + char localhost[255]; /* Local host name */ + int error; /* Error number */ + struct stat filestats; /* File statistics */ + int port; /* LPD connection port */ + int fd; /* LPD socket */ + char control[10240], /* LPD control 'file' */ + *cptr; /* Pointer into control file string */ + char status; /* Status byte from command */ + struct sockaddr_in addr; /* Socket address */ + struct hostent *hostaddr; /* Host address */ + size_t nbytes, /* Number of bytes written */ + tbytes; /* Total bytes written */ + char buffer[8192]; /* Output buffer */ + + + /* + * First try to reserve a port for this connection... + */ + + if ((hostaddr = gethostbyname(hostname)) == NULL) + { + fprintf(stderr, "ERROR: Unable to locate printer \'%s\' - %s", + hostname, strerror(errno)); + return (1); + } + + fprintf(stderr, "INFO: Attempting to connect to host %s for printer %s\n", + hostname, printer); + + memset(&addr, 0, sizeof(addr)); + memcpy(&(addr.sin_addr), hostaddr->h_addr, hostaddr->h_length); + addr.sin_family = hostaddr->h_addrtype; + addr.sin_port = htons(515); /* LPD/printer service */ + + for (port = 732;;) + { + if ((fd = rresvport(&port)) < 0) + { + perror("ERROR: Unable to connect to printer"); + return (1); + } + + if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) + { + error = errno; + close(fd); + fd = -1; + + if (error == ECONNREFUSED) + { + fprintf(stderr, "INFO: Network host \'%s\' is busy; will retry in 30 seconds...", + hostname); + sleep(30); + } + else if (error == EADDRINUSE) + { + port --; + if (port < 721) + port = 732; + } + else + { + perror("ERROR: Unable to connect to printer"); + return (1); + } + } + else + break; + } + + /* + * Next, open the print file and figure out its size... + */ + + if (stat(filename, &filestats)) + { + perror("lpd: unable to stat print file"); + return (1); + } + + if ((fp = fopen(filename, "rb")) == NULL) + { + perror("lpd: unable to open print file for reading"); + return (1); + } + + /* + * Send a job header to the printer, specifying no banner page and + * literal output... + */ + + lpd_command(fd, "\002%s\n", printer); /* Receive print job(s) */ + + gethostname(localhost, sizeof(localhost)); + if (strchr(localhost, '.') != NULL) + *strchr(localhost, '.') = '\0'; + + sprintf(control, "H%s\nP%s\n", localhost, user); + cptr = control + strlen(control); + + while (copies > 0) + { + sprintf(cptr, "ldfA%03.3d%s\n", getpid() % 1000, localhost); + cptr += strlen(cptr); + copies --; + } + + sprintf(cptr, "UdfA%03.3d%s\nNdfA%03.3d%s\n", + getpid() % 1000, localhost, + getpid() % 1000, localhost); + + fprintf(stderr, "lpd: Control file is:\n%s", control); + + lpd_command(fd, "\002%d cfA%03.3d%s\n", strlen(control), getpid() % 1000, + localhost); + + fprintf(stderr, "lpd: Sending control file (%d bytes)\n", strlen(control)); + + if (send(fd, control, strlen(control) + 1, 0) < (strlen(control) + 1)) + { + perror("ERROR: Unable to write control file"); + status = 1; + } + else if (read(fd, &status, 1) < 1 || status != 0) + fprintf(stderr, "ERROR: Remote host did not accept control file (%d)\n", + status); + else + { + /* + * Send the print file... + */ + + fputs("lpd: Control file sent successfully\n", stderr); + + lpd_command(fd, "\003%d dfA%03.3d%s\n", filestats.st_size, + getpid() % 1000, localhost); + + fprintf(stderr, "lpd: Sending data file (%u bytes)\n", + (unsigned)filestats.st_size); + + tbytes = 0; + while ((nbytes = fread(buffer, 1, sizeof(buffer), fp)) > 0) + { + fprintf(stderr, "INFO: Spooling LPR job, %u%% complete...\n", + (unsigned)(100 * tbytes / filestats.st_size)); + + if (send(fd, buffer, nbytes, 0) < nbytes) + { + perror("ERROR: Unable to send print file to printer"); + break; + } + else + tbytes += nbytes; + } + + send(fd, "", 1, 0); + + if (tbytes < filestats.st_size) + status = 1; + else if (recv(fd, &status, 1, 0) < 1 || status != 0) + fprintf(stderr, "ERROR: Remote host did not accept data file (%d)\n", + status); + else + fputs("lpd: Data file sent successfully\n", stderr); + } + + /* + * Close the socket connection and input file and return... + */ + + close(fd); + fclose(fp); + + return (status); +} + + +/* + * End of "$Id$". + */ diff --git a/backend/parallel.c b/backend/parallel.c new file mode 100644 index 0000000000..6e01b95f6b --- /dev/null +++ b/backend/parallel.c @@ -0,0 +1,179 @@ +/* + * "$Id$" + * + * Parallel port backend for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-1999 by Easy Software Products, all rights reserved. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44145 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * main() - Send a file to the specified parallel port. + */ + +/* + * Include necessary headers. + */ + +#include +#include +#include +#include + +#if defined(WIN32) || defined(__EMX__) +# include +#else +# include +# include +# include +#endif /* WIN32 || __EMX__ */ + + +/* + * 'main()' - Send a file to the specified parallel port. + * + * Usage: + * + * printer-uri job-id user title copies options [file] + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line arguments (6 or 7) */ + char *argv[]) /* I - Command-line arguments */ +{ + char method[255], /* Method in URI */ + hostname[1024], /* Hostname */ + username[255], /* Username info (not used) */ + resource[1024], /* Resource info (device and options) */ + *options; /* Pointer to options */ + int port; /* Port number (not used) */ + FILE *fp; /* Print file */ + int fd; /* Parallel device */ + int error; /* Error code (if any) */ + size_t nbytes, /* Number of bytes written */ + tbytes; /* Total number of bytes written */ + char buffer[8192]; /* Output buffer */ + struct termios opts; /* Parallel port options */ + + + if (argc < 6 || argc > 7) + { + fputs("Usage: parallel job-id user title copies options [file]\n", stderr); + return (1); + } + + /* + * If we have 7 arguments, print the file named on the command-line. + * Otherwise, send stdin instead... + */ + + if (argc == 6) + fp = stdin; + else + { + /* + * Try to open the print file... + */ + + if ((fp = fopen(argv[6], "rb")) == NULL) + { + perror("ERROR: unable to open print file"); + return (1); + } + } + + /* + * Extract the device name and options from the URI... + */ + + httpSeparate(argv[0], method, username, hostname, &port, resource); + + /* + * See if there are any options... + */ + + if ((options = strchr(resource, '?')) != NULL) + { + /* + * Yup, terminate the device name string and move to the first + * character of the options... + */ + + *options++ = '\0'; + } + + /* + * Open the parallel port device... + */ + + if ((fd = open(resource, O_WRONLY)) == -1) + { + perror("ERROR: Unable to open parallel port device file"); + return (1); + } + + /* + * Set any options provided... + */ + + tcgetattr(fd, &opts); + + opts.c_lflag &= ~(ICANON | ECHO | ISIG); /* Raw mode */ + + /**** No options supported yet ****/ + + tcsetattr(fd, TCSANOW, &opts); + + /* + * Finally, send the print file... + */ + + tbytes = 0; + while ((nbytes = fread(buffer, 1, sizeof(buffer), fp)) > 0) + { + /* + * Write the print data to the printer... + */ + + if (write(fd, buffer, nbytes) < nbytes) + { + perror("ERROR: Unable to send print file to printer"); + break; + } + else + tbytes += nbytes; + + if (argc > 6) + fprintf(stderr, "INFO: Sending print file, %u bytes...\n", tbytes); + } + + /* + * Close the socket connection and input file and return... + */ + + close(fd); + if (fp != stdin) + fclose(fp); + + return (0); +} + + +/* + * End of "$Id$". + */ diff --git a/backend/serial.c b/backend/serial.c new file mode 100644 index 0000000000..64bc334566 --- /dev/null +++ b/backend/serial.c @@ -0,0 +1,297 @@ +/* + * "$Id$" + * + * Serial port backend for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-1999 by Easy Software Products, all rights reserved. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44145 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * main() - Send a file to the printer or server. + */ + +/* + * Include necessary headers. + */ + +#include +#include +#include +#include + +#if defined(WIN32) || defined(__EMX__) +# include +#else +# include +# include +# include +#endif /* WIN32 || __EMX__ */ + + +/* + * 'main()' - Send a file to the printer or server. + * + * Usage: + * + * printer-uri job-id user title copies options [file] + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line arguments (6 or 7) */ + char *argv[]) /* I - Command-line arguments */ +{ + char method[255], /* Method in URI */ + hostname[1024], /* Hostname */ + username[255], /* Username info (not used) */ + resource[1024], /* Resource info (device and options) */ + *options, /* Pointer to options */ + name[255], /* Name of option */ + value[255], /* Value of option */ + *ptr; /* Pointer into name or value */ + int port; /* Port number (not used) */ + FILE *fp; /* Print file */ + int fd; /* Parallel device */ + int error; /* Error code (if any) */ + size_t nbytes, /* Number of bytes written */ + tbytes; /* Total number of bytes written */ + char buffer[8192]; /* Output buffer */ + struct termios opts; /* Parallel port options */ + + + if (argc < 6 || argc > 7) + { + fputs("Usage: serial job-id user title copies options [file]\n", stderr); + return (1); + } + + /* + * If we have 7 arguments, print the file named on the command-line. + * Otherwise, send stdin instead... + */ + + if (argc == 6) + fp = stdin; + else + { + /* + * Try to open the print file... + */ + + if ((fp = fopen(argv[6], "rb")) == NULL) + { + perror("ERROR: unable to open print file"); + return (1); + } + } + + /* + * Extract the device name and options from the URI... + */ + + httpSeparate(argv[0], method, username, hostname, &port, resource); + + /* + * See if there are any options... + */ + + if ((options = strchr(resource, '?')) != NULL) + { + /* + * Yup, terminate the device name string and move to the first + * character of the options... + */ + + *options++ = '\0'; + } + + /* + * Open the parallel port device... + */ + + if ((fd = open(resource, O_WRONLY)) == -1) + { + perror("ERROR: Unable to open serial port device file"); + return (1); + } + + /* + * Set any options provided... + */ + + tcgetattr(fd, &opts); + + opts.c_lflag &= ~(ICANON | ECHO | ISIG); /* Raw mode */ + + if (options != NULL) + while (*options) + { + /* + * Get the name... + */ + + for (ptr = name; *options && *options != '=';) + *ptr++ = *options++; + *ptr = '\0'; + + if (*options == '=') + { + /* + * Get the value... + */ + + options ++; + + for (ptr = value; *options && *options != '+';) + *ptr++ = *options++; + *ptr = '\0'; + + if (*options == '+') + options ++; + } + else + value[0] = '\0'; + + /* + * Process the option... + */ + + if (strcasecmp(name, "baud") == 0) + { + /* + * Set the baud rate... + */ + +#if B19200 == 19200 + cfsetispeed(&opts, atoi(value)); + cfsetospeed(&opts, atoi(value)); +#else + switch (atoi(value)) + { + case 1200 : + cfsetispeed(&opts, B1200); + cfsetospeed(&opts, B1200); + break; + case 2400 : + cfsetispeed(&opts, B2400); + cfsetospeed(&opts, B2400); + break; + case 4800 : + cfsetispeed(&opts, B4800); + cfsetospeed(&opts, B4800); + break; + case 9600 : + cfsetispeed(&opts, B9600); + cfsetospeed(&opts, B9600); + break; + case 19200 : + cfsetispeed(&opts, B19200); + cfsetospeed(&opts, B19200); + break; + case 38400 : + cfsetispeed(&opts, B38400); + cfsetospeed(&opts, B38400); + break; + default : + fprintf(stderr, "WARNING: Unsupported baud rate %s!\n", value); + break; + } +#endif /* B19200 == 19200 */ + } + else if (strcasecmp(name, "bits") == 0) + { + /* + * Set number of data bits... + */ + + switch (atoi(value)) + { + case 7 : + opts.c_cflag &= ~CSIZE; + opts.c_cflag |= CS7; + opts.c_cflag |= PARENB; + opts.c_cflag &= ~PARODD; + break; + case 8 : + opts.c_cflag &= ~CSIZE; + opts.c_cflag |= CS8; + opts.c_cflag &= ~PARENB; + break; + } + } + else if (strcasecmp(name, "parity") == 0) + { + /* + * Set parity checking... + */ + + if (strcasecmp(value, "even") == 0) + { + opts.c_cflag |= PARENB; + opts.c_cflag &= ~PARODD; + } + else if (strcasecmp(value, "odd") == 0) + { + opts.c_cflag |= PARENB; + opts.c_cflag |= PARODD; + } + else if (strcasecmp(value, "none") == 0) + opts.c_cflag &= ~PARENB; + } + } + + tcsetattr(fd, TCSANOW, &opts); + + /* + * Finally, send the print file... + */ + + tbytes = 0; + while ((nbytes = fread(buffer, 1, sizeof(buffer), fp)) > 0) + { + /* + * Write the print data to the printer... + */ + + if (write(fd, buffer, nbytes) < nbytes) + { + perror("ERROR: Unable to send print file to printer"); + break; + } + else + tbytes += nbytes; + + if (argc > 6) + fprintf(stderr, "INFO: Sending print file, %u bytes...\n", tbytes); + } + + /* + * Close the socket connection and input file and return... + */ + + close(fd); + if (fp != stdin) + fclose(fp); + + return (0); +} + + +/* + * End of "$Id$". + */ diff --git a/backend/smb.c b/backend/smb.c new file mode 100644 index 0000000000..23fddcd82a --- /dev/null +++ b/backend/smb.c @@ -0,0 +1,66 @@ +/* + * "$Id$" + * + * Server Message Block backend for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-1999 by Easy Software Products, all rights reserved. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44145 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + */ + +/* + * Include necessary headers. + */ + +#include +#include +#include +#include + + +/* + * 'main()' - Send a file to the printer or server. + * + * Usage: + * + * printer-uri job-id user title copies options [file] + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line arguments (6 or 7) */ + char *argv[]) /* I - Command-line arguments */ +{ + if (argc < 6 || argc > 7) + { + fprintf(stderr, "Usage: %s job-id user title copies options [file]\n", + argv[0]); + return (1); + } + + fputs("ERROR: Backend not implemented yet!\n", stderr); + + return (1); +} + + + +/* + * End of "$Id$". + */ diff --git a/backend/socket.c b/backend/socket.c new file mode 100644 index 0000000000..3f0e3fc72b --- /dev/null +++ b/backend/socket.c @@ -0,0 +1,232 @@ +/* + * "$Id$" + * + * AppSocket backend for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-1999 by Easy Software Products, all rights reserved. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * main() - Send a file to the printer or server. + */ + +/* + * Include necessary headers. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(WIN32) || defined(__EMX__) +# include +#else +# include +# include +# include +# include +#endif /* WIN32 || __EMX__ */ + + +/* + * 'main()' - Send a file to the printer or server. + * + * Usage: + * + * printer-uri job-id user title copies options [file] + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line arguments (6 or 7) */ + char *argv[]) /* I - Command-line arguments */ +{ + char method[255], /* Method in URI */ + hostname[1024], /* Hostname */ + username[255], /* Username info (not used) */ + resource[1024]; /* Resource info (not used) */ + FILE *fp; /* Print file */ + int port; /* Port number */ + int fd; /* AppSocket */ + int error; /* Error code (if any) */ + struct sockaddr_in addr; /* Socket address */ + struct hostent *hostaddr; /* Host address */ + int wbytes; /* Number of bytes written */ + size_t nbytes, /* Number of bytes read */ + tbytes; /* Total number of bytes written */ + char buffer[8192], /* Output buffer */ + *bufptr; /* Pointer into buffer */ + struct timeval timeout; /* Timeout for select() */ + fd_set input; /* Input set for select() */ + + + if (argc < 6 || argc > 7) + { + fprintf(stderr, "Usage: %s job-id user title copies options [file]\n", + argv[0]); + return (1); + } + + /* + * If we have 7 arguments, print the file named on the command-line. + * Otherwise, send stdin instead... + */ + + if (argc == 6) + fp = stdin; + else + { + /* + * Try to open the print file... + */ + + if ((fp = fopen(argv[6], "rb")) == NULL) + { + perror("ERROR: unable to open print file"); + return (1); + } + } + + /* + * Extract the hostname and port number from the URI... + */ + + httpSeparate(argv[0], method, username, hostname, &port, resource); + + if (port == 0) + port = 9100; /* Default to HP JetDirect/Tektronix PhaserShare */ + + /* + * Then try to connect to the remote host... + */ + + if ((hostaddr = gethostbyname(hostname)) == NULL) + { + fprintf(stderr, "ERROR: Unable to locate printer \'%s\' - %s", + hostname, strerror(errno)); + return (1); + } + + fprintf(stderr, "INFO: Attempting to connect to host %s on port %d\n", + hostname, port); + + memset(&addr, 0, sizeof(addr)); + memcpy(&(addr.sin_addr), hostaddr->h_addr, hostaddr->h_length); + addr.sin_family = hostaddr->h_addrtype; + addr.sin_port = htons(port); + + for (;;) + { + if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) + { + perror("ERROR: Unable to connect to printer"); + return (1); + } + + if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) + { + error = errno; + close(fd); + fd = -1; + + if (error == ECONNREFUSED) + { + fprintf(stderr, "INFO: Network host \'%s\' is busy; will retry in 30 seconds...\n", + hostname); + sleep(30); + } + else + { + perror("ERROR: Unable to connect to printer"); + return (1); + } + } + else + break; + } + + /* + * Finally, send the print file... + */ + + fputs("INFO: Connected to host, sending print job...\n", stderr); + + tbytes = 0; + while ((nbytes = fread(buffer, 1, sizeof(buffer), fp)) > 0) + { + /* + * Write the print data to the printer... + */ + + tbytes += nbytes; + bufptr = buffer; + + while (nbytes > 0) + { + if ((wbytes = send(fd, bufptr, nbytes, 0)) < 0) + { + perror("ERROR: Unable to send print file to printer"); + break; + } + + nbytes -= wbytes; + bufptr += wbytes; + } + + /* + * Check for possible data coming back from the printer... + */ + + timeout.tv_sec = 0; + timeout.tv_usec = 0; + FD_ZERO(&input); + FD_SET(fd, &input); + if (select(fd + 1, &input, NULL, NULL, &timeout) > 0) + { + /* + * Grab the data coming back and spit it out to stderr... + */ + + if ((nbytes = recv(fd, buffer, sizeof(buffer), 0)) > 0) + fprintf(stderr, "INFO: Received %u bytes of back-channel data!\n", + nbytes); + } + else if (argc > 6) + fprintf(stderr, "INFO: Sending print file, %u bytes...\n", tbytes); + } + + /* + * Close the socket connection and input file and return... + */ + + close(fd); + if (fp != stdin) + fclose(fp); + + return (0); +} + + +/* + * End of "$Id$". + */ diff --git a/berkeley/Makefile b/berkeley/Makefile new file mode 100644 index 0000000000..4715fce07c --- /dev/null +++ b/berkeley/Makefile @@ -0,0 +1,82 @@ +# +# "$Id$" +# +# Berkeley commands makefile for the Common UNIX Printing System (CUPS). +# +# Copyright 1997-1999 by Easy Software Products, all rights reserved. +# +# These coded instructions, statements, and computer programs are the +# property of Easy Software Products and are protected by Federal +# copyright law. Distribution and use rights are outlined in the file +# "LICENSE.txt" which should have been included with this file. If this +# file is missing or damaged please contact Easy Software Products +# at: +# +# Attn: CUPS Licensing Information +# Easy Software Products +# 44145 Airport View Drive, Suite 204 +# Hollywood, Maryland 20636-3111 USA +# +# Voice: (301) 373-9603 +# EMail: cups-info@cups.org +# WWW: http://www.cups.org +# + +include ../Makedefs + +TARGETS = lpc lpr lprm +OBJS = lpc.o lpr.o lprm.o + +# +# Make all targets... +# + +all: $(TARGETS) + +# +# Clean all object files... +# + +clean: + rm -f $(OBJS) $(TARGETS) + +# +# Install all targets... +# + +install: + -$(MKDIR) $(BINDIR) + -$(MKDIR) $(SBINDIR) + $(CP) lpr lprm $(BINDIR) + $(CP) lpc $(SBINDIR) + +# +# lpc +# + +lpc: lpc.o ../cups/libcups.a + $(CC) $(LDFLAGS) -o lpc lpc.o $(LIBS) + +lpc.o: ../cups/cups.h ../Makedefs + +# +# lpr +# + +lpr: lpr.o ../cups/libcups.a + $(CC) $(LDFLAGS) -o lpr lpr.o $(LIBS) + +lpr.o: ../cups/cups.h ../Makedefs + +# +# lprm +# + +lprm: lprm.o ../cups/libcups.a + $(CC) $(LDFLAGS) -o lprm lprm.o $(LIBS) + +lprm.o: ../cups/cups.h ../Makedefs + +# +# End of "$Id$". +# diff --git a/berkeley/lpc.c b/berkeley/lpc.c new file mode 100644 index 0000000000..c78e96f729 --- /dev/null +++ b/berkeley/lpc.c @@ -0,0 +1,452 @@ +/* + * "$Id$" + * + * "lpc" command for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * main() - Parse options and commands. + * compare_strings() - Compare two command-line strings. + * do_command() - Do an lpc command... + * show_help() - Show help messages. + * show_status() - Show printers. + */ + +/* + * Include necessary headers... + */ + +#include +#include +#include +#include +#include +#include + + +/* + * Local functions... + */ + +static int compare_strings(char *, char *, int); +static void do_command(http_t *, char *, char *); +static void show_help(char *); +static void show_status(http_t *, char *); + + +/* + * 'main()' - Parse options and commands. + */ + +int +main(int argc, /* I - Number of command-line arguments */ + char *argv[]) /* I - Command-line arguments */ +{ + int i; /* Looping var */ + http_t *http; /* Connection to server */ + char line[1024], /* Input line from user */ + *params; /* Pointer to parameters */ + + + /* + * Connect to the scheduler... + */ + + http = httpConnect("localhost", ippPort()); + + if (argc > 1) + { + /* + * Process a single command on the command-line... + */ + + do_command(http, argv[1], argv[2]); + } + else + { + /* + * Do the command prompt thing... + */ + + printf("lpc> "); + while (gets(line) != NULL) + { + /* + * Find any options in the string... + */ + + while (isspace(line[0])) + strcpy(line, line + 1); + + for (params = line; *params != '\0'; params ++) + if (isspace(*params)) + break; + + /* + * Remove whitespace between the command and parameters... + */ + + while (isspace(*params)) + *params++ = '\0'; + + /* + * The "quit" and "exit" commands exit; otherwise, process as needed... + */ + + if (compare_strings(line, "quit", 1) == 0 || + compare_strings(line, "exit", 2) == 0) + break; + + if (*params == '\0') + do_command(http, line, NULL); + else + do_command(http, line, params); + + /* + * Put another prompt out to the user... + */ + + printf("lpc> "); + } + } + + /* + * Close the connection to the server and return... + */ + + httpClose(http); + + return (0); +} + + +/* + * 'compare_strings()' - Compare two command-line strings. + */ + +static int /* O - -1 or 1 = no match, 0 = match */ +compare_strings(char *s, /* I - Command-line string */ + char *t, /* I - Option string */ + int tmin) /* I - Minimum number of unique chars in option */ +{ + int slen; /* Length of command-line string */ + + + slen = strlen(s); + if (slen < tmin) + return (-1); + else + return (strncmp(s, t, slen)); +} + + +/* + * 'do_command()' - Do an lpc command... + */ + +static void +do_command(http_t *http, /* I - HTTP connection to server */ + char *command, /* I - Command string */ + char *params) /* I - Parameters for command */ +{ + if (compare_strings(command, "status", 4) == 0) + show_status(http, params); + else if (compare_strings(command, "help", 1) == 0 || + strcmp(command, "?") == 0) + show_help(params); + else + puts("?Invalid command"); +} + + +/* + * 'show_help()' - Show help messages. + */ + +static void +show_help(char *command) /* I - Command to describe or NULL */ +{ + if (command == NULL) + { + puts("Commands may be abbreviated. Commands are:"); + puts(""); + puts("exit help quit status ?"); + } + else if (compare_strings(command, "help", 1) == 0 || + strcmp(command, "?") == 0) + puts("help\t\tget help on commands"); + else if (compare_strings(command, "status", 4) == 0) + puts("status\t\tshow status of daemon and queue"); + else + puts("?Invalid help command unknown"); +} + + +/* + * 'show_status()' - Show printers. + */ + +static void +show_status(http_t *http, /* I - HTTP connection to server */ + char *dests) /* I - Destinations */ +{ + ipp_t *request, /* IPP Request */ + *response, /* IPP Response */ + *jobs; /* IPP Get Jobs response */ + ipp_attribute_t *attr; /* Current attribute */ + cups_lang_t *language; /* Default language */ + char *printer, /* Printer name */ + *device; /* Device URI */ + ipp_pstate_t pstate; /* Printer state */ + int accepting; /* Is printer accepting jobs? */ + int jobcount; /* Count of current jobs */ + char *dptr, /* Pointer into destination list */ + *ptr; /* Pointer into printer name */ + int match; /* Non-zero if this job matches */ + char printer_uri[HTTP_MAX_URI]; + /* Printer URI */ + + + DEBUG_printf(("show_printers(%08x, %08x)\n", http, dests)); + + if (http == NULL) + return; + + /* + * Build a CUPS_GET_PRINTERS request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + */ + + request = ippNew(); + + request->request.op.operation_id = CUPS_GET_PRINTERS; + request->request.op.request_id = 1; + + language = cupsLangDefault(); + + attr = ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, + "attributes-charset", NULL, cupsLangEncoding(language)); + + attr = ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, + "attributes-natural-language", NULL, language->language); + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoRequest(http, request, "/printers/")) != NULL) + { + DEBUG_puts("show_printers: request succeeded..."); + + /* + * Loop through the printers returned in the list and display + * their status... + */ + + for (attr = response->attrs; attr != NULL; attr = attr->next) + { + /* + * Skip leading attributes until we hit a job... + */ + + while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER) + attr = attr->next; + + if (attr == NULL) + break; + + /* + * Pull the needed attributes from this job... + */ + + printer = NULL; + device = "file:/dev/null"; + pstate = IPP_PRINTER_IDLE; + jobcount = 0; + accepting = 1; + + while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) + { + if (strcmp(attr->name, "printer-name") == 0 && + attr->value_tag == IPP_TAG_NAME) + printer = attr->values[0].string.text; + + if (strcmp(attr->name, "device-uri") == 0 && + attr->value_tag == IPP_TAG_URI) + device = attr->values[0].string.text; + + if (strcmp(attr->name, "printer-state") == 0 && + attr->value_tag == IPP_TAG_ENUM) + pstate = (ipp_pstate_t)attr->values[0].integer; + + if (strcmp(attr->name, "printer-is-accepting-jobs") == 0 && + attr->value_tag == IPP_TAG_BOOLEAN) + accepting = attr->values[0].boolean; + + attr = attr->next; + } + + /* + * See if we have everything needed... + */ + + if (printer == NULL) + { + if (attr == NULL) + break; + else + continue; + } + + /* + * See if this is a printer we're interested in... + */ + + match = dests == NULL; + + if (dests != NULL) + { + for (dptr = dests; *dptr != '\0';) + { + /* + * Skip leading whitespace and commas... + */ + + while (isspace(*dptr) || *dptr == ',') + dptr ++; + + if (*dptr == '\0') + break; + + /* + * Compare names... + */ + + for (ptr = printer; + *ptr != '\0' && *dptr != '\0' && *ptr == *dptr; + ptr ++, dptr ++); + + if (*ptr == '\0' && (*dptr == '\0' || *dptr == ',' || isspace(*dptr))) + { + match = 1; + break; + } + + /* + * Skip trailing junk... + */ + + while (!isspace(*dptr) && *dptr != '\0') + dptr ++; + while (isspace(*dptr) || *dptr == ',') + dptr ++; + + if (*dptr == '\0') + break; + } + } + + /* + * Display the printer entry if needed... + */ + + if (match) + { + /* + * If the printer state is "IPP_PRINTER_PROCESSING", then grab the + * current job for the printer. + */ + + if (pstate == IPP_PRINTER_PROCESSING) + { + /* + * Build an IPP_GET_JOBS request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + * limit + */ + + request = ippNew(); + + request->request.op.operation_id = IPP_GET_JOBS; + request->request.op.request_id = 1; + + language = cupsLangDefault(); + + attr = ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, + "attributes-charset", NULL, + cupsLangEncoding(language)); + + attr = ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, + "attributes-natural-language", NULL, + language->language); + + sprintf(printer_uri, "http://localhost/printers/%s", printer); + attr = ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, + "printer-uri", NULL, printer_uri); + + if ((jobs = cupsDoRequest(http, request, "/jobs/")) != NULL) + { + for (attr = jobs->attrs; attr != NULL; attr = attr->next) + if (strcmp(attr->name, "job-id") == 0) + jobcount ++; + + ippDelete(jobs); + } + } + + /* + * Display it... + */ + + printf("%s:\n", printer); + if (strncmp(device, "file:", 5) == 0) + printf("\tprinter is on device \'%s\' speed -1\n", device + 5); + else + printf("\tprinter is on device \'%s\' speed -1\n", device); + printf("\tqueuing is %sabled\n", accepting ? "en" : "dis"); + printf("\tprinting is %sabled\n", + pstate == IPP_PRINTER_STOPPED ? "dis" : "en"); + if (jobcount == 0) + puts("\tno entries"); + else + printf("\t%d entries\n", jobcount); + puts("\tdaemon present"); + } + + if (attr == NULL) + break; + } + + ippDelete(response); + } +} + + +/* + * End of "$Id$". + */ diff --git a/berkeley/lpr.c b/berkeley/lpr.c new file mode 100644 index 0000000000..cc6d4da4b6 --- /dev/null +++ b/berkeley/lpr.c @@ -0,0 +1,232 @@ +/* + * "$Id$" + * + * "lpr" command for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * main() - Parse options and send files for printing. + */ + +/* + * Include necessary headers... + */ + +#include +#include +#include + + +/* + * 'main()' - Parse options and send files for printing. + */ + +int +main(int argc, /* I - Number of command-line arguments */ + char *argv[]) /* I - Command-line arguments */ +{ + int i; /* Looping var */ + int job_id; /* Job ID */ + char *dest; /* Destination printer */ + char *title; /* Job title */ + int priority; /* Job priority (1-100) */ + int num_copies; /* Number of copies per file */ + int num_files; /* Number of files printed */ + int num_options; /* Number of options */ + cups_option_t *options; /* Options */ + int silent; /* Silent or verbose output? */ + char tempfile[1024]; /* Temporary file for printing from stdin */ + char buffer[8192]; /* Copy buffer */ + FILE *temp; /* Temporary file pointer */ + + + silent = 0; + dest = cupsGetDefault(); + num_options = 0; + options = NULL; + num_files = 0; + title = NULL; + + for (i = 1; i < argc; i ++) + if (argv[i][0] == '-') + switch (argv[i][1]) + { + case 'i' : /* indent */ + case 'w' : /* width */ + if (argv[i][2] == '\0') + i ++; + case 'c' : /* CIFPLOT */ + case 'd' : /* DVI */ + case 'f' : /* FORTRAN */ + case 'g' : /* plot */ + case 'n' : /* Ditroff */ + case 't' : /* Troff */ + case 'v' : /* Raster image */ + fprintf(stderr, "Warning: \'%c\' format modifier not supported - output may not be correct!\n", + argv[i][1]); + break; + + case 'l' : /* Literal/raw */ + num_options = cupsParseOptions("raw", num_options, &options); + break; + + case 'p' : /* Prettyprint */ + num_options = cupsParseOptions("prettyprint", num_options, &options); + break; + + case 'h' : /* Suppress burst page */ + case 's' : /* Don't use symlinks */ + break; + + case 'm' : /* mail on completion */ + fputs("Warning: email notification is not supported!\n", stderr); + break; + + case 'P' : /* Destination printer or class */ + if (argv[i][2] != '\0') + dest = argv[i] + 2; + else + { + i ++; + dest = argv[i]; + } + break; + + case '#' : /* Number of copies */ + if (argv[i][2] != '\0') + num_copies = atoi(argv[i] + 2); + else + { + i ++; + num_copies = atoi(argv[i]); + } + + if (num_copies < 1 || num_copies > 100) + { + fputs("lpr: Number copies must be between 1 and 100.\n", stderr); + return (1); + } + + sprintf(buffer, "%d", num_copies); + num_options = cupsAddOption("copies", buffer, num_options, &options); + break; + + case 'C' : /* Class */ + case 'J' : /* Job name */ + case 'T' : /* Title */ + if (argv[i][2] != '\0') + title = argv[i] + 2; + else + { + i ++; + title = argv[i]; + } + break; + + default : + fprintf(stderr, "lpr: Unknown option \'%c\'!\n", argv[i][1]); + return (1); + } + else + { + /* + * Print a file... + */ + + if (dest == NULL) + { + fputs("lpr: error - no default destination available.\n", stderr); + return (1); + } + + num_files ++; + if (title) + job_id = cupsPrintFile(dest, argv[i], title, num_options, options); + else + { + char *filename; + + if ((filename = strrchr(argv[i], '/')) != NULL) + filename ++; + else + filename = argv[i]; + + job_id = cupsPrintFile(dest, argv[i], filename, num_options, options); + } + + if (job_id < 1) + { + fprintf(stderr, "lpr: unable to print file \'%s\'.\n", argv[i]); + return (1); + } + } + + /* + * See if we printed anything; if not, print from stdin... + */ + + if (num_files == 0) + { + if (dest == NULL) + { + fputs("lpr: error - no default destination available.\n", stderr); + return (1); + } + + temp = fopen(tmpnam(tempfile), "w"); + + if (temp == NULL) + { + fputs("lpr: unable to create temporary file.\n", stderr); + return (1); + } + + while ((i = fread(buffer, 1, sizeof(buffer), stdin)) > 0) + fwrite(buffer, 1, i, temp); + + i = ftell(temp); + fclose(temp); + + if (i == 0) + { + fputs("lpr: stdin is empty, so no job has been sent.\n", stderr); + return (1); + } + + if (title) + job_id = cupsPrintFile(dest, tempfile, title, num_options, options); + else + job_id = cupsPrintFile(dest, tempfile, "(stdin)", num_options, options); + + if (job_id < 1) + { + fprintf(stderr, "lpr: unable to print file \'%s\'.\n", argv[i]); + return (1); + } + } + + return (0); +} + + +/* + * End of "$Id$". + */ diff --git a/berkeley/lprm.c b/berkeley/lprm.c new file mode 100644 index 0000000000..59bdd3e24e --- /dev/null +++ b/berkeley/lprm.c @@ -0,0 +1,198 @@ +/* + * "$Id$" + * + * "lprm" command for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44145 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * main() - Parse options and cancel jobs. + */ + +/* + * Include necessary headers... + */ + +#include +#include +#include + +#include +#include + + +/* + * 'main()' - Parse options and cancel jobs. + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line arguments */ + char *argv[]) /* I - Command-line arguments */ +{ + http_t *http; /* HTTP connection to server */ + int i; /* Looping var */ + int job_id; /* Job ID */ + char *dest; /* Destination printer */ + char uri[1024]; /* Printer or job URI */ + ipp_t *request; /* IPP request */ + ipp_t *response; /* IPP response */ + ipp_op_t op; /* Operation */ + cups_lang_t *language; /* Language */ + + + /* + * Setup to cancel individual print jobs... + */ + + op = IPP_CANCEL_JOB; + job_id = 0; + dest = cupsGetDefault(); + response = NULL; + + /* + * Open a connection to the server... + */ + + if ((http = httpConnect("localhost", ippPort())) == NULL) + { + fputs("lprm: Unable to contact server!\n", stderr); + return (1); + } + + /* + * Process command-line arguments... + */ + + for (i = 1; i < argc; i ++) + if (argv[i][0] == '-' && argv[i][1] != '\0') + switch (argv[i][1]) + { + case 'P' : /* Cancel jobs on a printer */ + if (argv[i][2]) + dest = argv[i] + 2; + else + { + i ++; + dest = argv[i]; + } + break; + + default : + fprintf(stderr, "lprm: Unknown option \'%c\'!\n", argv[i][1]); + return (1); + } + else + { + /* + * Cancel a job or printer... + */ + + if (isdigit(argv[i][0])) + { + dest = NULL; + op = IPP_CANCEL_JOB; + job_id = atoi(argv[i]); + } + else if (strcmp(argv[i], "-") == 0) + { + /* + * Cancel all jobs + */ + + op = IPP_PURGE_JOBS; + } + else + job_id = 0; + + /* + * Build an IPP request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + job-id *or* job-uri + * [requesting-user-name] + */ + + request = ippNew(); + + request->request.op.operation_id = op; + request->request.op.request_id = 1; + + language = cupsLangDefault(); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, + "attributes-charset", NULL, cupsLangEncoding(language)); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, + "attributes-natural-language", NULL, language->language); + + if (dest) + { + sprintf(uri, "http://localhost/printers/%s", dest); + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, + "printer-uri", NULL, uri); + ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", + job_id); + } + else + { + sprintf(uri, "http://localhost/jobs/%d", job_id); + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, + uri); + } + + /* + * Do the request and get back a response... + */ + + if (op == IPP_PURGE_JOBS) + response = cupsDoRequest(http, request, "/admin/"); + else + response = cupsDoRequest(http, request, "/jobs/"); + + if (response != NULL) + ippDelete(response); + else + { + fputs("lprm: Unable to cancel job(s)!\n", stderr); + return (1); + } + } + + /* + * If nothing has been cancelled yet, cancel the current job on the specified + * (or default) printer... + */ + + if (response == NULL) + if (!cupsCancelJob(dest, 0)) + { + fputs("lprm: Unable to cancel job(s)!\n", stderr); + return (1); + } + + return (0); +} + + +/* + * End of "$Id$". + */ diff --git a/cgi-bin/Makefile b/cgi-bin/Makefile new file mode 100644 index 0000000000..63ce603e5c --- /dev/null +++ b/cgi-bin/Makefile @@ -0,0 +1,61 @@ +# +# "$Id$" +# +# CGI makefile for the Common UNIX Printing System (CUPS). +# +# Copyright 1997-1999 by Easy Software Products. +# +# These coded instructions, statements, and computer programs are the +# property of Easy Software Products and are protected by Federal +# copyright law. Distribution and use rights are outlined in the file +# "LICENSE.txt" which should have been included with this file. If this +# file is missing or damaged please contact Easy Software Products +# at: +# +# Attn: CUPS Licensing Information +# Easy Software Products +# 44145 Airport View Drive, Suite 204 +# Hollywood, Maryland 20636-3111 USA +# +# Voice: (301) 373-9603 +# EMail: cups-info@cups.org +# WWW: http://www.cups.org +# + +include ../Makedefs + +#TARGETS = classes.cgi jobs.cgi printers.cgi +TARGETS = printers.cgi +OBJS = classes.o jobs.o printers.o + +# +# Make all targets... +# + +all: $(TARGETS) + +# +# Clean all object files... +# + +clean: + rm -f $(OBJS) $(TARGETS) + +# +# Install all targets... +# + +install: + +# +# printers.cgi +# + +printers.cgi: printers.o ../Makedefs ../cups/libcups.a + $(CC) $(LDFLAGS) -o $@ printers.o $(LIBS) + +$(OBJS): ../Makedefs ../cups/cups.h ../cups/ipp.h ../cups/language.h + +# +# End of "$Id$". +# diff --git a/cgi-bin/printers.c b/cgi-bin/printers.c new file mode 100644 index 0000000000..03cfafde87 --- /dev/null +++ b/cgi-bin/printers.c @@ -0,0 +1,461 @@ +/* + * "$Id$" + * + * Printer status CGI for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * main() - Main entry for CGI. + * show_printer_list() - Show a list of printers... + * show_printer_info() - Show printer information. + */ + +/* + * Include necessary headers... + */ + +#include +#include +#include +#include +#include +#include + + +/* + * Local functions... + */ + +static void show_printer_list(http_t *http, cups_lang_t *language); +static void show_printer_info(http_t *http, cups_lang_t *language, + char *name); + + +/* + * 'main()' - Main entry for CGI. + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line arguments */ + char *argv[]) /* I - Command-line arguments */ +{ + cups_lang_t *language; /* Language information */ + char *printer; /* Printer name */ + http_t *http; /* Connection to the server */ + + + setbuf(stdout, NULL); + /* + * Get the request language... + */ + + language = cupsLangDefault(); + + /* + * Connect to the HTTP server... + */ + + http = httpConnect("localhost", ippPort()); + + /* + * Tell the client to expect HTML... + */ + + printf("Content-Type: text/html;charset=%s\n\n", cupsLangEncoding(language)); + + /* + * See if we need to show a list of printers or the status of a + * single printer... + */ + + printer = argv[0]; + if (strcmp(printer, "/") == 0 || strcmp(printer, "printers.cgi") == 0) + printer = NULL; + + /* + * Print the standard header... + */ + + puts(""); + puts(""); + if (printer) + puts(""); + else + puts(""); + printf("%s on %s - Common UNIX Printing System\n", + printer == NULL ? "Printers" : printer, getenv("SERVER_NAME")); + puts(""); + puts(""); + puts("\"Current"); + puts("\"Current"); + puts("\"Current"); + puts("\"Read"); + puts("\"Download"); + puts(""); + puts(""); + puts(""); + puts("

"); + puts(""); + puts("\"Easy"); + puts(""); + + printf("

%s on %s

\n", printer == NULL ? "Printers" : printer, + getenv("SERVER_NAME")); + fflush(stdout); + + puts("
"); + puts(""); + puts(""); + puts(""); + puts(""); + puts(""); + puts(""); + + /* + * Show the information... + */ + + if (printer == NULL) + show_printer_list(http, language); + else + show_printer_info(http, language, printer); + + /* + * Write a standard trailer... + */ + + puts("
NameStatusJobs
"); + puts("
"); + + puts("
"); + + puts("

The Common UNIX Printing System, CUPS, and the CUPS logo are the"); + puts("trademark property of Easy Software"); + puts("Products. CUPS is copyright 1997-1999 by Easy Software Products,"); + puts("All Rights Reserved."); + + puts(""); + puts(""); + + /* + * Close the HTTP server connection... + */ + + httpClose(http); + cupsLangFree(language); + + /* + * Return with no errors... + */ + + return (0); +} + + +/* + * 'show_printer_list()' - Show a list of printers... + */ + +static void +show_printer_list(http_t *http, /* I - HTTP connection */ + cups_lang_t *language)/* I - Client's language */ +{ + ipp_t *request, /* IPP request */ + *response; /* IPP response */ + ipp_attribute_t *attr; /* IPP attribute */ + + + /* + * Build a CUPS_GET_PRINTERS request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + */ + + request = ippNew(); + + request->request.op.operation_id = CUPS_GET_PRINTERS; + request->request.op.request_id = 1; + + + attr = ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, + "attributes-charset", NULL, cupsLangEncoding(language)); + + attr = ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, + "attributes-natural-language", NULL, language->language); + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoRequest(http, request, "/printers/")) != NULL) + { + /* + * Loop through the printers returned in the list and display + * their devices... + */ + + for (attr = response->attrs; attr != NULL; attr = attr->next) + { + /* + * Skip leading attributes until we hit a job... + */ + + while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER) + attr = attr->next; + + if (attr == NULL) + break; + + /* + * Show the printer status for each printer... + */ + + while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) + { + if (strcmp(attr->name, "printer-name") == 0 && + attr->value_tag == IPP_TAG_NAME) + show_printer_info(http, language, attr->values[0].string.text); + + attr = attr->next; + } + + if (attr == NULL) + break; + } + + ippDelete(response); + } +} + + +/* + * 'show_printer_info()' - Show printer information. + */ + +static void +show_printer_info(http_t *http, + cups_lang_t *language, + char *name) +{ + ipp_t *request, /* IPP request */ + *response, /* IPP response */ + *jobs; /* IPP Get Jobs response */ + int jobcount; /* Number of jobs */ + ipp_attribute_t *attr; /* IPP attribute */ + char *message; /* Printer state message */ + int accepting; /* Accepting requests? */ + ipp_pstate_t pstate; /* Printer state */ + char uri[1024]; /* Printer URI */ + + + /* + * Build a IPP_GET_PRINTER_ATTRIBUTES request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + */ + + request = ippNew(); + + request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES; + request->request.op.request_id = 1; + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, + "attributes-charset", NULL, cupsLangEncoding(language)); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, + "attributes-natural-language", NULL, language->language); + + sprintf(uri, "ipp://localhost/printers/%s", name); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri); + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoRequest(http, request, uri + 15)) != NULL) + { + /* + * Grab the needed printer attributes... + */ + + if ((attr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM)) != NULL) + pstate = (ipp_pstate_t)attr->values[0].integer; + else + pstate = IPP_PRINTER_IDLE; + + if ((attr = ippFindAttribute(response, "printer-state-message", IPP_TAG_TEXT)) != NULL) + message = attr->values[0].string.text; + else + message = NULL; + + if ((attr = ippFindAttribute(response, "printer-is-accepting-jobs", + IPP_TAG_BOOLEAN)) != NULL) + accepting = attr->values[0].boolean; + else + accepting = 1; + + /* + * Display the printer entry... + */ + + puts(""); + + printf("%s\n", name, name); + + printf("\n", + pstate == IPP_PRINTER_IDLE ? "idle" : + pstate == IPP_PRINTER_PROCESSING ? "processing" : "stopped"); + + printf("%s: %s, %s
\n", + cupsLangString(language, CUPS_MSG_PRINTER_STATE), + cupsLangString(language, pstate == IPP_PRINTER_IDLE ? CUPS_MSG_IDLE : + pstate == IPP_PRINTER_PROCESSING ? + CUPS_MSG_PROCESSING : CUPS_MSG_STOPPED), + cupsLangString(language, accepting ? CUPS_MSG_ACCEPTING_JOBS : + CUPS_MSG_NOT_ACCEPTING_JOBS)); + + if (message) + printf("
\"%s\"\n", message); + else if (!accepting || pstate == IPP_PRINTER_STOPPED) + puts("
\"Reason Unknown\""); + + puts(""); + + /* + * Show a list of jobs as needed... + */ + + if (pstate != IPP_PRINTER_IDLE) + { + /* + * Build an IPP_GET_JOBS request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + */ + + request = ippNew(); + + request->request.op.operation_id = IPP_GET_JOBS; + request->request.op.request_id = 1; + + attr = ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, + "attributes-charset", NULL, + cupsLangEncoding(language)); + + attr = ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, + "attributes-natural-language", NULL, + language->language); + + attr = ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, + "printer-uri", NULL, uri); + + jobs = cupsDoRequest(http, request, uri + 15); + } + else + jobs = NULL; + + puts(""); + jobcount = 0; + + if (jobs != NULL) + { + char *username; /* Pointer to job-originating-user-name */ + int jobid, /* job-id */ + size; /* job-k-octets */ + + + for (attr = jobs->attrs; attr != NULL; attr = attr->next) + { + /* + * Skip leading attributes until we hit a job... + */ + + while (attr != NULL && attr->group_tag != IPP_TAG_JOB) + attr = attr->next; + + if (attr == NULL) + break; + + /* + * Pull the needed attributes from this job... + */ + + jobid = 0; + size = 0; + username = NULL; + + while (attr != NULL && attr->group_tag == IPP_TAG_JOB) + { + if (strcmp(attr->name, "job-id") == 0 && + attr->value_tag == IPP_TAG_INTEGER) + jobid = attr->values[0].integer; + + if (strcmp(attr->name, "job-k-octets") == 0 && + attr->value_tag == IPP_TAG_INTEGER) + size = attr->values[0].integer; + + if (strcmp(attr->name, "job-originating-user-name") == 0 && + attr->value_tag == IPP_TAG_NAME) + username = attr->values[0].string.text; + + attr = attr->next; + } + + /* + * Display the job if it matches the current printer... + */ + + if (username != NULL) + { + jobcount ++; + printf("%s-%d %s %dk
\n", jobid, name, + jobid, username, size); + } + + if (attr == NULL) + break; + } + + ippDelete(jobs); + } + + if (jobcount == 0) + puts("None"); + puts(""); + puts(""); + + ippDelete(response); + } +} + + +/* + * End of "$Id$". + */ diff --git a/conf/Makefile b/conf/Makefile new file mode 100644 index 0000000000..3a71b1b5a5 --- /dev/null +++ b/conf/Makefile @@ -0,0 +1,61 @@ +# +# "$Id$" +# +# Configuration file makefile for the Common UNIX Printing System (CUPS). +# +# Copyright 1993-1999 by Easy Software Products. +# +# These coded instructions, statements, and computer programs are the +# property of Easy Software Products and are protected by Federal +# copyright law. Distribution and use rights are outlined in the file +# "LICENSE.txt" which should have been included with this file. If this +# file is missing or damaged please contact Easy Software Products +# at: +# +# Attn: CUPS Licensing Information +# Easy Software Products +# 44141 Airport View Drive, Suite 204 +# Hollywood, Maryland 20636-3111 USA +# +# Voice: (301) 373-9603 +# EMail: cups-info@cups.org +# WWW: http://www.cups.org +# + +include ../Makedefs + +# +# Config files... +# + +FILES = classes.conf cupsd.conf mime.convs mime.types printers.conf + +# +# Make everything... +# + +all: + +# +# Clean all config and object files... +# + +clean: + +# +# Install files... +# + +install: + -$(MKDIR) $(SERVERROOT)/conf + for file in $(FILES); do \ + if test -e $(SERVERROOT)/conf/$$file ; then \ + $(CP) $$file $(SERVERROOT)/conf/$$file.N ; \ + else \ + $(CP) $$file $(SERVERROOT)/conf ; \ + fi ; \ + end + +# +# End of "$Id$". +# diff --git a/conf/classes.conf b/conf/classes.conf new file mode 100644 index 0000000000..8b549ee847 --- /dev/null +++ b/conf/classes.conf @@ -0,0 +1,72 @@ +# +# "$Id: classes.conf 320 1999-05-13 20:40:14Z mike $" +# +# Sample class configuration file for the Common UNIX Printing System +# (CUPS) scheduler. +# +# Copyright 1997-1999 by Easy Software Products, all rights reserved. +# +# These coded instructions, statements, and computer programs are the +# property of Easy Software Products and are protected by Federal +# copyright law. Distribution and use rights are outlined in the file +# "LICENSE.txt" which should have been included with this file. If this +# file is missing or damaged please contact Easy Software Products +# at: +# +# Attn: CUPS Licensing Information +# Easy Software Products +# 44145 Airport View Drive, Suite 204 +# Hollywood, Maryland 20636-3111 USA +# +# Voice: (301) 373-9603 +# EMail: cups-info@cups.org +# WWW: http://www.cups.org +# + +######################################################################## +# # +# This is a sample class configuration file. This file is included # +# from the main configuration file (cups.conf) and lists all of the # +# printer classes known to the system. # +# # +######################################################################## + +# +# Each class starts with a definition. Class names +# can be up to 128 characters in length and are *not* case sensitive. +# +# One entry can appear in this file; if you don't +# define a default destination, the first printer or class becomes +# the default. +# + + +# +# Info: the description for the class. +# + +Info Acme LaserPrint 1000 Printers + +# +# MoreInfo: a URL for more information on the printer. +# + +MoreInfo http://www.acme.com/lp1000.html + +# +# Location: the location of the printer. +# + +Location Room 101 in the activities building + +# +# Printer: adds a printer to the class. +# + +Printer sample@host1 +Printer sample@host2 + + +# +# End of "$Id: classes.conf 320 1999-05-13 20:40:14Z mike $". +# diff --git a/conf/cupsd.conf b/conf/cupsd.conf new file mode 100644 index 0000000000..673f51e367 --- /dev/null +++ b/conf/cupsd.conf @@ -0,0 +1,324 @@ +# +# "$Id: cupsd.conf 327 1999-05-14 17:03:06Z mike $" +# +# Sample configuration file for the Common UNIX Printing System (CUPS) +# scheduler. +# +# Copyright 1997-1999 by Easy Software Products, all rights reserved. +# +# These coded instructions, statements, and computer programs are the +# property of Easy Software Products and are protected by Federal +# copyright law. Distribution and use rights are outlined in the file +# "LICENSE.txt" which should have been included with this file. If this +# file is missing or damaged please contact Easy Software Products +# at: +# +# Attn: CUPS Licensing Information +# Easy Software Products +# 44145 Airport View Drive, Suite 204 +# Hollywood, Maryland 20636-3111 USA +# +# Voice: (301) 373-9603 +# EMail: cups-info@cups.org +# WWW: http://www.cups.org +# + +######################################################################## +# # +# This is the CUPS configuration file. If you are familiar with # +# Apache or any of the other popular web servers, we've followed the # +# same format. Any configuration variable used here has the same # +# semantics as the corresponding variable in Apache. If we need # +# different functionality then a different name is used to avoid # +# confusion... # +# # +######################################################################## + +# +# Ports/addresses that we listen to. The default port 631 is reserved +# for the Internet Printing Protocol (IPP) and is what we use here. +# +# You can have multiple Port/Listen lines to listen to more than one +# port or address, or to restrict access: +# +# Port 80 +# Port 631 +# Listen hostname +# Listen hostname:80 +# Listen hostname:631 +# Listen 1.2.3.4 +# Listen 1.2.3.4:631 +# + +#Port 80 +Port 631 + +# +# User/Group: the user and group the server runs under. Normally this +# must be lp and sys, however you can configure things for another user +# or group as needed. +# +# Note: the server must be run initially as root to support the +# default IPP port of 631. It changes users whenever an external +# program is run... +# + +User lp +Group sys + +# +# SystemGroup: the group name for "System" (printer administration) +# access. +# + +SystemGroup sys + +# +# ServerName: the hostname of your server, as advertised to the world. +# By default CUPS will use the hostname of the system. +# + +#ServerName myhost.domain.com + +# +# ServerAdmin: the email address to send all complaints/problems to. +# By default CUPS will use "root@hostname". +# + +#ServerAdmin root@your.domain.com + +# +# ServerRoot: the root directory for the scheduler. +# By default the compiled-in value. +# + +#ServerRoot /var/spool/cups + +# +# AccessLog: the access log file; if this does not start with a leading / +# then it is assumed to be relative to ServerRoot. By default set to +# "logs/access_log" +# + +#AccessLog logs/access_log + +# +# ErrorLog: the error log file; if this does not start with a leading / +# then it is assumed to be relative to ServerRoot. By default set to +# "logs/error_log" +# + +#ErrorLog logs/error_log + +# +# LogLevel: controls the number of messages logged to the ErrorLog +# file and can be one of the following: +# +# debug Log everything. +# info Log all requests and state changes. +# warn Log errors and warnings. +# error Log only errors. +# none Log nothing. +# + +LogLevel warn + +# +# MaxLogSize: controls the maximum size of each log file before they are +# rotated. Defaults to 1048576 (1MB). Set to 0 to disable log rotating. +# + +#MaxLogSize: 0 + +# +# MaxRequestSize: controls the maximum size of print files. Set to 0 to +# disable this feature (defaults to 0.) +# + +#MaxRequestSize: 0 + +# +# HostNameLookups: whether or not to do lookups on IP addresses to get a +# fully-qualified hostname. This defaults to Off for performance reasons... +# + +#HostNameLookups On + +# +# Timeout: the timeout before requests time out. Default is 300 seconds. +# + +#Timeout 300 + +# +# KeepAlive: whether or not to support the Keep-Alive connection +# option. Default is on. +# + +#KeepAlive On + +# +# KeepAliveTimeout: the timeout before Keep-Alive connections are +# automatically closed. Default is 60 seconds. +# + +#KeepAliveTimeout 60 + +# +# ImplicitClasses: whether or not to use implicit classes. +# +# Printer classes can be specified explicitly in the classes.conf +# file, implicitly based upon the printers available on the LAN, or +# both. +# +# When ImplicitClasses is On, printers on the LAN with the same name +# (e.g. Acme-LaserPrint-1000) will be put into a class with the same +# name. This allows you to setup multiple redundant queues on a LAN +# without a lot of administrative difficulties. If a user sends a +# job to Acme-LaserPrint-1000, the job will go to the first available +# queue. +# +# Enabled by default. +# + +#ImplicitClasses On + +# +# Browsing: whether or not to broadcast printer information to +# other CUPS servers. Enabled by default. +# + +#Browsing On + +# +# BrowseInterval: the time between browsing updates in seconds. Default +# is 30 seconds. +# +# Note that browsing information is sent whenever a printer's state changes +# as well, so this represents the maximum time between updates. +# + +#BrowseInterval 30 + +# +# BrowseTimeout: the timeout for network printers - if we don't +# get an update within this time the printer will be removed +# from the printer list. This number definitely should not be +# less the BrowseInterval value for obvious reasons. Defaults +# to 300 seconds. +# + +#BrowseTimeout 300 + +# +# BrowsePort: the port used for UDP broadcasts. By default this is +# the IPP port; if you change this you need to do it on all servers. +# Only one BrowsePort is recognized. +# + +#BrowsePort 631 + +# +# BrowseAddress: specifies a broadcast address to be used. By +# default browsing information is broadcast to all active interfaces. +# +# Note: HP-UX 10.20 and earlier do not properly handle broadcast unless +# you have a Class A, B, C, or D netmask (i.e. no CIDR support). +# + +#BrowseAddress x.y.z.255 +#BrowseAddress x.y.255.255 +#BrowseAddress x.255.255.255 + +# +# DocumentRoot: the root directory for HTTP documents that are served. +# By default the compiled in directory. +# + +#DocumentRoot /usr/share/cups/doc + +# +# DefaultLanguage: the default language if not specified by the browser. +# If not specified, the current locale is used. +# + +#DefaultLanguage en + +# +# DefaultCharset: the default character set to use. If not specified, +# defaults to iso-8859-1. Note that this can also be overridden in +# HTML documents... +# + +#DefaultCharset iso-8859-1 + +# +# RIPCache: the amount of memory that each RIP should use to cache +# bitmaps. The value can be any real number followed by "k" for +# kilobytes, "m" for megabytes, "g" for gigabytes, or "t" for tiles +# (1 tile = 256x256 pixels.) Defaults to "32m" (32 megabytes). +# + +#RIPCache: 32m + +# +# Access permissions for each directory served by the scheduler. +# Locations are relative to DocumentRoot... +# +# AuthType: the authorization to use; currently only "Basic" authorization is +# supported. +# +# AuthClass: the authorization class; currently only "Anonymous", "User", +# "System" (valid user belonging to group SystemGroupName), and "Group" +# (valid user belonging to the specified group) are supported. +# +# AuthGroupName: the group name for "Group" authorization. +# +# Order: the order of Allow/Deny processing. +# +# Allow: allows access from the specified hostname, domain, IP address, or +# network. +# +# Deny: denies access from the specified hostname, domain, IP address, or +# network. +# + + + + + +# +# You may wish to limit access to printers and classes, either with Allow +# and Deny lines, or by requiring a username and password. +# + +## Require a username and password +#AuthType Basic +#AuthClass User + +## Restrict access to local domain +#Order Deny,Allow +#Deny From All +#Allow From .mydomain.com + + + +# +# You definitely will want to limit access to the administration tools. +# The default configuration requires a local connection from a user who +# is a member of group "sys" to do any admin tasks. You can change the +# group name using the SystemGroup directive. +# + +AuthType Basic +AuthClass System + +## Restrict access to local domain +Order Deny,Allow +Deny From All +Allow From 127.0.0.1 + + +# +# End of "$Id: cupsd.conf 327 1999-05-14 17:03:06Z mike $". +# diff --git a/conf/mime.convs b/conf/mime.convs new file mode 100644 index 0000000000..02f6945fff --- /dev/null +++ b/conf/mime.convs @@ -0,0 +1,62 @@ +# +# "$Id: mime.convs 237 1999-04-21 19:29:35Z mike $" +# +# MIME converts file for the Common UNIX Printing System (CUPS). +# +# Copyright 1997-1999 by Easy Software Products. +# +# These coded instructions, statements, and computer programs are the +# property of Easy Software Products and are protected by Federal +# copyright law. Distribution and use rights are outlined in the file +# "LICENSE.txt" which should have been included with this file. If this +# file is missing or damaged please contact Easy Software Products +# at: +# +# Attn: CUPS Licensing Information +# Easy Software Products +# 44141 Airport View Drive, Suite 204 +# Hollywood, Maryland 20636-3111 USA +# +# Voice: (301) 373-9603 +# EMail: cups-info@cups.org +# WWW: http://www.cups.org +# + +######################################################################## +# +# Format of Lines: +# +# source/type destination/type cost filter +# +# General Notes: +# +# Currently the "cost" field is not used (all filters are assumed to +# be equally costly in terms of speed/memory). Also, a filter program +# *must* accept the standard command-line arguments (job-id, user, title, +# copies,options,[filename or stdin]) or this won't work. +# + +######################################################################## +# +# PostScript filters +# + +application/msword application/postscript 50 mswordtops +application/pdf application/postscript 50 pdftops +application/postscript application/vnd.cups-postscript 50 pstops +application/vnd.hp-HPGL application/postscript 50 hpgltops +image/* application/vnd.cups-postscript 50 imagetops +text/html application/postscript 50 htmltops +text/plain application/postscript 50 texttops + +######################################################################## +# +# Raster filters... +# + +image/* application/vnd.cups-raster 50 imagetoraster +application/vnd.cups-postscript application/vnd.cups-raster 50 pstoraster + +# +# End of "$Id: mime.convs 237 1999-04-21 19:29:35Z mike $". +# diff --git a/conf/mime.types b/conf/mime.types new file mode 100644 index 0000000000..85e7e1c6c6 --- /dev/null +++ b/conf/mime.types @@ -0,0 +1,123 @@ +# +# "$Id: mime.types 185 1999-03-24 18:38:50Z mike $" +# +# MIME types file for the Common UNIX Printing System (CUPS). +# +# Copyright 1997-1999 by Easy Software Products. +# +# These coded instructions, statements, and computer programs are the +# property of Easy Software Products and are protected by Federal +# copyright law. Distribution and use rights are outlined in the file +# "LICENSE.txt" which should have been included with this file. If this +# file is missing or damaged please contact Easy Software Products +# at: +# +# Attn: CUPS Licensing Information +# Easy Software Products +# 44141 Airport View Drive, Suite 204 +# Hollywood, Maryland 20636-3111 USA +# +# Voice: (301) 373-9603 +# EMail: cups-info@cups.org +# WWW: http://www.cups.org +# + +######################################################################## +# +# Format of Lines: +# +# super/type rules +# +# "rules" can be any combination of: +# +# ( expr ) Parenthesis for expression grouping +# + Logical AND +# , or whitespace Logical OR +# ! Logical NOT +# match("pattern") Pattern match on filename +# extension Pattern match on "*.extension" +# ascii(offset,length) True if bytes are valid printable ASCII +# (CR, NL, TAB, BS, 32-126) +# printable(offset,length) True if bytes are printable 8-bit chars +# (CR, NL, TAB, BS, 32-126, 160-254) +# string(offset,"string") True if bytes are identical to string +# char(offset,value) True if byte is identical +# short(offset,value) True if 16-bit integer is identical +# int(offset,value) True if 32-bit integer is identical +# locale("string") True if current locale matches string +# +# General Notes: +# +# MIME type names are case-insensitive. Internally they are converted +# to lowercase. Multiple occurrences of a type will cause the provided +# rules to be appended to the existing definition. Type names are sorted +# in ascending order, so if two types use the same rules to resolve a type +# (e.g. doc extension for two types), the returned type will be the first +# type in the sorted list. +# +# The "printable" rule differs from the "ascii" rule in that it also +# accepts 8-bit characters in the range 160-254. +# +# String constants must be surrounded by "" if they contain whitespace. +# To instead binary data into a string, use the notation. +# + +######################################################################## +# +# Application-generated files... +# + +application/msword doc string(0,) +application/pdf pdf string(0,%PDF) +application/postscript ai eps ps string(0,%!) string(0,<04>%!) +application/vnd.hp-HPGL hpgl string(0,<1b>%) string(0,<1b>&)\ + string(0,<1b>E) string(0,<201b>)\ + string(0,BP;) string(0,IN;) string(0,DF;) + +######################################################################## +# +# Image files... +# + +image/gif gif string(0,GIF87a) string(0,GIF89a) +image/png png string(0,<89>PNG) +image/jpeg jpeg jpg jpe string(6,JFIF) +image/tiff tiff tif string(0,MM) string(0,II) +image/x-photocd pcd string(2048,PCD_IPI) +image/x-portable-anymap pnm +image/x-portable-bitmap pbm string(0,P1) string(0,P4) +image/x-portable-graymap pgm string(0,P2) string(0,P5) +image/x-portable-pixmap ppm string(0,P3) string(0,P6) +image/x-sgi-rgb rgb sgi bw icon short(0,474) +image/x-xbitmap xbm +image/x-xpixmap xpm ascii(0,1024) + string(3,"XPM") +image/x-xwindowdump xwd + +# TODO: Add Sun Raster, Alias, SoftImage, GIMP??? files + +image/x-sun-raster ras +#image/x-alias pix +#image/x-softimage +#image/x-gimp-xcf xcf xcf.gz + +######################################################################## +# +# Text files... +# + +text/html html htm printable(0,1024) +\ + (string(0,"") string(0," definition. Printer names +# can be up to 128 characters in length and are *not* case sensitive. +# +# One entry can appear in this file; if you don't +# define a default destination, the first printer or class becomes the +# default. +# + + +# +# Info: the description for the printer. +# + +Info Acme LaserPrint 1000 + +# +# MoreInfo: a URL for more information on the printer. +# + +MoreInfo http://www.acme.com/lp1000.html + +# +# Location: the location of the printer. +# + +Location Room 101 in the activities building + +# +# DeviceURI: the device URI for this printer. +# + +#DeviceURI parallel:/dev/plp +#DeviceURI serial:/dev/ttyd1?baud=38400+size=8+parity=none+flow=soft +#DeviceURI scsi:/dev/scsi/sc1d6l0 +#DeviceURI socket://hostname:port +#DeviceURI tftp://hostname/path +#DeviceURI ftp://hostname/path +#DeviceURI http://hostname[:port]/path +#DeviceURI ipp://hostname/path +#DeviceURI smb://hostname/printer + +# +# AddFilter: adds a filter for this printer. Format is: +# +# AddFilter from-type cost program +# +# Filter programs must accept the standard filter options outlined in +# the CUPS documentation. A filter program of "-" means that the +# two types are equivalent. +# + +AddFilter application/cups-postscript 0 - + +# +# State: sets the initial state of the printer. Can be one of the +# following: +# +# Idle - Printer is available to accept new jobs. +# Stopped - Printer is disabled but accepting new jobs. +# + +State Idle + + +# +# End of "$Id: printers.conf 320 1999-05-13 20:40:14Z mike $". +# diff --git a/config.h.in b/config.h.in new file mode 100644 index 0000000000..8e42e793dd --- /dev/null +++ b/config.h.in @@ -0,0 +1,95 @@ +/* + * "$Id$" + * + * Configuration file for the Common UNIX Printing System (CUPS). + * + * @configure_input@ + * + * Copyright 1997-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44145 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + */ + +/* + * Version of software... + */ + +#define CUPS_SVERSION "CUPS v1.0" + +/* + * Where are files stored? + */ + +#define CUPS_LOCALEDIR "/usr/lib/locale" +#define CUPS_SERVERROOT "/var/cups" +#define CUPS_DATADIR "/usr/share/cups" + +/* + * Do we have various image libraries? + */ + +#undef HAVE_LIBPNG +#undef HAVE_LIBZ +#undef HAVE_LIBJPEG +#undef HAVE_LIBTIFF + +/* + * Does this machine store words in big-endian (MSB-first) order? + */ + +#undef WORDS_BIGENDIAN + +/* + * Which directory functions and headers do we use? + */ + +#undef HAVE_DIRENT_H +#undef HAVE_SYS_DIR_H +#undef HAVE_SYS_NDIR_H +#undef HAVE_NDIR_H + +/* + * Do we have ? + */ + +#undef HAVE_SHADOW_H + +/* + * Do we have the strXXX() functions? + */ + +#undef HAVE_STRDUP +#undef HAVE_STRCASECMP +#undef HAVE_STRNCASECMP + +/* + * What signal functions to use? + */ + +#undef HAVE_SIGSET +#undef HAVE_SIGACTION + +/* + * What wait functions to use? + */ + +#undef HAVE_WAITPID +#undef HAVE_WAIT3 + +/* + * End of "$Id$". + */ diff --git a/configure.in b/configure.in new file mode 100644 index 0000000000..3f0799bb56 --- /dev/null +++ b/configure.in @@ -0,0 +1,142 @@ +dnl +dnl "$Id$" +dnl +dnl Configuration script for the Common UNIX Printing System (CUPS). +dnl +dnl Copyright 1997-1999 by Easy Software Products, all rights reserved. +dnl +dnl These coded instructions, statements, and computer programs are the +dnl property of Easy Software Products and are protected by Federal +dnl copyright law. Distribution and use rights are outlined in the file +dnl "LICENSE.txt" which should have been included with this file. If this +dnl file is missing or damaged please contact Easy Software Products +dnl at: +dnl +dnl Attn: CUPS Licensing Information +dnl Easy Software Products +dnl 44145 Airport View Drive, Suite 204 +dnl Hollywood, Maryland 20636-3111 USA +dnl +dnl Voice: (301) 373-9603 +dnl EMail: cups-info@cups.org +dnl WWW: http://www.cups.org +dnl + +AC_INIT(cups/cups.h) +AC_CONFIG_HEADER(config.h) +AC_PREFIX_DEFAULT(/usr) + +dnl Clear default debugging options and set normal optimization by +dnl default unless the user asks for debugging specifically. + +CFLAGS="${CFLAGS:=}" +CXXFLAGS="${CXXFLAGS:=}" +OPTIM="-O" +AC_SUBST(OPTIM) + +AC_ARG_ENABLE(debug, [ --enable-debug turn on debugging [default=no]], +if eval "test x$enable_debug = xyes"; then + OPTIM="-g" +fi) + +dnl Checks for programs... +AC_PROG_AWK +AC_PROG_CC +AC_PROG_CPP +AC_PROG_RANLIB +AC_PATH_PROG(AR,ar) +AC_PATH_PROG(CP,cp) +AC_PATH_PROG(MKDIR,mkdir) +AC_PATH_PROG(RM,rm) +AC_PATH_PROG(GROFF,groff) +AC_PATH_PROG(HTMLDOC,htmldoc) + +dnl Architecture checks... +AC_C_BIGENDIAN +uname=`uname` +if test "$uname" = "IRIX64"; then + uname=IRIX +fi + +dnl Check for libraries... +AC_CHECK_LIB(c,crypt,LIBS="$LIBS",AC_CHECK_LIB(crypt,crypt)) +AC_CHECK_LIB(sec,getspent) +AC_CHECK_LIB(socket,socket, +if test "$uname" != "IRIX"; then + LIBS="$LIBS -lsocket" +else + echo "Not using -lsocket since you are running IRIX." +fi) +AC_CHECK_LIB(nsl,gethostbyaddr, +if test "$uname" != "IRIX"; then + LIBS="$LIBS -lnsl" +else + echo "Not using -lnsl since you are running IRIX." +fi) + +IMGLIBS="" +AC_SUBST(IMGLIBS) +AC_CHECK_LIB(jpeg,jpeg_destroy_decompress, + AC_CHECK_HEADER(jpeglib.h, + AC_DEFINE(HAVE_LIBJPEG) + IMGLIBS="$IMGLIBS -ljpeg")) +AC_CHECK_LIB(png,png_read_info, + AC_CHECK_HEADER(png.h, + AC_DEFINE(HAVE_LIBPNG) + IMGLIBS="$IMGLIBS -lpng")) +AC_CHECK_LIB(tiff,TIFFGetField, + AC_CHECK_HEADER(tiff.h, + AC_DEFINE(HAVE_LIBTIFF) + IMGLIBS="$IMGLIBS -ltiff")) +AC_CHECK_LIB(z,deflate, + AC_CHECK_HEADER(zlib.h, + AC_DEFINE(HAVE_LIBZ) + IMGLIBS="$IMGLIBS -lz")) + +dnl Checks for header files. +AC_HEADER_STDC +AC_HEADER_DIRENT +AC_CHECK_HEADER(shadow.h,AC_DEFINE(HAVE_SHADOW_H)) + +dnl Checks for string functions. +AC_CHECK_FUNCS(strdup) +AC_CHECK_FUNCS(strcasecmp) +AC_CHECK_FUNCS(strncasecmp) + +dnl Checks for signal functions. +AC_CHECK_FUNCS(sigset) +AC_CHECK_FUNCS(sigaction) + +dnl Checks for wait functions. +AC_CHECK_FUNCS(waitpid) +AC_CHECK_FUNCS(wait3) + +dnl Fix "prefix" variable if it hasn't been specified... +if test "$prefix" = "NONE"; then + prefix="/usr" +fi + +dnl CUPS_SERVERROOT needs special attention for the default location... +if test "$prefix" = "/usr"; then + CUPS_SERVERROOT="/var/cups" +else + CUPS_SERVERROOT="$prefix/var/cups" +fi +AC_DEFINE_UNQUOTED(CUPS_SERVERROOT, "$CUPS_SERVERROOT") +AC_SUBST(CUPS_SERVERROOT) + +dnl Set the CUPS_LOCALE directory... +CUPS_LOCALEDIR="$prefix/lib/locale" +AC_DEFINE_UNQUOTED(CUPS_LOCALEDIR, "$CUPS_LOCALEDIR") +AC_SUBST(CUPS_LOCALEDIR) + +dnl Set the CUPS_DATAFILE directory... +CUPS_DATADIR="$prefix/share/cups" +AC_DEFINE_UNQUOTED(CUPS_DATADIR, "$CUPS_DATADIR") +AC_SUBST(CUPS_DATADIR) + +AC_OUTPUT(Makedefs) + +dnl +dnl End of "$Id$". +dnl diff --git a/cups.dsw b/cups.dsw new file mode 100644 index 0000000000..e332b183d5 --- /dev/null +++ b/cups.dsw @@ -0,0 +1,113 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "cups"=.\cups\cups.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "hpgltops"=.\filter\hpgltops.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name cups + End Project Dependency +}}} + +############################################################################### + +Project: "image"=.\filter\image.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "pstops"=.\filter\pstops.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "testmime"=.\cups\testmime.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name cups + End Project Dependency +}}} + +############################################################################### + +Project: "testppd"=.\cups\testppd.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name cups + End Project Dependency +}}} + +############################################################################### + +Project: "texttops"=.\filter\texttops.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name cups + End Project Dependency +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/cups/Makefile b/cups/Makefile new file mode 100644 index 0000000000..dd7287b7cf --- /dev/null +++ b/cups/Makefile @@ -0,0 +1,130 @@ +# +# "$Id$" +# +# Support library Makefile for the Common UNIX Printing System (CUPS). +# +# Copyright 1997-1999 by Easy Software Products, all rights reserved. +# +# These coded instructions, statements, and computer programs are the +# property of Easy Software Products and are protected by Federal +# copyright law. Distribution and use rights are outlined in the file +# "LICENSE.txt" which should have been included with this file. If this +# file is missing or damaged please contact Easy Software Products +# at: +# +# Attn: CUPS Licensing Information +# Easy Software Products +# 44145 Airport View Drive, Suite 204 +# Hollywood, Maryland 20636-3111 USA +# +# Voice: (301) 373-9603 +# EMail: cups-info@cups.org +# WWW: http://www.cups.org +# + +include ../Makedefs + +# +# Object files... +# + +OBJS = emit.o filter.o http.o ipp.o language.o mark.o mime.o \ + options.o page.o ppd.o raster.o string.o type.o util.o + +# +# Header files to install... +# + +HEADERS = cups.h http.h ipp.h language.h mime.h ppd.h raster.h + +# +# Targets in this directory... +# + +TARGETS = libcups.a testmime testppd testhttp + +# +# Make all targets... +# + +all: $(TARGETS) + +# +# Remove object and target files... +# + +clean: + rm -f $(OBJS) $(TARGETS) + +# +# Install object and target files... +# + +install: all + -$(MKDIR) $(LIBDIR) + $(CP) libcups.a $(LIBDIR) + -$(MKDIR) $(INCLUDEDIR)/cups + $(CP) $(HEADERS) $(INCLUDEDIR)/cups + +# +# libcups.a +# + +libcups.a: $(OBJS) + $(RM) $@ + $(AR) $(ARFLAGS) $@ $(OBJS) + $(RANLIB) $@ + +# +# cups_C.h - the default POSIX locale that is compiled in. +# + +cups_C.h: ../locale/C/cups_C + $(RM) cups_C.h + $(AWK) '{print "\"" $$0 "\","}' < ../locale/C/cups_C > cups_C.h + +emit.o: ppd.h ../config.h ../Makedefs +filter.o: mime.h ../config.h ../Makedefs +http.o: http.h ipp.h string.h ../config.h ../Makedefs +ipp.o: http.h ipp.h ../config.h ../Makedefs +language.o: cups_C.h language.h string.h ../config.h ../Makedefs +mark.o: ppd.h ../config.h ../Makedefs +mime.o: mime.h ../config.h ../Makedefs +options.o: cups.h ../config.h ../Makedefs +page.o: ppd.h ../config.h ../Makedefs +ppd.o: ppd.h ../config.h ../Makedefs +raster.o: raster.h ../config.h ../Makedefs +string.o: string.h ../config.h ../Makedefs +type.o: mime.h ../config.h ../Makedefs +util.o: cups.h http.h ipp.h ../config.h ../Makedefs + +# +# testhttp +# + +testhttp: testhttp.o libcups.a + $(CC) $(LDFLAGS) -o $@ testhttp.o $(LIBS) + +testhttp.o: http.h ../Makedefs + +# +# testmime +# + +testmime: testmime.o libcups.a + $(CC) $(LDFLAGS) -o $@ testmime.o $(LIBS) + +testmime.o: mime.h ../Makedefs + +# +# testppd +# + +testppd: testppd.o libcups.a + $(CC) $(LDFLAGS) -o $@ testppd.o $(LIBS) + +testppd.o: ppd.h ../Makedefs + +# +# End of "$Id$". +# diff --git a/cups/cups.h b/cups/cups.h new file mode 100644 index 0000000000..317f3c11e4 --- /dev/null +++ b/cups/cups.h @@ -0,0 +1,135 @@ +/* + * "$Id$" + * + * API definitions for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + */ + +#ifndef _CUPS_CUPS_H_ +# define _CUPS_CUPS_H_ + +/* + * Include necessary headers... + */ + +# include +# include +# include + + +/* + * C++ magic... + */ + +# ifdef __cplusplus +extern "C" { +# endif /* __cplusplus */ + + +/* + * Constants... + */ + +# define CUPS_VERSION 1.0 +# define CUPS_DATE_ANY -1 + + +/* + * Types and structures... + */ + +typedef unsigned cups_ptype_t; /**** Printer Type/Capability Bits ****/ +enum /* Not a typedef'd enum so we can OR */ +{ + CUPS_PRINTER_LOCAL = 0x0000, /* Local printer or class */ + CUPS_PRINTER_CLASS = 0x0001, /* Printer class */ + CUPS_PRINTER_REMOTE = 0x0002, /* Remote printer or class */ + CUPS_PRINTER_BW = 0x0004, /* Can do B&W printing */ + CUPS_PRINTER_COLOR = 0x0008, /* Can do color printing */ + CUPS_PRINTER_DUPLEX = 0x0010, /* Can do duplexing */ + CUPS_PRINTER_STAPLE = 0x0020, /* Can staple output */ + CUPS_PRINTER_COPIES = 0x0040, /* Can do copies */ + CUPS_PRINTER_COLLATE = 0x0080, /* Can collage copies */ + CUPS_PRINTER_PUNCH = 0x0100, /* Can punch output */ + CUPS_PRINTER_COVER = 0x0200, /* Can cover output */ + CUPS_PRINTER_BIND = 0x0400, /* Can bind output */ + CUPS_PRINTER_SORT = 0x0800, /* Can sort output */ + CUPS_PRINTER_SMALL = 0x1000, /* Can do Letter/Legal/A4 */ + CUPS_PRINTER_MEDIUM = 0x2000, /* Can do Tabloid/B/C/A3/A2 */ + CUPS_PRINTER_LARGE = 0x4000, /* Can do D/E/A1/A0 */ + CUPS_PRINTER_VARIABLE = 0x8000 /* Can do variable sizes */ +}; + + +/* + * Types & structures... + */ + +typedef struct /**** Printer Information ****/ +{ + char name[IPP_MAX_NAME], /* Printer or class name */ + uri[HTTP_MAX_URI]; /* Universal resource identifier */ + unsigned char info[IPP_MAX_NAME], /* Printer or class info/description */ + location[IPP_MAX_NAME]; /* Location text */ + ipp_pstate_t state; /* Printer state */ + unsigned char message[IPP_MAX_NAME]; /* State text */ + cups_ptype_t type; /* Printer type/capability codes */ +} cups_browse_t; + +typedef struct /**** Printer Options ****/ +{ + char *name; /* Name of option */ + char *value; /* Value of option */ +} cups_option_t; + + +/* + * Functions... + */ + +extern int cupsCancelJob(char *printer, int job); +extern ipp_t *cupsDoRequest(http_t *http, ipp_t *request, + char *resource); +extern int cupsGetClasses(char ***classes); +extern char *cupsGetPPD(char *printer); +extern char *cupsGetDefault(void); +extern int cupsGetPrinters(char ***printers); +extern int cupsPrintFile(char *printer, char *filename, char *title, + int num_options, cups_option_t *options); + +extern int cupsAddOption(char *name, char *value, int num_options, + cups_option_t **options); +extern void cupsFreeOptions(int num_options, cups_option_t *options); +extern char *cupsGetOption(char *name, int num_options, + cups_option_t *options); +extern int cupsParseOptions(char *arg, int num_options, + cups_option_t **options); +extern int cupsMarkOptions(ppd_file_t *ppd, int num_options, + cups_option_t *options); + +# ifdef __cplusplus +} +# endif /* __cplusplus */ + +#endif /* !_CUPS_CUPS_H_ */ + +/* + * End of "$Id$". + */ diff --git a/cups/debug.h b/cups/debug.h new file mode 100644 index 0000000000..3a3d033a1b --- /dev/null +++ b/cups/debug.h @@ -0,0 +1,57 @@ +/* + * "$Id$" + * + * Debugging macros for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44145 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + */ + +#ifndef _CUPS_DEBUG_H_ +# define _CUPS_DEBUG_H_ + +/* + * Include necessary headers... + */ + +# include + +/* + * The debug macros are used if you compile with DEBUG defined. + * + * Usage: + * + * DEBUG_puts("string") + * DEBUG_printf(("format string", arg, arg, ...)); + * + * Note the extra parenthesis around the DEBUG_printf macro... + */ + +# ifdef DEBUG +# define DEBUG_puts(x) puts(x) +# define DEBUG_printf(x) printf x +# else +# define DEBUG_puts(x) +# define DEBUG_printf(x) +# endif /* DEBUG */ + +#endif /* !_CUPS_DEBUG_H_ */ + +/* + * End of "$Id$". + */ diff --git a/cups/emit.c b/cups/emit.c new file mode 100644 index 0000000000..b8681e69b4 --- /dev/null +++ b/cups/emit.c @@ -0,0 +1,301 @@ +/* + * "$Id$" + * + * PPD code emission routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-1999 by Easy Software Products, all rights reserved. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * PostScript is a trademark of Adobe Systems, Inc. + * + * Contents: + * + * ppdEmit() - Emit code for marked options to a file. + * ppdEmitFd() - Emit code for marked options to a file. + */ + +/* + * Include necessary headers... + */ + +#include "ppd.h" +#include +#include "string.h" + +#if defined(WIN32) || defined(__EMX__) +# include +#else +# include +#endif /* WIN32 || __EMX__ */ + + +/* + * Local functions... + */ + +static int ppd_sort(ppd_choice_t **c1, ppd_choice_t **c2); +static int ppd_collect(ppd_file_t *ppd, ppd_section_t section, + ppd_choice_t ***choices); + + +/* + * 'ppdEmit()' - Emit code for marked options to a file. + */ + +int /* O - 0 on success, -1 on failure */ +ppdEmit(ppd_file_t *ppd, /* I - PPD file record */ + FILE *fp, /* I - File to write to */ + ppd_section_t section) /* I - Section to write */ +{ + int i, /* Looping var */ + count; /* Number of choices */ + ppd_choice_t **choices; /* Choices */ + ppd_size_t *size; /* Custom page size */ + + + if ((count = ppd_collect(ppd, section, &choices)) == 0) + return (0); + + for (i = 0; i < count; i ++) + if (section != PPD_ORDER_EXIT && section != PPD_ORDER_JCL) + { + /* + * Send DSC comments with option... + */ + + if (fprintf(fp, "%%%%BeginFeature: %s %s\n", + ((ppd_option_t *)choices[i]->option)->keyword, + choices[i]->choice) < 0) + { + free(choices); + return (-1); + } + + if (strcmp(((ppd_option_t *)choices[i]->option)->keyword, "PageSize") == 0 && + strcmp(choices[i]->choice, "Custom") == 0) + { + /* + * Variable size; write out standard size options (this should + * eventually be changed to use the parameter positions defined + * in the PPD file...) + */ + + size = ppdPageSize(ppd, "Custom"); + fprintf(fp, "%.0f %.0f 0 0 0\n", size->width, size->length); + + if (choices[i]->code == NULL) + { + /* + * This can happen with certain buggy PPD files that don't include + * a CustomPageSize command sequence... We just use a generic + * Level 2 command sequence... + */ + + fputs("pop pop pop\n", fp); + fputs("<>setpagedevice\n", fp); + } + } + + if (choices[i]->code != NULL && choices[i]->code[0] != '\0') + { + if (fputs(choices[i]->code, fp) < 0) + { + free(choices); + return (-1); + } + + if (choices[i]->code[strlen(choices[i]->code) - 1] != '\n') + putc('\n', fp); + } + + if (fputs("%%EndFeature\n", fp) < 0) + { + free(choices); + return (-1); + } + } + else if (fputs(choices[i]->code, fp) < 0) + { + free(choices); + return (-1); + } + + free(choices); + return (0); +} + + +/* + * 'ppdEmitFd()' - Emit code for marked options to a file. + */ + +int /* O - 0 on success, -1 on failure */ +ppdEmitFd(ppd_file_t *ppd, /* I - PPD file record */ + int fd, /* I - File to write to */ + ppd_section_t section) /* I - Section to write */ +{ + int i, /* Looping var */ + count; /* Number of choices */ + ppd_choice_t **choices; /* Choices */ + char buf[1024]; /* Output buffer for feature */ + + + if ((count = ppd_collect(ppd, section, &choices)) == 0) + return (0); + + for (i = 0; i < count; i ++) + if (section != PPD_ORDER_EXIT && section != PPD_ORDER_JCL) + { + /* + * Send DSC comments with option... + */ + + sprintf(buf, "%%%%BeginFeature: %s %s\n", + ((ppd_option_t *)choices[i]->option)->keyword, choices[i]->choice); + + if (write(fd, buf, strlen(buf)) < 1) + { + free(choices); + return (-1); + } + + if (write(fd, choices[i]->code, strlen(choices[i]->code)) < 1) + { + free(choices); + return (-1); + } + + if (write(fd, "%%EndFeature\n", 13) < 1) + { + free(choices); + return (-1); + } + } + else if (write(fd, choices[i]->code, strlen(choices[i]->code)) < 1) + { + free(choices); + return (-1); + } + + free(choices); + return (0); +} + + +/* + * 'ppd_sort()' - Sort options by ordering numbers... + */ + +static int /* O - -1 if c1 < c2, 0 if equal, 1 otherwise */ +ppd_sort(ppd_choice_t **c1, /* I - First choice */ + ppd_choice_t **c2) /* I - Second choice */ +{ + if (((ppd_option_t *)(*c1)->option)->order < ((ppd_option_t *)(*c2)->option)->order) + return (-1); + else if (((ppd_option_t *)(*c1)->option)->order > ((ppd_option_t *)(*c2)->option)->order) + return (1); + else + return (0); +} + + +/* + * 'ppd_collect()' - Collect all marked options that reside in the specified + * section. + */ + +static int /* O - Number of options marked */ +ppd_collect(ppd_file_t *ppd, /* I - PPD file data */ + ppd_section_t section, /* I - Section to collect */ + ppd_choice_t ***choices) /* O - Pointers to choices */ +{ + int i, j, k, m; /* Looping vars */ + ppd_group_t *g, /* Current group */ + *sg; /* Current sub-group */ + ppd_option_t *o; /* Current option */ + ppd_choice_t *c; /* Current choice */ + int count; /* Number of choices collected */ + ppd_choice_t **collect; /* Collected choices */ + + + if (ppd == NULL) + return (0); + + /* + * Allocate memory for up to 1000 selected choices... + */ + + count = 0; + collect = calloc(sizeof(ppd_choice_t *), 1000); + + /* + * Loop through all options and add choices as needed... + */ + + for (i = ppd->num_groups, g = ppd->groups; i > 0; i --, g ++) + { + for (j = g->num_options, o = g->options; j > 0; j --, o ++) + if (o->section == section) + for (k = o->num_choices, c = o->choices; k > 0; k --, c ++) + if (c->marked && count < 1000) + { + collect[count] = c; + count ++; + } + + for (j = g->num_subgroups, sg = g->subgroups; j > 0; j --, sg ++) + for (k = sg->num_options, o = sg->options; k > 0; k --, o ++) + if (o->section == section) + for (m = o->num_choices, c = o->choices; m > 0; m --, c ++) + if (c->marked && count < 1000) + { + collect[count] = c; + count ++; + } + } + + /* + * If we have more than 1 marked choice, sort them... + */ + + if (count > 1) + qsort(collect, count, sizeof(ppd_choice_t *), + (int (*)(const void *, const void *))ppd_sort); + + /* + * Return the array and number of choices; if 0, free the array since + * it isn't needed. + */ + + if (count > 0) + { + *choices = collect; + return (count); + } + else + { + *choices = NULL; + free(collect); + return (0); + } +} + + +/* + * End of "$Id$". + */ diff --git a/cups/filter.c b/cups/filter.c new file mode 100644 index 0000000000..155f8ecc7d --- /dev/null +++ b/cups/filter.c @@ -0,0 +1,329 @@ +/* + * "$Id$" + * + * File type conversion routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-1999 by Easy Software Products, all rights reserved. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44145 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * mimeAddFilter() - Add a filter to the current MIME database. + * mimeFilter() - Find the fastest way to convert from one type to another. + * compare() - Compare two filter types... + * lookup() - Lookup a filter... + * + * Revision History: + * + * $Log: filter.c,v $ + * Revision 1.6 1999/04/21 14:49:49 mike + * cupsDoRequest() needed to retry requests when doing authorization. + * + * mimeFilter() didn't always return the least-cost filter. + * + * Revision 1.5 1999/03/01 20:51:51 mike + * Code cleanup - removed extraneous semi-colons... + * + * Revision 1.4 1999/02/05 17:40:51 mike + * Added IPP client read/write code. + * + * Added string functions missing from some UNIXs. + * + * Added option parsing functions. + * + * Added IPP convenience functions (not implemented yet). + * + * Updated source files to use local string.h as needed (for + * missing string functions) + * + * Revision 1.3 1999/01/24 14:18:43 mike + * Check-in prior to CVS use. + * + * Revision 1.2 1998/08/06 14:38:38 mike + * Finished coding and testing for CUPS 1.0. + * + * Revision 1.1 1998/06/11 20:50:53 mike + * Initial revision + */ + +/* + * Include necessary headers... + */ + +#include +#include +#include + +#include "string.h" +#include "mime.h" + + +/* + * Local functions... + */ + +static int compare(mime_filter_t *, mime_filter_t *); +static mime_filter_t *lookup(mime_t *, mime_type_t *, mime_type_t *); + + +/* + * 'mimeAddFilter()' - Add a filter to the current MIME database. + */ + +mime_filter_t * /* O - New filter */ +mimeAddFilter(mime_t *mime, /* I - MIME database */ + mime_type_t *src, /* I - Source type */ + mime_type_t *dst, /* I - Destination type */ + int cost, /* I - Relative time/resource cost */ + char *filter) /* I - Filter program to run */ +{ + mime_filter_t *temp; /* New filter */ + + + /* + * Range-check the input... + */ + + if (mime == NULL || src == NULL || dst == NULL || filter == NULL) + return (NULL); + + if (strlen(filter) > (MIME_MAX_FILTER - 1)) + return (NULL); + + /* + * See if we already have an existing filter for the given source and + * destination... + */ + + if ((temp = lookup(mime, src, dst)) != NULL) + { + /* + * Yup, does the existing filter have a higher cost? If so, copy the + * filter and cost to the existing filter entry and return it... + */ + + if (temp->cost > cost) + { + temp->cost = cost; + strcpy(temp->filter, filter); + } + } + else + { + /* + * Nope, add a new one... + */ + + if (mime->num_filters == 0) + temp = malloc(sizeof(mime_filter_t)); + else + temp = realloc(mime->filters, sizeof(mime_filter_t) * (mime->num_filters + 1)); + + if (temp == NULL) + return (NULL); + + mime->filters = temp; + temp += mime->num_filters; + mime->num_filters ++; + + /* + * Copy the information over and sort if necessary... + */ + + temp->src = src; + temp->dst = dst; + temp->cost = cost; + strcpy(temp->filter, filter); + + if (mime->num_filters > 1) + qsort(mime->filters, mime->num_filters, sizeof(mime_filter_t), + (int (*)(const void *, const void *))compare); + } + + /* + * Return the new/updated filter... + */ + + return (temp); +} + + +/* + * 'mimeFilter()' - Find the fastest way to convert from one type to another. + * + * NOTE: Currently we do not use the "cost" field provided with each filter. + * This will be addressed in a future version of this function. For + * now all filters are assumed to be equally costly and we find the + * smallest number of filters to run that satisfies the filter + * requirements. + */ + +mime_filter_t * /* O - Array of filters to run */ +mimeFilter(mime_t *mime, /* I - MIME database */ + mime_type_t *src, /* I - Source file type */ + mime_type_t *dst, /* I - Destination file type */ + int *num_filters) /* O - Number of filters to run */ +{ + int i; /* Looping var */ + int num_temp, /* Number of temporary filters */ + num_mintemp; /* Current minimum */ + mime_filter_t *temp, /* Temporary filter */ + *mintemp, /* Current minimum */ + *mincurrent, /* Current filter for minimum */ + *current, /* Current filter */ + *filters; /* Filters to use */ + + + /* + * Range-check the input... + */ + + if (mime == NULL || src == NULL || dst == NULL || num_filters == NULL) + return (NULL); + + *num_filters = 0; + + /* + * See if there is a filter that can convert the files directly... + */ + + if ((temp = lookup(mime, src, dst)) != NULL) + { + /* + * Got a direct filter! + */ + + if ((filters = (mime_filter_t *)malloc(sizeof(mime_filter_t))) == NULL) + return (NULL); + + memcpy(filters, temp, sizeof(mime_filter_t)); + *num_filters = 1; + return (filters); + } + + /* + * OK, now look for filters from the source type to any other type... + */ + + num_mintemp = 100000; + mintemp = NULL; + + for (i = mime->num_filters, current = mime->filters; i > 0; i --, current ++) + if (current->src == src) + { + /* + * See if we have any filters that can convert from the destination type + * of this filter to the final type... + */ + + if ((temp = mimeFilter(mime, current->dst, dst, &num_temp)) == NULL) + continue; + + /* + * Found a match; see if this one is less costly than the last (if + * any...) + */ + + if (num_temp < num_mintemp) + { + if (mintemp != NULL) + free(mintemp); + + num_mintemp = num_temp; + mintemp = temp; + mincurrent = current; + } + else + free(temp); + } + + if (mintemp != NULL) + { + /* + * Hey, we got a match! Add the current filter to the beginning of the + * filter list... + */ + + filters = (mime_filter_t *)realloc(mintemp, sizeof(mime_filter_t) * + (num_mintemp + 1)); + + if (filters == NULL) + { + *num_filters = 0; + return (NULL); + } + + memmove(filters + 1, filters, num_mintemp * sizeof(mime_filter_t)); + memcpy(filters, mincurrent, sizeof(mime_filter_t)); + + *num_filters = num_mintemp + 1; + + return (filters); + } + + return (NULL); +} + + +/* + * 'compare()' - Compare two filter types... + */ + +static int /* O - Comparison result */ +compare(mime_filter_t *f0, /* I - First filter */ + mime_filter_t *f1) /* I - Second filter */ +{ + int i; /* Result of comparison */ + + + if ((i = strcmp(f0->src->super, f1->src->super)) == 0) + if ((i = strcmp(f0->src->type, f1->src->type)) == 0) + if ((i = strcmp(f0->dst->super, f1->dst->super)) == 0) + i = strcmp(f0->dst->type, f1->dst->type); + + return (i); +} + + +/* + * 'lookup()' - Lookup a filter... + */ + +static mime_filter_t * /* O - Filter for src->dst */ +lookup(mime_t *mime, /* I - MIME database */ + mime_type_t *src, /* I - Source type */ + mime_type_t *dst) /* I - Destination type */ +{ + mime_filter_t key; /* Key record for filter search */ + + + if (mime->num_filters == 0) + return (NULL); + + key.src = src; + key.dst = dst; + + return ((mime_filter_t *)bsearch(&key, mime->filters, mime->num_filters, + sizeof(mime_filter_t), + (int (*)(const void *, const void *))compare)); +} + + +/* + * End of "$Id$". + */ diff --git a/cups/http.c b/cups/http.c new file mode 100644 index 0000000000..b9f47dc131 --- /dev/null +++ b/cups/http.c @@ -0,0 +1,1393 @@ +/* + * "$Id$" + * + * HTTP routines for the Common UNIX Printing System (CUPS) scheduler. + * + * Copyright 1997-1999 by Easy Software Products, all rights reserved. + * + * These statusd instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44145 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * httpInitialize() - Initialize the HTTP interface library and set the + * default HTTP proxy (if any). + * httpClose() - Close an HTTP connection... + * httpConnect() - Connect to a HTTP server. + * httpReconnect() - Reconnect to a HTTP server... + * httpSeparate() - Separate a Universal Resource Identifier into its + * components. + * httpSetField() - Set the value of an HTTP header. + * httpDelete() - Send a DELETE request to the server. + * httpGet() - Send a GET request to the server. + * httpHead() - Send a HEAD request to the server. + * httpOptions() - Send an OPTIONS request to the server. + * httpPost() - Send a POST request to the server. + * httpPut() - Send a PUT request to the server. + * httpTrace() - Send an TRACE request to the server. + * httpFlush() - Flush data from a HTTP connection. + * httpRead() - Read data from a HTTP connection. + * httpWrite() - Write data to a HTTP connection. + * httpGets() - Get a line of text from a HTTP connection. + * httpPrintf() - Print a formatted string to a HTTP connection. + * httpStatus() - Return a short string describing a HTTP status code. + * httpGetDateString() - Get a formatted date/time string from a time value. + * httpGetDateTime() - Get a time value from a formatted date/time string. + * httpUpdate() - Update the current HTTP state for incoming data. + * httpDecode64() - Base64-decode a string. + * httpEncode64() - Base64-encode a string. + * httpGetLength() - Get the amount of data remaining from the + * content-length or transfer-encoding fields. + * http_field() - Return the field index for a field name. + * http_send() - Send a request with all fields and the trailing + * blank line. + */ + +/* + * Include necessary headers... + */ + +#include +#include +#include +#include +#include "string.h" +#include + +#include "http.h" +#include "ipp.h" +#include "debug.h" + +#if !defined(WIN32) && !defined(__EMX__) +# include +#endif /* !WIN32 && !__EMX__ */ + +/* + * Some operating systems have done away with the Fxxxx constants for + * the fcntl() call; this works around that "feature"... + */ + +#ifndef FNONBLK +# define FNONBLK O_NONBLOCK +#endif /* !FNONBLK */ + + +/* + * Local functions... + */ + +static http_field_t http_field(char *name); +static int http_send(http_t *http, http_state_t request, char *uri); + + +/* + * Local globals... + */ + +static char *http_fields[] = + { + "Accept", + "Accept-Charset", + "Accept-Encoding", + "Accept-Language", + "Accept-Ranges", + "Age", + "Allow", + "Alternates", + "Authorization", + "Cache-Control", + "Connection", + "Content-Base", + "Content-Encoding", + "Content-Language", + "Content-Length", + "Content-Location", + "Content-MD5", + "Content-Range", + "Content-Type", + "Content-Version", + "Date", + "Derived-From", + "Etag", + "Expires", + "From", + "Host", + "If-Match", + "If-Modified-Since", + "If-None-Match", + "If-Range", + "If-Unmodified-since", + "Keep-Alive", + "Last-Modified", + "Link", + "Location", + "Max-Forwards", + "Message-Id", + "MIME-Version", + "Pragma", + "Proxy-Authenticate", + "Proxy-Authorization", + "Public", + "Range", + "Referer", + "Retry-After", + "Server", + "Transfer-Encoding", + "Upgrade", + "URI", + "User-Agent", + "Vary", + "Via", + "Warning", + "WWW-Authenticate" + }; +static char *days[7] = + { + "Sun", + "Mon", + "Tue", + "Wed", + "Thu", + "Fri", + "Sat" + }; +static char *months[12] = + { + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec" + }; + + +/* + * 'httpInitialize()' - Initialize the HTTP interface library and set the + * default HTTP proxy (if any). + */ + +void +httpInitialize(void) +{ +#if defined(WIN32) || defined(__EMX__) + WSADATA winsockdata; /* WinSock data */ + static int initialized = 0;/* Has WinSock been initialized? */ + + + if (!initialized) + WSAStartup(MAKEWORD(1,1), &winsockdata); +#elif defined(HAVE_SIGSET) + sigset(SIGPIPE, SIG_IGN); +#elif defined(HAVE_SIGACTION) + struct sigaction action; /* POSIX sigaction data */ + + + /* + * Ignore SIGPIPE signals... + */ + + memset(&action, 0, sizeof(action)); + action.sa_handler = SIG_IGN; + sigaction(SIGPIPE, &action, NULL); +#else + signal(SIGPIPE, SIG_IGN); +#endif /* WIN32 || __EMX__ */ +} + + +/* + * 'httpClose()' - Close an HTTP connection... + */ + +void +httpClose(http_t *http) /* I - Connection to close */ +{ + if (http == NULL) + return; + +#ifdef WIN32 + closesocket(http->fd); +#else + close(http->fd); +#endif /* WIN32 */ + + free(http); +} + + +/* + * 'httpConnect()' - Connect to a HTTP server. + */ + +http_t * /* O - New HTTP connection */ +httpConnect(char *host, /* I - Host to connect to */ + int port) /* I - Port number */ +{ + http_t *http; /* New HTTP connection */ + struct hostent *hostaddr; /* Host address data */ + + + httpInitialize(); + + /* + * Lookup the host... + */ + + if ((hostaddr = gethostbyname(host)) == NULL) + return (NULL); + + /* + * Allocate memory for the structure... + */ + + http = calloc(sizeof(http_t), 1); + if (http == NULL) + return (NULL); + + http->version = HTTP_1_1; + http->blocking = 1; + http->activity = time(NULL); + + /* + * Copy the hostname and port and then "reconnect"... + */ + + strcpy(http->hostname, host); + memset((char *)&(http->hostaddr), 0, sizeof(http->hostaddr)); + memcpy((char *)&(http->hostaddr.sin_addr), hostaddr->h_addr, hostaddr->h_length); + http->hostaddr.sin_family = hostaddr->h_addrtype; +#ifdef WIN32 + http->hostaddr.sin_port = htons((u_short)port); +#else + http->hostaddr.sin_port = htons(port); +#endif /* WIN32 */ + if (httpReconnect(http)) + { + free(http); + return (NULL); + } + else + return (http); +} + + +/* + * 'httpReconnect()' - Reconnect to a HTTP server... + */ + +int /* O - 0 on success, non-zero on failure */ +httpReconnect(http_t *http) /* I - HTTP data */ +{ + int val; /* Socket option value */ + + + /* + * Close any previously open socket... + */ + + if (http->fd) +#ifdef WIN32 + closesocket(http->fd); +#else + close(http->fd); +#endif /* WIN32 */ + + /* + * Create the socket and set options to allow reuse. + */ + + if ((http->fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) + return (-1); + +#ifdef FD_CLOEXEC + fcntl(http->fd, F_SETFD, FD_CLOEXEC); /* Close this socket when starting * + * other processes... */ +#endif /* FD_CLOEXEC */ + + val = 1; + setsockopt(http->fd, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val)); + +#ifdef SO_REUSEPORT + val = 1; + setsockopt(http->fd, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val)); +#endif /* SO_REUSEPORT */ + + /* + * Connect to the server... + */ + + if (connect(http->fd, (struct sockaddr *)&(http->hostaddr), + sizeof(http->hostaddr)) < 0) + { +#ifdef WIN32 + closesocket(http->fd); +#else + close(http->fd); +#endif + + return (-1); + } + + return (0); +} + + +/* + * 'httpSeparate()' - Separate a Universal Resource Identifier into its + * components. + */ + +void +httpSeparate(char *uri, /* I - Universal Resource Identifier */ + char *method, /* O - Method (http, https, etc.) */ + char *username, /* O - Username */ + char *host, /* O - Hostname */ + int *port, /* O - Port number to use */ + char *resource) /* O - Resource/filename */ +{ + char *ptr; /* Pointer into string... */ + + + if (uri == NULL || method == NULL || username == NULL || host == NULL || + port == NULL || resource == NULL) + return; + + /* + * Grab the method portion of the URI... + */ + + ptr = host; + while (*uri != ':' && *uri != '\0') + *ptr++ = *uri++; + + *ptr = '\0'; + if (*uri == ':') + uri ++; + + /* + * If the method contains a period or slash, then it's probably + * hostname/filename... + */ + + if (strchr(host, '.') != NULL || strchr(host, '/') != NULL || *uri == '\0') + { + if ((ptr = strchr(host, '/')) != NULL) + { + strcpy(resource, ptr); + *ptr = '\0'; + } + else + resource[0] = '\0'; + + if (isdigit(*uri)) + { + /* + * OK, we have "hostname:port[/resource]"... + */ + + *port = strtol(uri, &uri, 10); + + if (*uri == '/') + strcpy(resource, uri); + } + else + *port = 0; + + strcpy(method, "http"); + username[0] = '\0'; + return; + } + else + strcpy(method, host); + + /* + * If the method starts with less than 2 slashes then it is a local resource... + */ + + if (strncmp(uri, "//", 2) != 0) + { + strcpy(resource, uri); + username[0] = '\0'; + host[0] = '\0'; + *port = 0; + return; + } + + /* + * Grab the hostname... + */ + + while (*uri == '/') + uri ++; + + ptr = host; + while (*uri != ':' && *uri != '@' && *uri != '/' && *uri != '\0') + *ptr ++ = *uri ++; + + *ptr = '\0'; + + if (*uri == '@') + { + /* + * Got a username... + */ + + strcpy(username, host); + + ptr = host; + while (*uri != ':' && *uri != '/' && *uri != '\0') + *ptr ++ = *uri ++; + + *ptr = '\0'; + } + else + username[0] = '\0'; + + if (*uri == '\0') + { + /* + * Hostname but no port or path... + */ + + *port = 0; + resource[0] = '/'; + resource[1] = '\0'; + return; + } + else if (*uri == ':') + { + /* + * Parse port number... + */ + + *port = 0; + uri ++; + while (isdigit(*uri)) + { + *port = (*port * 10) + *uri - '0'; + uri ++; + } + } + else + { + /* + * Figure out the default port number based on the method... + */ + + if (strcasecmp(method, "http") == 0) + *port = 80; + else if (strcasecmp(method, "https") == 0) + *port = 443; + else if (strcasecmp(method, "ipp") == 0) /* Not registered yet... */ + *port = ippPort(); + else + *port = 0; + } + + /* + * The remaining portion is the resource string... + */ + + strcpy(resource, uri); +} + + +/* + * 'httpSetField()' - Set the value of an HTTP header. + */ + +void +httpSetField(http_t *http, /* I - HTTP data */ + http_field_t field, /* I - Field index */ + char *value) /* I - Value */ +{ + strncpy(http->fields[field], value, HTTP_MAX_VALUE - 1); + http->fields[field][HTTP_MAX_VALUE - 1] = '\0'; +} + + +/* + * 'httpDelete()' - Send a DELETE request to the server. + */ + +int /* O - Status of call (0 = success) */ +httpDelete(http_t *http, /* I - HTTP data */ + char *uri) /* I - URI to delete */ +{ + return (http_send(http, HTTP_DELETE, uri)); +} + + +/* + * 'httpGet()' - Send a GET request to the server. + */ + +int /* O - Status of call (0 = success) */ +httpGet(http_t *http, /* I - HTTP data */ + char *uri) /* I - URI to get */ +{ + return (http_send(http, HTTP_GET, uri)); +} + + +/* + * 'httpHead()' - Send a HEAD request to the server. + */ + +int /* O - Status of call (0 = success) */ +httpHead(http_t *http, /* I - HTTP data */ + char *uri) /* I - URI for head */ +{ + return (http_send(http, HTTP_HEAD, uri)); +} + + +/* + * 'httpOptions()' - Send an OPTIONS request to the server. + */ + +int /* O - Status of call (0 = success) */ +httpOptions(http_t *http, /* I - HTTP data */ + char *uri) /* I - URI for options */ +{ + return (http_send(http, HTTP_OPTIONS, uri)); +} + + +/* + * 'httpPost()' - Send a POST request to the server. + */ + +int /* O - Status of call (0 = success) */ +httpPost(http_t *http, /* I - HTTP data */ + char *uri) /* I - URI for post */ +{ + httpGetLength(http); + + return (http_send(http, HTTP_POST, uri)); +} + + +/* + * 'httpPut()' - Send a PUT request to the server. + */ + +int /* O - Status of call (0 = success) */ +httpPut(http_t *http, /* I - HTTP data */ + char *uri) /* I - URI to put */ +{ + httpGetLength(http); + + return (http_send(http, HTTP_PUT, uri)); +} + + +/* + * 'httpTrace()' - Send an TRACE request to the server. + */ + +int /* O - Status of call (0 = success) */ +httpTrace(http_t *http, /* I - HTTP data */ + char *uri) /* I - URI for trace */ +{ + return (http_send(http, HTTP_TRACE, uri)); +} + + +/* + * 'httpFlush()' - Flush data from a HTTP connection. + */ + +void +httpFlush(http_t *http) /* I - HTTP data */ +{ + char buffer[8192]; /* Junk buffer */ + + + while (httpRead(http, buffer, sizeof(buffer)) > 0); +} + + +/* + * 'httpRead()' - Read data from a HTTP connection. + */ + +int /* O - Number of bytes read */ +httpRead(http_t *http, /* I - HTTP data */ + char *buffer, /* I - Buffer for data */ + int length) /* I - Maximum number of bytes */ +{ + int bytes; /* Bytes read */ + char len[32]; /* Length string */ + + + DEBUG_printf(("httpRead(%08x, %08x, %d)\n", http, buffer, length)); + + if (http == NULL || buffer == NULL) + return (-1); + + http->activity = time(NULL); + + if (length <= 0) + return (0); + + if (http->data_encoding == HTTP_ENCODE_CHUNKED && + http->data_remaining <= 0 && + (http->state == HTTP_GET_SEND || http->state == HTTP_POST_RECV || + http->state == HTTP_POST_SEND || http->state == HTTP_PUT_RECV)) + { + if (httpGets(len, sizeof(len), http) == NULL) + return (0); + + http->data_remaining = strtol(len, NULL, 16); + } + + DEBUG_printf(("httpRead: data_remaining = %d\n", http->data_remaining)); + + if (http->data_remaining == 0) + { + /* + * A zero-length chunk ends a transfer; unless we are reading POST + * data, go idle... + */ + + if (http->state == HTTP_POST_RECV) + http->state ++; + else + http->state = HTTP_WAITING; + + return (0); + } + else if (length > http->data_remaining) + length = http->data_remaining; + + if (http->used > 0) + { + if (length > http->used) + length = http->used; + + bytes = length; + + DEBUG_printf(("httpRead: grabbing %d bytes from input buffer...\n", bytes)); + + memcpy(buffer, http->buffer, length); + http->used -= length; + + if (http->used > 0) + memcpy(http->buffer, http->buffer + length, http->used); + } + else + { + DEBUG_printf(("httpRead: reading %d bytes from socket...\n", length)); + bytes = recv(http->fd, buffer, length, 0); + DEBUG_printf(("httpRead: read %d bytes from socket...\n", bytes)); + } + + if (bytes > 0) + http->data_remaining -= bytes; + + if (http->data_remaining == 0 && http->data_encoding != HTTP_ENCODE_CHUNKED) + { + if (http->state == HTTP_POST_RECV) + http->state ++; + else + http->state = HTTP_WAITING; + } + + return (bytes); +} + + +/* + * 'httpWrite()' - Write data to a HTTP connection. + */ + +int /* O - Number of bytes written */ +httpWrite(http_t *http, /* I - HTTP data */ + char *buffer, /* I - Buffer for data */ + int length) /* I - Number of bytes to write */ +{ + int tbytes, /* Total bytes sent */ + bytes; /* Bytes sent */ + char len[32]; /* Length string */ + + + if (http == NULL || buffer == NULL) + return (-1); + + http->activity = time(NULL); + + if (http->data_encoding == HTTP_ENCODE_CHUNKED && + (http->state == HTTP_GET_SEND || http->state == HTTP_POST_RECV || + http->state == HTTP_POST_SEND || http->state == HTTP_PUT_RECV)) + { + sprintf(len, "%x\r\n", length); + if (send(http->fd, len, strlen(len), 0) < 3) + return (-1); + } + + if (length == 0) + { + /* + * A zero-length chunk ends a transfer; unless we are sending POST + * data, go idle... + */ + + if (http->state == HTTP_POST_RECV) + http->state ++; + else + http->state = HTTP_WAITING; + + return (0); + } + + tbytes = 0; + + while (length > 0) + { + bytes = send(http->fd, buffer, length, 0); + if (bytes < 0) + { + perror("httpWrite"); + DEBUG_puts("httpWrite: error writing data...\n"); + return (-1); + } + + buffer += bytes; + tbytes += bytes; + length -= bytes; + if (http->data_encoding == HTTP_ENCODE_LENGTH) + http->data_remaining -= bytes; + } + + if (http->data_remaining == 0 && http->data_encoding == HTTP_ENCODE_LENGTH) + { + /* + * Finished with the transfer; unless we are sending POST data, go idle... + */ + + if (http->state == HTTP_POST_RECV) + http->state ++; + else + http->state = HTTP_WAITING; + } + + DEBUG_printf(("httpWrite: wrote %d bytes...\n", tbytes)); + + return (tbytes); +} + + +/* + * 'httpGets()' - Get a line of text from a HTTP connection. + */ + +char * /* O - Line or NULL */ +httpGets(char *line, /* I - Line to read into */ + int length, /* I - Max length of buffer */ + http_t *http) /* I - HTTP data */ +{ + char *lineptr, /* Pointer into line */ + *bufptr, /* Pointer into input buffer */ + *bufend; /* Pointer to end of buffer */ + int bytes; /* Number of bytes read */ + + + DEBUG_printf(("httpGets(%08x, %d, %08x)\n", line, length, http)); + + if (http == NULL || line == NULL) + return (NULL); + + /* + * Pre-scan the buffer and see if there is a newline in there... + */ + + do + { + bufptr = http->buffer; + bufend = http->buffer + http->used; + + while (bufptr < bufend) + if (*bufptr == 0x0a) + break; + else + bufptr ++; + + if (bufptr >= bufend) + { + /* + * No newline; see if there is more data to be read... + */ + + if ((bytes = recv(http->fd, bufend, HTTP_MAX_BUFFER - http->used, 0)) < 1) + { + /* + * Nope, can't get a line this time... + */ + + return (NULL); + } + else + { + /* + * Yup, update the amount used and the end pointer... + */ + + http->used += bytes; + bufend += bytes; + } + } + } + while (bufptr >= bufend); + + http->activity = time(NULL); + + /* + * Read a line from the buffer... + */ + + lineptr = line; + bufptr = http->buffer; + bytes = 0; + + while (bufptr < bufend && bytes < length) + { + bytes ++; + + if (*bufptr == 0x0a) + { + bufptr ++; + *lineptr = '\0'; + + http->used -= bytes; + if (http->used > 0) + memcpy(http->buffer, bufptr, http->used); + + return (line); + } + else if (*bufptr == 0x0d) + bufptr ++; + else + *lineptr++ = *bufptr++; + } + + return (NULL); +} + + +/* + * 'httpPrintf()' - Print a formatted string to a HTTP connection. + */ + +int /* O - Number of bytes written */ +httpPrintf(http_t *http, /* I - HTTP data */ + const char *format, /* I - printf-style format string */ + ...) /* I - Additional args as needed */ +{ + int bytes; /* Number of bytes to write */ + char buf[HTTP_MAX_BUFFER]; /* Buffer for formatted string */ + va_list ap; /* Variable argument pointer */ + + + va_start(ap, format); + bytes = vsprintf(buf, format, ap); + va_end(ap); + + DEBUG_printf(("httpPrintf: %s", buf)); + + return (send(http->fd, buf, bytes, 0)); +} + + +/* + * 'httpStatus()' - Return a short string describing a HTTP status code. + */ + +char * /* O - String or NULL */ +httpStatus(http_status_t status) /* I - HTTP status code */ +{ + switch (status) + { + case HTTP_OK : + return ("OK"); + case HTTP_CREATED : + return ("Created"); + case HTTP_ACCEPTED : + return ("Accepted"); + case HTTP_NO_CONTENT : + return ("No Content"); + case HTTP_NOT_MODIFIED : + return ("Not Modified"); + case HTTP_BAD_REQUEST : + return ("Bad Request"); + case HTTP_UNAUTHORIZED : + return ("Unauthorized"); + case HTTP_FORBIDDEN : + return ("Forbidden"); + case HTTP_NOT_FOUND : + return ("Not Found"); + case HTTP_REQUEST_TOO_LARGE : + return ("Request Entity Too Large"); + case HTTP_URI_TOO_LONG : + return ("URI Too Long"); + case HTTP_NOT_IMPLEMENTED : + return ("Not Implemented"); + case HTTP_NOT_SUPPORTED : + return ("Not Supported"); + default : + return ("Unknown"); + } +} + + +/* + * 'httpGetDateString()' - Get a formatted date/time string from a time value. + */ + +char * /* O - Date/time string */ +httpGetDateString(time_t t) /* I - UNIX time */ +{ + struct tm *tdate; + static char datetime[256]; + + + tdate = gmtime(&t); + sprintf(datetime, "%s, %02d %s %d %02d:%02d:%02d GMT", + days[tdate->tm_wday], tdate->tm_mday, months[tdate->tm_mon], + tdate->tm_year + 1900, tdate->tm_hour, tdate->tm_min, tdate->tm_sec); + + return (datetime); +} + + +/* + * 'httpGetDateTime()' - Get a time value from a formatted date/time string. + */ + +time_t /* O - UNIX time */ +httpGetDateTime(char *s) /* I - Date/time string */ +{ + int i; /* Looping var */ + struct tm tdate; /* Time/date structure */ + char mon[16]; /* Abbreviated month name */ + int day, year; /* Day of month and year */ + int hour, min, sec; /* Time */ + + + if (sscanf(s, "%*s%d%s%d%d:%d:%d", &day, mon, &year, &hour, &min, &sec) < 6) + return (0); + + for (i = 0; i < 12; i ++) + if (strcasecmp(mon, months[i]) == 0) + break; + + if (i >= 12) + return (0); + + tdate.tm_mon = i; + tdate.tm_mday = day; + tdate.tm_year = year - 1900; + tdate.tm_hour = hour; + tdate.tm_min = min; + tdate.tm_sec = sec; + tdate.tm_isdst = 0; + + return (mktime(&tdate)); +} + + +/* + * 'httpUpdate()' - Update the current HTTP state for incoming data. + */ + +http_status_t /* O - HTTP status */ +httpUpdate(http_t *http) /* I - HTTP data */ +{ + char line[1024], /* Line from connection... */ + *value; /* Pointer to value on line */ + http_field_t field; /* Field index */ + int major, minor; /* HTTP version numbers */ + http_status_t status; /* Authorization status */ + + + DEBUG_printf(("httpUpdate(%08x)\n", http)); + + /* + * If we haven't issued any commands, then there is nothing to "update"... + */ + + if (http->state == HTTP_WAITING) + return (HTTP_CONTINUE); + + /* + * Grab all of the lines we can from the connection... + */ + + while (httpGets(line, sizeof(line), http) != NULL) + { + DEBUG_puts(line); + + if (line[0] == '\0') + { + /* + * Blank line means the start of the data section (if any). Return + * the result code, too... + */ + + httpGetLength(http); + + switch (http->state) + { + case HTTP_GET : + case HTTP_POST : + case HTTP_POST_RECV : + case HTTP_PUT : + http->state ++; + break; + + default : + http->state = HTTP_WAITING; + break; + } + + return (http->status); + } + else if (strncmp(line, "HTTP/", 5) == 0) + { + /* + * Got the beginning of a response... + */ + + if (sscanf(line, "HTTP/%d.%d%d", &major, &minor, &status) != 3) + return (HTTP_ERROR); + + http->version = (http_version_t)(major * 100 + minor); + http->status = status; + } + else if ((value = strchr(line, ':')) != NULL) + { + /* + * Got a value... + */ + + *value++ = '\0'; + while (isspace(*value)) + value ++; + + /* + * Be tolerants of servers that send unknown attribute fields... + */ + + if ((field = http_field(line)) == HTTP_FIELD_UNKNOWN) + { + DEBUG_printf(("httpUpdate: unknown field %s seen!\n", line)); + continue; + } + + httpSetField(http, field, value); + } + else + return (HTTP_ERROR); + } + + /* + * If we haven't already returned, then there is nothing new... + */ + + return (HTTP_CONTINUE); +} + + +/* + * 'httpDecode64()' - Base64-decode a string. + */ + +char * /* O - Decoded string */ +httpDecode64(char *out, /* I - String to write to */ + char *in) /* I - String to read from */ +{ + int pos, /* Bit position */ + base64; /* Value of this character */ + char *outptr; /* Output pointer */ + + + for (outptr = out, pos = 0; *in != '\0'; in ++) + { + /* + * Decode this character into a number from 0 to 63... + */ + + if (*in >= 'A' && *in <= 'Z') + base64 = *in - 'A'; + else if (*in >= 'a' && *in <= 'z') + base64 = *in - 'a' + 26; + else if (*in >= '0' && *in <= '9') + base64 = *in - '0' + 52; + else if (*in == '+') + base64 = 62; + else if (*in == '/') + base64 = 63; + else if (*in == '=') + break; + else + continue; + + /* + * Store the result in the appropriate chars... + */ + + switch (pos) + { + case 0 : + *outptr = base64 << 2; + pos ++; + break; + case 1 : + *outptr++ |= (base64 >> 4) & 3; + *outptr = (base64 << 4) & 255; + pos ++; + break; + case 2 : + *outptr++ |= (base64 >> 2) & 15; + *outptr = (base64 << 6) & 255; + pos ++; + break; + case 3 : + *outptr++ |= base64; + pos = 0; + break; + } + } + + *outptr = '\0'; + + /* + * Return the decoded string... + */ + + return (out); +} + + +/* + * 'httpEncode64()' - Base64-encode a string. + */ + +char * /* O - Encoded string */ +httpEncode64(char *out, /* I - String to write to */ + char *in) /* I - String to read from */ +{ + char *outptr; /* Output pointer */ + static char base64[] = /* Base64 characters... */ + { + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789" + "+/" + }; + + + for (outptr = out; *in != '\0'; in ++) + { + /* + * Encode the up to 3 characters as 4 Base64 numbers... + */ + + *outptr ++ = base64[in[0] >> 2]; + *outptr ++ = base64[((in[0] << 4) | (in[1] >> 4)) & 63]; + + in ++; + if (*in == '\0') + break; + + *outptr ++ = base64[((in[0] << 2) | (in[1] >> 6)) & 63]; + + in ++; + if (*in == '\0') + break; + + *outptr ++ = base64[in[0] & 63]; + } + + *outptr ++ = '='; + *outptr = '\0'; + + /* + * Return the encoded string... + */ + + return (out); +} + + +/* + * 'httpGetLength()' - Get the amount of data remaining from the + * content-length or transfer-encoding fields. + */ + +int +httpGetLength(http_t *http) /* I - HTTP data */ +{ + if (strcasecmp(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked") == 0) + { + http->data_encoding = HTTP_ENCODE_CHUNKED; + http->data_remaining = 0; + } + else + { + http->data_encoding = HTTP_ENCODE_LENGTH; + + /* + * The following is a hack for HTTP servers that don't send a + * content-length or transfer-encoding field... + * + * If there is no content-length then the connection must close + * after the transfer is complete... + */ + + if (http->fields[HTTP_FIELD_CONTENT_LENGTH][0] == '\0') + http->data_remaining = 2147483647; + else + http->data_remaining = atoi(http->fields[HTTP_FIELD_CONTENT_LENGTH]); + } + + return (http->data_remaining); +} + + +/* + * 'http_field()' - Return the field index for a field name. + */ + +static http_field_t /* O - Field index */ +http_field(char *name) /* I - String name */ +{ + int i; /* Looping var */ + + + for (i = 0; i < HTTP_FIELD_MAX; i ++) + if (strcasecmp(name, http_fields[i]) == 0) + return ((http_field_t)i); + + return (HTTP_FIELD_UNKNOWN); +} + + +/* + * 'http_send()' - Send a request with all fields and the trailing blank line. + */ + +static int /* O - 0 on success, non-zero on error */ +http_send(http_t *http, /* I - HTTP data */ + http_state_t request, /* I - Request code */ + char *uri) /* I - URI */ +{ + int i; /* Looping var */ + char *ptr, /* Pointer in buffer */ + buf[1024]; /* Encoded URI buffer */ + static char *codes[] = /* Request code strings */ + { + NULL, + "OPTIONS", + "GET", + NULL, + "HEAD", + "POST", + NULL, + NULL, + "PUT", + NULL, + "DELETE", + "TRACE", + "CLOSE" + }; + static char *hex = "0123456789ABCDEF"; + /* Hex digits */ + + + if (http == NULL || uri == NULL) + return (-1); + + /* + * Encode the URI as needed... + */ + + for (ptr = buf; *uri != '\0'; uri ++) + if (*uri <= ' ' || *uri >= 127) + { + *ptr ++ = '%'; + *ptr ++ = hex[(*uri >> 4) & 15]; + *ptr ++ = hex[*uri & 15]; + } + else + *ptr ++ = *uri; + + *ptr = '\0'; + + /* + * Send the request header... + */ + + http->state = request; + if (request == HTTP_POST || request == HTTP_PUT) + http->state ++; + + if (httpPrintf(http, "%s %s HTTP/1.1\n", codes[request], buf) < 1) + { + /* + * Might have lost connection; try to reconnect... + */ + + if (httpReconnect(http)) + return (-1); + + /* + * OK, we've reconnected, send the request again... + */ + + if (httpPrintf(http, "%s %s HTTP/%d.%d\n", codes[request], buf, + http->version / 100, http->version % 100) < 1) + return (-1); + } + + for (i = 0; i < HTTP_FIELD_MAX; i ++) + if (http->fields[i][0] != '\0') + { + DEBUG_printf(("%s: %s\n", http_fields[i], http->fields[i])); + + if (httpPrintf(http, "%s: %s\n", http_fields[i], http->fields[i]) < 1) + return (-1); + } + + if (httpPrintf(http, "\n") < 1) + return (-1); + + httpClearFields(http); + + return (0); +} + + +/* + * End of "$Id$". + */ diff --git a/cups/http.h b/cups/http.h new file mode 100644 index 0000000000..06046cc994 --- /dev/null +++ b/cups/http.h @@ -0,0 +1,316 @@ +/* + * "$Id$" + * + * Hyper-Text Transport Protocol definitions for the Common UNIX Printing + * System (CUPS). + * + * Copyright 1997-1999 by Easy Software Products, all rights reserved. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44145 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + */ + +#ifndef _CUPS_HTTP_H_ +# define _CUPS_HTTP_H_ + +/* + * Include necessary headers... + */ + +# include +# include +# if defined(WIN32) || defined(__EMX__) +# include +# else +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# endif /* WIN32 || __EMX__ */ + + +/* + * C++ magic... + */ + +# ifdef __cplusplus +extern "C" { +# endif /* __cplusplus */ + + +/* + * Limits... + */ + +# define HTTP_MAX_URI 1024 /* Max length of URI string */ +# define HTTP_MAX_HOST 256 /* Max length of hostname string */ +# define HTTP_MAX_BUFFER 8192 /* Max length of data buffer */ +# define HTTP_MAX_VALUE 256 /* Max header field value length */ + + +/* + * HTTP state values... + */ + +typedef enum /* States are server-oriented */ +{ + HTTP_WAITING, /* Waiting for command */ + HTTP_OPTIONS, /* OPTIONS command, waiting for blank line */ + HTTP_GET, /* GET command, waiting for blank line */ + HTTP_GET_SEND, /* GET command, sending data */ + HTTP_HEAD, /* HEAD command, waiting for blank line */ + HTTP_POST, /* POST command, waiting for blank line */ + HTTP_POST_RECV, /* POST command, receiving data */ + HTTP_POST_SEND, /* POST command, sending data */ + HTTP_PUT, /* PUT command, waiting for blank line */ + HTTP_PUT_RECV, /* PUT command, receiving data */ + HTTP_DELETE, /* DELETE command, waiting for blank line */ + HTTP_TRACE, /* TRACE command, waiting for blank line */ + HTTP_CLOSE, /* CLOSE command, waiting for blank line */ + HTTP_STATUS /* Command complete, sending status */ +} http_state_t; + + +/* + * HTTP version numbers... + */ + +typedef enum +{ + HTTP_0_9 = 9, /* HTTP/0.9 */ + HTTP_1_0 = 100, /* HTTP/1.0 */ + HTTP_1_1 = 101 /* HTTP/1.1 */ +} http_version_t; + + +/* + * HTTP keep-alive values... + */ + +typedef enum +{ + HTTP_KEEPALIVE_OFF = 0, + HTTP_KEEPALIVE_ON +} http_keepalive_t; + + +/* + * HTTP transfer encoding values... + */ + +typedef enum +{ + HTTP_ENCODE_LENGTH, /* Data is sent with Content-Length */ + HTTP_ENCODE_CHUNKED /* Data is chunked */ +} http_encoding_t; + + +/* + * HTTP status codes... + */ + +typedef enum +{ + HTTP_ERROR = -1, /* An error response from httpXxxx() */ + HTTP_CONTINUE, /* Everything OK, keep going... */ + + HTTP_OK = 200, /* OPTIONS/GET/HEAD/POST/TRACE command was successful */ + HTTP_CREATED, /* PUT command was successful */ + HTTP_ACCEPTED, /* DELETE command was successful */ + HTTP_NOT_AUTHORITATIVE, /* Information isn't authoritative */ + HTTP_NO_CONTENT, /* Successful command, no new data */ + HTTP_RESET_CONTENT, /* Content was reset/recreated */ + HTTP_PARTIAL_CONTENT, /* Only a partial file was recieved/sent */ + + HTTP_MULTIPLE_CHOICES = 300, /* Multiple files match request */ + HTTP_MOVED_PERMANENTLY, /* Document has moved permanently */ + HTTP_MOVED_TEMPORARILY, /* Document has moved temporarily */ + HTTP_SEE_OTHER, /* See this other link... */ + HTTP_NOT_MODIFIED, /* File not modified */ + HTTP_USE_PROXY, /* Must use a proxy to access this URI */ + + HTTP_BAD_REQUEST = 400, /* Bad request */ + HTTP_UNAUTHORIZED, /* Unauthorized to access host */ + HTTP_PAYMENT_REQUIRED, /* Payment required */ + HTTP_FORBIDDEN, /* Forbidden to access this URI */ + HTTP_NOT_FOUND, /* URI was not found */ + HTTP_METHOD_NOT_ALLOWED, /* Method is not allowed */ + HTTP_NOT_ACCEPTABLE, /* Not Acceptable */ + HTTP_PROXY_AUTHENTICATION, /* Proxy Authentication is Required */ + HTTP_REQUEST_TIMEOUT, /* Request timed out */ + HTTP_CONFLICT, /* Request is self-conflicting */ + HTTP_GONE, /* Server has gone away */ + HTTP_LENGTH_REQUIRED, /* A content length or encoding is required */ + HTTP_PRECONDITION, /* Precondition failed */ + HTTP_REQUEST_TOO_LARGE, /* Request entity too large */ + HTTP_URI_TOO_LONG, /* URI too long */ + HTTP_UNSUPPORTED_MEDIATYPE, /* The requested media type is unsupported */ + + HTTP_SERVER_ERROR = 500, /* Internal server error */ + HTTP_NOT_IMPLEMENTED, /* Feature not implemented */ + HTTP_BAD_GATEWAY, /* Bad gateway */ + HTTP_SERVICE_UNAVAILABLE, /* Service is unavailable */ + HTTP_GATEWAY_TIMEOUT, /* Gateway connection timed out */ + HTTP_NOT_SUPPORTED /* HTTP version not supported */ +} http_status_t; + + +/* + * HTTP field names... + */ + +typedef enum +{ + HTTP_FIELD_UNKNOWN = -1, + HTTP_FIELD_ACCEPT = 0, + HTTP_FIELD_ACCEPT_CHARSET, + HTTP_FIELD_ACCEPT_ENCODING, + HTTP_FIELD_ACCEPT_LANGUAGE, + HTTP_FIELD_ACCEPT_RANGES, + HTTP_FIELD_AGE, + HTTP_FIELD_ALLOW, + HTTP_FIELD_ALTERNATES, + HTTP_FIELD_AUTHORIZATION, + HTTP_FIELD_CACHE_CONTROL, + HTTP_FIELD_CONNECTION, + HTTP_FIELD_CONTENT_BASE, + HTTP_FIELD_CONTENT_ENCODING, + HTTP_FIELD_CONTENT_LANGUAGE, + HTTP_FIELD_CONTENT_LENGTH, + HTTP_FIELD_CONTENT_LOCATION, + HTTP_FIELD_CONTENT_MD5, + HTTP_FIELD_CONTENT_RANGE, + HTTP_FIELD_CONTENT_TYPE, + HTTP_FIELD_CONTENT_VERSION, + HTTP_FIELD_DATE, + HTTP_FIELD_DERIVED_FROM, + HTTP_FIELD_ETAG, + HTTP_FIELD_EXPIRES, + HTTP_FIELD_FROM, + HTTP_FIELD_HOST, + HTTP_FIELD_IF_MATCH, + HTTP_FIELD_IF_MODIFIED_SINCE, + HTTP_FIELD_IF_NONE_MATCH, + HTTP_FIELD_IF_RANGE, + HTTP_FIELD_IF_UNMODIFIED_SINCE, + HTTP_FIELD_KEEP_ALIVE, + HTTP_FIELD_LAST_MODIFIED, + HTTP_FIELD_LINK, + HTTP_FIELD_LOCATION, + HTTP_FIELD_MAX_FORWARDS, + HTTP_FIELD_MESSAGE_ID, + HTTP_FIELD_MIME_VERSION, + HTTP_FIELD_PRAGMA, + HTTP_FIELD_PROXY_AUTHENTICATE, + HTTP_FIELD_PROXY_AUTHORIZATION, + HTTP_FIELD_PUBLIC, + HTTP_FIELD_RANGE, + HTTP_FIELD_REFERER, + HTTP_FIELD_RETRY_AFTER, + HTTP_FIELD_SERVER, + HTTP_FIELD_TRANSFER_ENCODING, + HTTP_FIELD_UPGRADE, + HTTP_FIELD_URI, + HTTP_FIELD_USER_AGENT, + HTTP_FIELD_VARY, + HTTP_FIELD_VIA, + HTTP_FIELD_WARNING, + HTTP_FIELD_WWW_AUTHENTICATE, + HTTP_FIELD_MAX +} http_field_t; + + +/* + * HTTP connection structure... + */ + +typedef struct +{ + int fd; /* File descriptor for this socket */ + int blocking; /* To block or not to block */ + time_t activity; /* Time since last read/write */ + http_state_t state; /* State of client */ + http_status_t status; /* Status of last request */ + http_version_t version; /* Protocol version */ + http_keepalive_t keep_alive; /* Keep-alive supported? */ + struct sockaddr_in hostaddr; /* Address of connected host */ + char hostname[HTTP_MAX_HOST], + /* Name of connected host */ + fields[HTTP_FIELD_MAX][HTTP_MAX_VALUE]; + /* Field values */ + char *data; /* Pointer to data buffer */ + http_encoding_t data_encoding; /* Chunked or not */ + int data_remaining; /* Number of bytes left */ + int used; /* Number of bytes used in buffer */ + char buffer[HTTP_MAX_BUFFER]; + /* Buffer for messages */ +} http_t; + + +/* + * Prototypes... + */ + +# define httpBlocking(http,b) (http)->blocking = (b) +# define httpClearFields(http) memset((http)->fields, 0, sizeof((http)->fields)),\ + httpSetField((http), HTTP_FIELD_HOST, (http)->hostname) +extern void httpClose(http_t *http); +extern http_t *httpConnect(char *host, int port); +extern int httpDelete(http_t *http, char *uri); +extern void httpFlush(http_t *http); +extern int httpGet(http_t *http, char *uri); +extern char *httpGets(char *line, int length, http_t *http); +extern char *httpGetDateString(time_t t); +extern time_t httpGetDateTime(char *s); +# define httpGetField(http,field) (http)->fields[field] +extern int httpHead(http_t *http, char *uri); +extern void httpInitialize(void); +extern int httpOptions(http_t *http, char *uri); +extern int httpPost(http_t *http, char *uri); +extern int httpPrintf(http_t *http, const char *format, ...); +extern int httpPut(http_t *http, char *uri); +extern int httpRead(http_t *http, char *buffer, int length); +extern int httpReconnect(http_t *http); +extern void httpSeparate(char *uri, char *method, char *username, + char *host, int *port, char *resource); +extern void httpSetField(http_t *http, http_field_t field, char *value); +extern char *httpStatus(http_status_t status); +extern int httpTrace(http_t *http, char *uri); +extern http_status_t httpUpdate(http_t *http); +extern int httpWrite(http_t *http, char *buffer, int length); +extern char *httpEncode64(char *out, char *in); +extern char *httpDecode64(char *out, char *in); +extern int httpGetLength(http_t *http); + + +/* + * C++ magic... + */ + +# ifdef __cplusplus +} +# endif /* __cplusplus */ +#endif /* !_CUPS_HTTP_H_ */ + +/* + * End of "$Id$". + */ diff --git a/cups/ipp.c b/cups/ipp.c new file mode 100644 index 0000000000..38835dea37 --- /dev/null +++ b/cups/ipp.c @@ -0,0 +1,1458 @@ +/* + * "$Id$" + * + * Internet Printing Protocol support functions for the Common UNIX + * Printing System (CUPS). + * + * Copyright 1997-1999 by Easy Software Products, all rights reserved. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * ippAddBoolean() - Add a boolean attribute to an IPP request. + * ippAddBooleans() - Add an array of boolean values. + * ippAddDate() - Add a date attribute to an IPP request. + * ippAddInteger() - Add a integer attribute to an IPP request. + * ippAddIntegers() - Add an array of integer values. + * ippAddString() - Add a language-encoded string to an IPP request. + * ippAddStrings() - Add language-encoded strings to an IPP request. + * ippAddRange() - Add a range of values to an IPP request. + * ippAddRanges() - Add ranges of values to an IPP request. + * ippAddResolution() - Add a resolution value to an IPP request. + * ippAddResolutions() - Add resolution values to an IPP request. + * ippAddSeparator() - Add a group separator to an IPP request. + * ippDateToTime() - Convert from RFC 1903 Date/Time format to UNIX time + * ippDelete() - Delete an IPP request. + * ippFindAttribute() - Find a named attribute in a request... + * ippLength() - Compute the length of an IPP request. + * ippPort() - Return the default IPP port number. + * ippRead() - Read data for an IPP request. + * ippTimeToDate() - Convert from UNIX time to RFC 1903 format. + * ippWrite() - Write data for an IPP request. + * add_attr() - Add a new attribute to the request. + * ipp_read() - Semi-blocking read on a HTTP connection... + */ + +/* + * Include necessary headers... + */ + +#include +#include +#include + +#include "ipp.h" +#include "debug.h" + + +/* + * Local functions... + */ + +static ipp_attribute_t *add_attr(ipp_t *ipp, int num_values); +static int ipp_read(http_t *http, char *buffer, int length); + + +/* + * 'ippAddBoolean()' - Add a boolean attribute to an IPP request. + */ + +ipp_attribute_t * /* O - New attribute */ +ippAddBoolean(ipp_t *ipp, /* I - IPP request */ + ipp_tag_t group, /* I - IPP group */ + char *name, /* I - Name of attribute */ + char value) /* I - Value of attribute */ +{ + ipp_attribute_t *attr; /* New attribute */ + + + DEBUG_printf(("ippAddBoolean(%08x, %02x, \'%s\', %d)\n", ipp, group, name, value)); + + if (ipp == NULL || name == NULL) + return (NULL); + + if ((attr = add_attr(ipp, 1)) == NULL) + return (NULL); + + attr->name = strdup(name); + attr->group_tag = group; + attr->value_tag = IPP_TAG_BOOLEAN; + attr->values[0].boolean = value; + + return (attr); +} + + +/* + * 'ippAddBooleans()' - Add an array of boolean values. + */ + +ipp_attribute_t * /* O - New attribute */ +ippAddBooleans(ipp_t *ipp, /* I - IPP request */ + ipp_tag_t group, /* I - IPP group */ + char *name, /* I - Name of attribute */ + int num_values, /* I - Number of values */ + char *values) /* I - Values */ +{ + int i; /* Looping var */ + ipp_attribute_t *attr; /* New attribute */ + + + DEBUG_printf(("ippAddBooleans(%08x, %02x, \'%s\', %d, %08x)\n", ipp, + group, name, num_values, values)); + + if (ipp == NULL || name == NULL) + return (NULL); + + if ((attr = add_attr(ipp, num_values)) == NULL) + return (NULL); + + attr->name = strdup(name); + attr->group_tag = group; + attr->value_tag = IPP_TAG_BOOLEAN; + + if (values != NULL) + for (i = 0; i < num_values; i ++) + attr->values[i].boolean = values[i]; + + return (attr); +} + + +/* + * 'ippAddDate()' - Add a date attribute to an IPP request. + */ + +ipp_attribute_t * /* O - New attribute */ +ippAddDate(ipp_t *ipp, /* I - IPP request */ + ipp_tag_t group, /* I - IPP group */ + char *name, /* I - Name of attribute */ + ipp_uchar_t *value) /* I - Value */ +{ + ipp_attribute_t *attr; /* New attribute */ + + + DEBUG_printf(("ippAddDate(%08x, %02x, \'%s\', %08x)\n", ipp, group, name, + value)); + + if (ipp == NULL || name == NULL || value == NULL) + return (NULL); + + if ((attr = add_attr(ipp, 1)) == NULL) + return (NULL); + + attr->name = strdup(name); + attr->group_tag = group; + attr->value_tag = IPP_TAG_DATE; + memcpy(attr->values[0].date, value, 11); + + return (attr); +} + + +/* + * 'ippAddInteger()' - Add a integer attribute to an IPP request. + */ + +ipp_attribute_t * /* O - New attribute */ +ippAddInteger(ipp_t *ipp, /* I - IPP request */ + ipp_tag_t group, /* I - IPP group */ + ipp_tag_t type, /* I - Type of attribute */ + char *name, /* I - Name of attribute */ + int value) /* I - Value of attribute */ +{ + ipp_attribute_t *attr; /* New attribute */ + + + DEBUG_printf(("ippAddInteger(%08x, %d, \'%s\', %d)\n", ipp, group, name, + value)); + + if (ipp == NULL || name == NULL) + return (NULL); + + if ((attr = add_attr(ipp, 1)) == NULL) + return (NULL); + + attr->name = strdup(name); + attr->group_tag = group; + attr->value_tag = type; + attr->values[0].integer = value; + + return (attr); +} + + +/* + * 'ippAddIntegers()' - Add an array of integer values. + */ + +ipp_attribute_t * /* O - New attribute */ +ippAddIntegers(ipp_t *ipp, /* I - IPP request */ + ipp_tag_t group, /* I - IPP group */ + ipp_tag_t type, /* I - Type of attribute */ + char *name, /* I - Name of attribute */ + int num_values, /* I - Number of values */ + int *values) /* I - Values */ +{ + int i; /* Looping var */ + ipp_attribute_t *attr; /* New attribute */ + + + if (ipp == NULL || name == NULL) + return (NULL); + + if ((attr = add_attr(ipp, num_values)) == NULL) + return (NULL); + + attr->name = strdup(name); + attr->group_tag = group; + attr->value_tag = type; + + if (values != NULL) + for (i = 0; i < num_values; i ++) + attr->values[i].integer = values[i]; + + return (attr); +} + + +/* + * 'ippAddString()' - Add a language-encoded string to an IPP request. + */ + +ipp_attribute_t * /* O - New attribute */ +ippAddString(ipp_t *ipp, /* I - IPP request */ + ipp_tag_t group, /* I - IPP group */ + ipp_tag_t type, /* I - Type of attribute */ + char *name, /* I - Name of attribute */ + char *charset, /* I - Character set */ + char *value) /* I - Value */ +{ + ipp_attribute_t *attr; /* New attribute */ + + + if (ipp == NULL || name == NULL) + return (NULL); + + if ((attr = add_attr(ipp, 1)) == NULL) + return (NULL); + + attr->name = strdup(name); + attr->group_tag = group; + attr->value_tag = type; + attr->values[0].string.charset = charset ? strdup(charset) : NULL; + attr->values[0].string.text = strdup(value); + + return (attr); +} + + +/* + * 'ippAddStrings()' - Add language-encoded strings to an IPP request. + */ + +ipp_attribute_t * /* O - New attribute */ +ippAddStrings(ipp_t *ipp, /* I - IPP request */ + ipp_tag_t group, /* I - IPP group */ + ipp_tag_t type, /* I - Type of attribute */ + char *name, /* I - Name of attribute */ + int num_values, /* I - Number of values */ + char *charset, /* I - Character set */ + char **values) /* I - Values */ +{ + int i; /* Looping var */ + ipp_attribute_t *attr; /* New attribute */ + + + if (ipp == NULL || name == NULL) + return (NULL); + + if ((attr = add_attr(ipp, num_values)) == NULL) + return (NULL); + + attr->name = strdup(name); + attr->group_tag = group; + attr->value_tag = type; + + if (values != NULL) + for (i = 0; i < num_values; i ++) + { + if (i == 0) + attr->values[0].string.charset = charset ? strdup(charset) : NULL; + else + attr->values[i].string.charset = attr->values[0].string.charset; + + attr->values[i].string.text = strdup(values[i]); + } + + return (attr); +} + + +/* + * 'ippAddRange()' - Add a range of values to an IPP request. + */ + +ipp_attribute_t * /* O - New attribute */ +ippAddRange(ipp_t *ipp, /* I - IPP request */ + ipp_tag_t group, /* I - IPP group */ + char *name, /* I - Name of attribute */ + int lower, /* I - Lower value */ + int upper) /* I - Upper value */ +{ + ipp_attribute_t *attr; /* New attribute */ + + + if (ipp == NULL || name == NULL) + return (NULL); + + if ((attr = add_attr(ipp, 1)) == NULL) + return (NULL); + + attr->name = strdup(name); + attr->group_tag = group; + attr->value_tag = IPP_TAG_RANGE; + attr->values[0].range.lower = lower; + attr->values[0].range.upper = upper; + + return (attr); +} + + +/* + * 'ippAddRanges()' - Add ranges of values to an IPP request. + */ + +ipp_attribute_t * /* O - New attribute */ +ippAddRanges(ipp_t *ipp, /* I - IPP request */ + ipp_tag_t group, /* I - IPP group */ + char *name, /* I - Name of attribute */ + int num_values, /* I - Number of values */ + int *lower, /* I - Lower values */ + int *upper) /* I - Upper values */ +{ + int i; /* Looping var */ + ipp_attribute_t *attr; /* New attribute */ + + + if (ipp == NULL || name == NULL) + return (NULL); + + if ((attr = add_attr(ipp, num_values)) == NULL) + return (NULL); + + attr->name = strdup(name); + attr->group_tag = group; + attr->value_tag = IPP_TAG_RANGE; + + if (lower != NULL && upper != NULL) + for (i = 0; i < num_values; i ++) + { + attr->values[i].range.lower = lower[i]; + attr->values[i].range.upper = upper[i]; + } + + return (attr); +} + + +/* + * 'ippAddResolution()' - Add a resolution value to an IPP request. + */ + +ipp_attribute_t * /* O - New attribute */ +ippAddResolution(ipp_t *ipp, /* I - IPP request */ + ipp_tag_t group, /* I - IPP group */ + char *name, /* I - Name of attribute */ + ipp_res_t units, /* I - Units for resolution */ + int xres, /* I - X resolution */ + int yres) /* I - Y resolution */ +{ + ipp_attribute_t *attr; /* New attribute */ + + + if (ipp == NULL || name == NULL) + return (NULL); + + if ((attr = add_attr(ipp, 1)) == NULL) + return (NULL); + + attr->name = strdup(name); + attr->group_tag = group; + attr->value_tag = IPP_TAG_RESOLUTION; + attr->values[0].resolution.xres = xres; + attr->values[0].resolution.yres = yres; + attr->values[0].resolution.units = units; + + return (attr); +} + + +/* + * 'ippAddResolutions()' - Add resolution values to an IPP request. + */ + +ipp_attribute_t * /* O - New attribute */ +ippAddResolutions(ipp_t *ipp, /* I - IPP request */ + ipp_tag_t group, /* I - IPP group */ + char *name, /* I - Name of attribute */ + int num_values, /* I - Number of values */ + ipp_res_t units, /* I - Units for resolution */ + int *xres, /* I - X resolutions */ + int *yres) /* I - Y resolutions */ +{ + int i; /* Looping var */ + ipp_attribute_t *attr; /* New attribute */ + + + if (ipp == NULL || name == NULL) + return (NULL); + + if ((attr = add_attr(ipp, num_values)) == NULL) + return (NULL); + + attr->name = strdup(name); + attr->group_tag = group; + attr->value_tag = IPP_TAG_RESOLUTION; + + if (xres != NULL && yres != NULL) + for (i = 0; i < num_values; i ++) + { + attr->values[i].resolution.xres = xres[i]; + attr->values[i].resolution.yres = yres[i]; + attr->values[i].resolution.units = units; + } + + return (attr); +} + + +/* + * 'ippAddSeparator()' - Add a group separator to an IPP request. + */ + +ipp_attribute_t * /* O - New attribute */ +ippAddSeparator(ipp_t *ipp) /* I - IPP request */ +{ + ipp_attribute_t *attr; /* New attribute */ + + + DEBUG_printf(("ippAddSeparator(%08x)\n", ipp)); + + if (ipp == NULL) + return (NULL); + + if ((attr = add_attr(ipp, 0)) == NULL) + return (NULL); + + attr->group_tag = IPP_TAG_ZERO; + attr->value_tag = IPP_TAG_ZERO; + + return (attr); +} + + +/* + * 'ippDateToTime()' - Convert from RFC 1903 Date/Time format to UNIX time + * in seconds. + */ + +time_t /* O - UNIX time value */ +ippDateToTime(ipp_uchar_t *date)/* I - RFC 1903 date info */ +{ + struct tm unixdate; /* UNIX date/time info */ + time_t t; /* Computed time */ + + + memset(&unixdate, 0, sizeof(unixdate)); + + /* + * RFC-1903 date/time format is: + * + * Byte(s) Description + * ------- ----------- + * 0-1 Year (0 to 65535) + * 2 Month (1 to 12) + * 3 Day (1 to 31) + * 4 Hours (0 to 23) + * 5 Minutes (0 to 59) + * 6 Seconds (0 to 60, 60 = "leap second") + * 7 Deciseconds (0 to 9) + * 8 +/- UTC + * 9 UTC hours (0 to 11) + * 10 UTC minutes (0 to 59) + */ + + unixdate.tm_year = ((date[0] << 8) | date[1]) - 1900; + unixdate.tm_mon = date[2] - 1; + unixdate.tm_mday = date[3]; + unixdate.tm_hour = date[4]; + unixdate.tm_min = date[5]; + unixdate.tm_sec = date[6]; + + t = mktime(&unixdate); + + if (date[8] == '-') + t += date[9] * 3600 + date[10] * 60; + else + t -= date[9] * 3600 + date[10] * 60; + + return (t); +} + + +/* + * 'ippDelete()' - Delete an IPP request. + */ + +void +ippDelete(ipp_t *ipp) /* I - IPP request */ +{ + int i; /* Looping var */ + ipp_attribute_t *attr, /* Current attribute */ + *next; /* Next attribute */ + + + if (ipp == NULL) + return; + + for (attr = ipp->attrs; attr != NULL; attr = next) + { + switch (attr->value_tag) + { + case IPP_TAG_TEXT : + case IPP_TAG_NAME : + case IPP_TAG_KEYWORD : + case IPP_TAG_STRING : + case IPP_TAG_URI : + case IPP_TAG_URISCHEME : + case IPP_TAG_CHARSET : + case IPP_TAG_LANGUAGE : + case IPP_TAG_MIMETYPE : + for (i = 0; i < attr->num_values; i ++) + free(attr->values[i].string.text); + break; + + case IPP_TAG_TEXTLANG : + case IPP_TAG_NAMELANG : + for (i = 0; i < attr->num_values; i ++) + { + if (attr->values[i].string.charset) + free(attr->values[i].string.charset); + free(attr->values[i].string.text); + } + break; + } + + next = attr->next; + + if (attr->name != NULL) + free(attr->name); + + free(attr); + } + + free(ipp); +} + + +/* + * 'ippFindAttribute()' - Find a named attribute in a request... + */ + +ipp_attribute_t * /* O - Matching attribute */ +ippFindAttribute(ipp_t *ipp, /* I - IPP request */ + char *name, /* I - Name of attribute */ + ipp_tag_t type) /* I - Type of attribute */ +{ + ipp_attribute_t *attr; /* Current atttribute */ + + + DEBUG_printf(("ippFindAttribute(%08x, \'%s\')\n", ipp, name)); + + if (ipp == NULL || name == NULL) + return (NULL); + + for (attr = ipp->attrs; attr != NULL; attr = attr->next) + { + DEBUG_printf(("ippFindAttribute: attr = %08x, name = \'%s\'\n", attr, + attr->name)); + + if (attr->name != NULL && strcmp(attr->name, name) == 0 && + (attr->value_tag == type || + (attr->value_tag == IPP_TAG_TEXTLANG && type == IPP_TAG_TEXT) || + (attr->value_tag == IPP_TAG_NAMELANG && type == IPP_TAG_NAME))) + return (attr); + } + + return (NULL); +} + + +/* + * 'ippLength()' - Compute the length of an IPP request. + */ + +size_t /* O - Size of IPP request */ +ippLength(ipp_t *ipp) /* I - IPP request */ +{ + int i; /* Looping var */ + int bytes; /* Number of bytes */ + ipp_attribute_t *attr; /* Current attribute */ + ipp_tag_t group; /* Current group */ + + + if (ipp == NULL) + return (0); + + /* + * Start with 8 bytes for the IPP request or status header... + */ + + bytes = 8; + + /* + * Then add the lengths of each attribute... + */ + + group = IPP_TAG_ZERO; + + for (attr = ipp->attrs; attr != NULL; attr = attr->next) + { + if (attr->group_tag != group) + { + group = attr->group_tag; + if (group == IPP_TAG_ZERO) + continue; + + bytes ++; /* Group tag */ + } + + DEBUG_printf(("attr->name = %s, attr->num_values = %d, bytes = %d\n", + attr->name, attr->num_values, bytes)); + + bytes += strlen(attr->name); /* Name */ + bytes += attr->num_values; /* Value tag for each value */ + bytes += 2 * attr->num_values; /* Name lengths */ + bytes += 2 * attr->num_values; /* Value lengths */ + + switch (attr->value_tag) + { + case IPP_TAG_INTEGER : + case IPP_TAG_ENUM : + bytes += 4 * attr->num_values; + break; + + case IPP_TAG_BOOLEAN : + bytes += attr->num_values; + break; + + case IPP_TAG_TEXT : + case IPP_TAG_NAME : + case IPP_TAG_KEYWORD : + case IPP_TAG_STRING : + case IPP_TAG_URI : + case IPP_TAG_URISCHEME : + case IPP_TAG_CHARSET : + case IPP_TAG_LANGUAGE : + case IPP_TAG_MIMETYPE : + for (i = 0; i < attr->num_values; i ++) + bytes += strlen(attr->values[i].string.text); + break; + + case IPP_TAG_DATE : + bytes += 11 * attr->num_values; + break; + + case IPP_TAG_RESOLUTION : + bytes += 9 * attr->num_values; + break; + + case IPP_TAG_RANGE : + bytes += 8 * attr->num_values; + break; + + case IPP_TAG_TEXTLANG : + case IPP_TAG_NAMELANG : + bytes += 2 * attr->num_values;/* Charset length */ + for (i = 0; i < attr->num_values; i ++) + bytes += strlen(attr->values[i].string.charset) + + strlen(attr->values[i].string.text); + break; + } + } + + /* + * Finally, add 1 byte for the "end of attributes" tag and return... + */ + + DEBUG_printf(("bytes = %d\n", bytes + 1)); + + return (bytes + 1); +} + + +ipp_t * /* O - New IPP request */ +ippNew(void) +{ + return ((ipp_t *)calloc(sizeof(ipp_t), 1)); +} + + +/* + * 'ippRead()' - Read data for an IPP request. + */ + +ipp_state_t /* O - Current state */ +ippRead(http_t *http, /* I - HTTP data */ + ipp_t *ipp) /* I - IPP data */ +{ + int n; /* Length of data */ + char buffer[8192]; /* Data buffer */ + ipp_attribute_t *attr; /* Current attribute */ + ipp_tag_t tag; /* Current tag */ + + + DEBUG_printf(("ippRead(%08x, %08x)\n", http, ipp)); + + if (http == NULL || ipp == NULL) + return (IPP_ERROR); + + switch (ipp->state) + { + case IPP_IDLE : + ipp->state ++; /* Avoid common problem... */ + + case IPP_HEADER : + /* + * Get the request header... + */ + + if ((n = ipp_read(http, buffer, 8)) < 8) + { + DEBUG_printf(("ippRead: Unable to read header (%d bytes read)!\n", n)); + return (n == 0 ? IPP_IDLE : IPP_ERROR); + } + + /* + * Verify the major version number... + */ + + if (buffer[0] != 1) + { + DEBUG_printf(("ippRead: version number (%d.%d) is bad.\n", buffer[0], + buffer[1])); + return (IPP_ERROR); + } + + /* + * Then copy the request header over... + */ + + ipp->request.any.version[0] = buffer[0]; + ipp->request.any.version[1] = buffer[1]; + ipp->request.any.op_status = (buffer[2] << 8) | buffer[3]; + ipp->request.any.request_id = (((((buffer[4] << 8) | buffer[5]) << 8) | + buffer[6]) << 8) | buffer[7]; + + ipp->state = IPP_ATTRIBUTE; + ipp->current = NULL; + ipp->curtag = IPP_TAG_ZERO; + + /* + * If blocking is disabled, stop here... + */ + + if (!http->blocking && http->used == 0) + break; + + case IPP_ATTRIBUTE : + while (ipp_read(http, buffer, 1) > 0) + { + /* + * Read this attribute... + */ + + tag = (ipp_tag_t)buffer[0]; + + if (tag == IPP_TAG_END) + { + /* + * No more attributes left... + */ + + DEBUG_puts("ippRead: IPP_TAG_END!"); + + ipp->state = IPP_DATA; + break; + } + else if (tag <= IPP_TAG_UNSUPPORTED) + { + /* + * Group tag... Set the current group and continue... + */ + + if (ipp->curtag == tag) + ippAddSeparator(ipp); + + ipp->curtag = tag; + ipp->current = NULL; + DEBUG_printf(("ippRead: group tag = %x\n", tag)); + continue; + } + + DEBUG_printf(("ippRead: value tag = %x\n", tag)); + + /* + * Get the name... + */ + + if (ipp_read(http, buffer, 2) < 2) + { + DEBUG_puts("ippRead: unable to read name length!"); + return (IPP_ERROR); + } + + n = (buffer[0] << 8) | buffer[1]; + + DEBUG_printf(("ippRead: name length = %d\n", n)); + + if (n == 0) + { + /* + * More values for current attribute... + */ + + if (ipp->current == NULL) + return (IPP_ERROR); + + attr = ipp->current; + + if (attr->num_values >= IPP_MAX_VALUES) + return (IPP_ERROR); + } + else + { + /* + * New attribute; read the name and add it... + */ + + if (ipp_read(http, buffer, n) < n) + { + DEBUG_puts("ippRead: unable to read name!"); + return (IPP_ERROR); + } + + buffer[n] = '\0'; + DEBUG_printf(("ippRead: name = \'%s\'\n", buffer)); + + attr = ipp->current = add_attr(ipp, IPP_MAX_VALUES); + + attr->group_tag = ipp->curtag; + attr->value_tag = tag; + attr->name = strdup(buffer); + attr->num_values = 0; + } + + if (ipp_read(http, buffer, 2) < 2) + { + DEBUG_puts("ippRead: unable to read value length!"); + return (IPP_ERROR); + } + + n = (buffer[0] << 8) | buffer[1]; + DEBUG_printf(("ippRead: value length = %d\n", n)); + + switch (tag) + { + case IPP_TAG_INTEGER : + case IPP_TAG_ENUM : + if (ipp_read(http, buffer, 4) < 4) + return (IPP_ERROR); + + n = (((((buffer[0] << 8) | buffer[1]) << 8) | buffer[2]) << 8) | + buffer[3]; + + attr->values[attr->num_values].integer = n; + break; + case IPP_TAG_BOOLEAN : + if (ipp_read(http, buffer, 1) < 1) + return (IPP_ERROR); + + attr->values[attr->num_values].boolean = buffer[0]; + break; + case IPP_TAG_TEXT : + case IPP_TAG_NAME : + case IPP_TAG_KEYWORD : + case IPP_TAG_STRING : + case IPP_TAG_URI : + case IPP_TAG_URISCHEME : + case IPP_TAG_CHARSET : + case IPP_TAG_LANGUAGE : + case IPP_TAG_MIMETYPE : + if (ipp_read(http, buffer, n) < n) + return (IPP_ERROR); + + buffer[n] = '\0'; + DEBUG_printf(("ippRead: value = \'%s\'\n", buffer)); + + attr->values[attr->num_values].string.text = strdup(buffer); + break; + case IPP_TAG_DATE : + if (ipp_read(http, buffer, 11) < 11) + return (IPP_ERROR); + + memcpy(attr->values[attr->num_values].date, buffer, 11); + break; + case IPP_TAG_RESOLUTION : + if (ipp_read(http, buffer, 9) < 9) + return (IPP_ERROR); + + attr->values[attr->num_values].resolution.xres = + (((((buffer[0] << 8) | buffer[1]) << 8) | buffer[2]) << 8) | + buffer[3]; + attr->values[attr->num_values].resolution.yres = + (((((buffer[4] << 8) | buffer[5]) << 8) | buffer[6]) << 8) | + buffer[7]; + attr->values[attr->num_values].resolution.units = + (ipp_res_t)buffer[8]; + break; + case IPP_TAG_RANGE : + if (ipp_read(http, buffer, 8) < 8) + return (IPP_ERROR); + + attr->values[attr->num_values].range.lower = + (((((buffer[0] << 8) | buffer[1]) << 8) | buffer[2]) << 8) | + buffer[3]; + attr->values[attr->num_values].range.upper = + (((((buffer[4] << 8) | buffer[5]) << 8) | buffer[6]) << 8) | + buffer[7]; + break; + case IPP_TAG_TEXTLANG : + case IPP_TAG_NAMELANG : + if (ipp_read(http, buffer, n) < n) + return (IPP_ERROR); + + buffer[n] = '\0'; + + attr->values[attr->num_values].string.charset = strdup(buffer); + + if (ipp_read(http, buffer, 2) < 2) + return (IPP_ERROR); + + n = (buffer[0] << 8) | buffer[1]; + + if (ipp_read(http, buffer, n) < n) + return (IPP_ERROR); + + buffer[n] = '\0'; + + attr->values[attr->num_values].string.text = strdup(buffer); + break; + } + + attr->num_values ++; + + /* + * If blocking is disabled, stop here... + */ + + if (!http->blocking && http->used == 0) + break; + } + break; + + case IPP_DATA : + break; + } + + return (ipp->state); +} + + +/* + * 'ippTimeToDate()' - Convert from UNIX time to RFC 1903 format. + */ + +ipp_uchar_t * /* O - RFC-1903 date/time data */ +ippTimeToDate(time_t t) /* I - UNIX time value */ +{ + struct tm *unixdate; /* UNIX unixdate/time info */ + static ipp_uchar_t date[11]; /* RFC-1903 date/time data */ + + + /* + * RFC-1903 date/time format is: + * + * Byte(s) Description + * ------- ----------- + * 0-1 Year (0 to 65535) + * 2 Month (1 to 12) + * 3 Day (1 to 31) + * 4 Hours (0 to 23) + * 5 Minutes (0 to 59) + * 6 Seconds (0 to 60, 60 = "leap second") + * 7 Deciseconds (0 to 9) + * 8 +/- UTC + * 9 UTC hours (0 to 11) + * 10 UTC minutes (0 to 59) + */ + + unixdate = gmtime(&t); + unixdate->tm_year += 1900; + + date[0] = unixdate->tm_year >> 8; + date[1] = unixdate->tm_year; + date[2] = unixdate->tm_mon + 1; + date[3] = unixdate->tm_mday; + date[4] = unixdate->tm_hour; + date[5] = unixdate->tm_min; + date[6] = unixdate->tm_sec; + date[7] = 0; + date[8] = '+'; + date[9] = 0; + date[10] = 0; + + return (date); +} + + +/* + * 'ippWrite()' - Write data for an IPP request. + */ + +ipp_state_t /* O - Current state */ +ippWrite(http_t *http, /* I - HTTP data */ + ipp_t *ipp) /* I - IPP data */ +{ + int i; /* Looping var */ + int n; /* Length of data */ + char buffer[8192], /* Data buffer */ + *bufptr; /* Pointer into buffer */ + ipp_attribute_t *attr; /* Current attribute */ + + + if (http == NULL || ipp == NULL) + return (IPP_ERROR); + + switch (ipp->state) + { + case IPP_IDLE : + ipp->state ++; /* Avoid common problem... */ + + case IPP_HEADER : + /* + * Send the request header... + */ + + bufptr = buffer; + + *bufptr++ = 1; + *bufptr++ = 0; + *bufptr++ = ipp->request.any.op_status >> 8; + *bufptr++ = ipp->request.any.op_status; + *bufptr++ = ipp->request.any.request_id >> 24; + *bufptr++ = ipp->request.any.request_id >> 16; + *bufptr++ = ipp->request.any.request_id >> 8; + *bufptr++ = ipp->request.any.request_id; + + if (httpWrite(http, buffer, bufptr - buffer) < 0) + { + DEBUG_puts("ippWrite: Could not write IPP header..."); + return (IPP_ERROR); + } + + ipp->state = IPP_ATTRIBUTE; + ipp->current = ipp->attrs; + ipp->curtag = IPP_TAG_ZERO; + + /* + * If blocking is disabled, stop here... + */ + + if (!http->blocking) + break; + + case IPP_ATTRIBUTE : + while (ipp->current != NULL) + { + /* + * Write this attribute... + */ + + bufptr = buffer; + attr = ipp->current; + + ipp->current = ipp->current->next; + + if (ipp->curtag != attr->group_tag) + { + /* + * Send a group operation tag... + */ + + ipp->curtag = attr->group_tag; + + if (attr->group_tag == IPP_TAG_ZERO) + continue; + + DEBUG_printf(("ippWrite: wrote group tag = %x\n", attr->group_tag)); + *bufptr++ = attr->group_tag; + } + + n = strlen(attr->name); + + DEBUG_printf(("ippWrite: writing value tag = %x\n", attr->value_tag)); + DEBUG_printf(("ippWrite: writing name = %d, \'%s\'\n", n, attr->name)); + + *bufptr++ = attr->value_tag; + *bufptr++ = n >> 8; + *bufptr++ = n; + memcpy(bufptr, attr->name, n); + bufptr += n; + + switch (attr->value_tag) + { + case IPP_TAG_INTEGER : + case IPP_TAG_ENUM : + for (i = 0; i < attr->num_values; i ++) + { + if (i) + { + /* + * Arrays and sets are done by sending additional + * values with a zero-length name... + */ + + *bufptr++ = attr->value_tag; + *bufptr++ = 0; + *bufptr++ = 0; + } + + *bufptr++ = 0; + *bufptr++ = 4; + *bufptr++ = attr->values[i].integer >> 24; + *bufptr++ = attr->values[i].integer >> 16; + *bufptr++ = attr->values[i].integer >> 8; + *bufptr++ = attr->values[i].integer; + } + break; + + case IPP_TAG_BOOLEAN : + for (i = 0; i < attr->num_values; i ++) + { + if (i) + { + /* + * Arrays and sets are done by sending additional + * values with a zero-length name... + */ + + *bufptr++ = attr->value_tag; + *bufptr++ = 0; + *bufptr++ = 0; + } + + *bufptr++ = 0; + *bufptr++ = 1; + *bufptr++ = attr->values[i].boolean; + } + break; + + case IPP_TAG_TEXT : + case IPP_TAG_NAME : + case IPP_TAG_KEYWORD : + case IPP_TAG_STRING : + case IPP_TAG_URI : + case IPP_TAG_URISCHEME : + case IPP_TAG_CHARSET : + case IPP_TAG_LANGUAGE : + case IPP_TAG_MIMETYPE : + for (i = 0; i < attr->num_values; i ++) + { + if (i) + { + /* + * Arrays and sets are done by sending additional + * values with a zero-length name... + */ + + DEBUG_printf(("ippWrite: writing value tag = %x\n", + attr->value_tag)); + DEBUG_printf(("ippWrite: writing name = 0, \'\'\n")); + + *bufptr++ = attr->value_tag; + *bufptr++ = 0; + *bufptr++ = 0; + } + + n = strlen(attr->values[i].string.text); + + DEBUG_printf(("ippWrite: writing string = %d, \'%s\'\n", n, + attr->values[i].string.text)); + + *bufptr++ = n >> 8; + *bufptr++ = n; + memcpy(bufptr, attr->values[i].string.text, n); + bufptr += n; + } + break; + + case IPP_TAG_DATE : + for (i = 0; i < attr->num_values; i ++) + { + if (i) + { + /* + * Arrays and sets are done by sending additional + * values with a zero-length name... + */ + + *bufptr++ = attr->value_tag; + *bufptr++ = 0; + *bufptr++ = 0; + } + + *bufptr++ = 0; + *bufptr++ = 11; + memcpy(bufptr, attr->values[i].date, 11); + bufptr += 11; + } + break; + + case IPP_TAG_RESOLUTION : + for (i = 0; i < attr->num_values; i ++) + { + if (i) + { + /* + * Arrays and sets are done by sending additional + * values with a zero-length name... + */ + + *bufptr++ = attr->value_tag; + *bufptr++ = 0; + *bufptr++ = 0; + } + + *bufptr++ = 0; + *bufptr++ = 9; + *bufptr++ = attr->values[i].resolution.xres >> 24; + *bufptr++ = attr->values[i].resolution.xres >> 16; + *bufptr++ = attr->values[i].resolution.xres >> 8; + *bufptr++ = attr->values[i].resolution.xres; + *bufptr++ = attr->values[i].resolution.yres >> 24; + *bufptr++ = attr->values[i].resolution.yres >> 16; + *bufptr++ = attr->values[i].resolution.yres >> 8; + *bufptr++ = attr->values[i].resolution.yres; + *bufptr++ = attr->values[i].resolution.units; + } + break; + + case IPP_TAG_RANGE : + for (i = 0; i < attr->num_values; i ++) + { + if (i) + { + /* + * Arrays and sets are done by sending additional + * values with a zero-length name... + */ + + *bufptr++ = attr->value_tag; + *bufptr++ = 0; + *bufptr++ = 0; + } + + *bufptr++ = 0; + *bufptr++ = 8; + *bufptr++ = attr->values[i].range.lower >> 24; + *bufptr++ = attr->values[i].range.lower >> 16; + *bufptr++ = attr->values[i].range.lower >> 8; + *bufptr++ = attr->values[i].range.lower; + *bufptr++ = attr->values[i].range.upper >> 24; + *bufptr++ = attr->values[i].range.upper >> 16; + *bufptr++ = attr->values[i].range.upper >> 8; + *bufptr++ = attr->values[i].range.upper; + } + break; + + case IPP_TAG_TEXTLANG : + case IPP_TAG_NAMELANG : + for (i = 0; i < attr->num_values; i ++) + { + if (i) + { + /* + * Arrays and sets are done by sending additional + * values with a zero-length name... + */ + + *bufptr++ = attr->value_tag; + *bufptr++ = 0; + *bufptr++ = 0; + } + + n = strlen(attr->values[i].string.charset); + *bufptr++ = n >> 8; + *bufptr++ = n; + memcpy(bufptr, attr->values[i].string.charset, n); + bufptr += n; + + n = strlen(attr->values[i].string.text); + *bufptr++ = n >> 8; + *bufptr++ = n; + memcpy(bufptr, attr->values[i].string.text, n); + bufptr += n; + } + break; + } + + /* + * Write the data out... + */ + + if (httpWrite(http, buffer, bufptr - buffer) < 0) + { + DEBUG_puts("ippWrite: Could not write IPP attribute..."); + return (IPP_ERROR); + } + + DEBUG_printf(("ippWrite: wrote %d bytes\n", bufptr - buffer)); + + /* + * If blocking is disabled, stop here... + */ + + if (!http->blocking) + break; + } + + if (ipp->current == NULL) + { + /* + * Done with all of the attributes; add the end-of-attributes tag... + */ + + buffer[0] = IPP_TAG_END; + if (httpWrite(http, buffer, 1) < 0) + { + DEBUG_puts("ippWrite: Could not write IPP end-tag..."); + return (IPP_ERROR); + } + + ipp->state = IPP_DATA; + } + break; + + case IPP_DATA : + break; + } + + return (ipp->state); +} + + +/* + * 'ippPort()' - Return the default IPP port number. + */ + +int /* O - Port number */ +ippPort(void) +{ + char *server_port; /* SERVER_PORT environment variable */ + struct servent *port; /* Port number info */ + + + if ((server_port = getenv("SERVER_PORT")) != NULL) + return (atoi(server_port)); + else if ((port = getservbyname("ipp", NULL)) == NULL) + return (IPP_PORT); + else + return (ntohs(port->s_port)); +} + + +/* + * 'add_attr()' - Add a new attribute to the request. + */ + +static ipp_attribute_t * /* O - New attribute */ +add_attr(ipp_t *ipp, /* I - IPP request */ + int num_values) /* I - Number of values */ +{ + ipp_attribute_t *attr; /* New attribute */ + + + DEBUG_printf(("add_attr(%08x, %d)\n", ipp, num_values)); + + if (ipp == NULL || num_values < 0) + return (NULL); + + attr = calloc(sizeof(ipp_attribute_t) + + (num_values - 1) * sizeof(ipp_value_t), 1); + + attr->num_values = num_values; + + if (attr == NULL) + return (NULL); + + if (ipp->last == NULL) + ipp->attrs = attr; + else + ipp->last->next = attr; + + ipp->last = attr; + + return (attr); +} + + +/* + * 'ipp_read()' - Semi-blocking read on a HTTP connection... + */ + +static int /* O - Number of bytes read */ +ipp_read(http_t *http, /* I - Client connection */ + char *buffer,/* O - Buffer for data */ + int length) /* I - Total length */ +{ + int tbytes, /* Total bytes read */ + bytes; /* Bytes read this pass */ + + + /* + * Loop until all bytes are read... + */ + + for (tbytes = 0; tbytes < length; tbytes += bytes, buffer += bytes) + if ((bytes = httpRead(http, buffer, length - tbytes)) <= 0) + break; + + /* + * Return the number of bytes read... + */ + + return (tbytes); +} + + + +/* + * End of "$Id$". + */ diff --git a/cups/ipp.h b/cups/ipp.h new file mode 100644 index 0000000000..62718a2b78 --- /dev/null +++ b/cups/ipp.h @@ -0,0 +1,341 @@ +/* + * "$Id$" + * + * Internet Printing Protocol definitions for the Common UNIX Printing + * System (CUPS). + * + * Copyright 1997-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + */ + +#ifndef _CUPS_IPP_H_ +# define _CUPS_IPP_H_ + +/* + * Include necessary headers... + */ + +# include + + +/* + * C++ magic... + */ + +# ifdef __cplusplus +extern "C" { +# endif /* __cplusplus */ + + +/* + * IPP version string... + */ + +# define IPP_VERSION "\001\000" + +/* + * IPP registered port number... This is the default value - applications + * should use the ippPort() function so that you can customize things in + * /etc/services if needed! + */ + +# define IPP_PORT 631 + +/* + * Common limits... + */ + +# define IPP_MAX_NAME 256 +# define IPP_MAX_VALUES 100 + + +/* + * Types and structures... + */ + +typedef enum /**** Format tags for attribute formats... ****/ +{ + IPP_TAG_ZERO = 0x00, + IPP_TAG_OPERATION, + IPP_TAG_JOB, + IPP_TAG_END, + IPP_TAG_PRINTER, + IPP_TAG_EXTENSION, + IPP_TAG_UNSUPPORTED = 0x10, + IPP_TAG_DEFAULT, + IPP_TAG_UNKNOWN, + IPP_TAG_NOVALUE, + IPP_TAG_INTEGER = 0x21, + IPP_TAG_BOOLEAN, + IPP_TAG_ENUM, + IPP_TAG_STRING = 0x30, + IPP_TAG_DATE, + IPP_TAG_RESOLUTION, + IPP_TAG_RANGE, + IPP_TAG_TEXTLANG, + IPP_TAG_NAMELANG, + IPP_TAG_TEXT = 0x41, + IPP_TAG_NAME, + IPP_TAG_KEYWORD, + IPP_TAG_URI, + IPP_TAG_URISCHEME, + IPP_TAG_CHARSET, + IPP_TAG_LANGUAGE, + IPP_TAG_MIMETYPE +} ipp_tag_t; + +typedef enum /**** Resolution units... ****/ +{ + IPP_RES_PER_INCH = 3, + IPP_RES_PER_CM +} ipp_res_t; + +typedef enum /**** Multiple Document Handling ****/ +{ + IPP_DOC_SINGLE, + IPP_DOC_UNCOLLATED, + IPP_DOC_COLLATED, + IPP_DOC_SEPARATE +} ipp_doc_t; + +typedef enum /**** Finishings... ****/ +{ + IPP_FINISH_NONE = 3, + IPP_FINISH_STAPLE, + IPP_FINISH_PUNCH, + IPP_FINISH_COVER, + IPP_FINISH_BIND +} ipp_finish_t; + +typedef enum /**** Orientation... ****/ +{ + IPP_PORTRAIT = 3, /* No rotation */ + IPP_LANDSCAPE, /* 90 degrees counter-clockwise */ + IPP_REVERSE_LANDSCAPE, /* 90 degrees clockwise */ + IPP_REVERSE_PORTRAIT /* 180 degrees */ +} ipp_orient_t; + +typedef enum /**** Qualities... ****/ +{ + IPP_QUALITY_DRAFT = 3, + IPP_QUALITY_NORMAL, + IPP_QUALITY_HIGH +} ipp_quality_t; + +typedef enum /**** Job States.... */ +{ + IPP_JOB_PENDING = 3, + IPP_JOB_HELD, + IPP_JOB_PROCESSING, + IPP_JOB_STOPPED, + IPP_JOB_CANCELED, + IPP_JOB_ABORTED, + IPP_JOB_COMPLETED +} ipp_jstate_t; + +typedef enum /**** Printer States.... */ +{ + IPP_PRINTER_IDLE = 3, + IPP_PRINTER_PROCESSING, + IPP_PRINTER_STOPPED +} ipp_pstate_t; + +typedef enum /**** IPP states... ****/ +{ + IPP_ERROR = -1, /* An error occurred */ + IPP_IDLE, /* Nothing is happening/request completed */ + IPP_HEADER, /* The request header needs to be sent/received */ + IPP_ATTRIBUTE, /* One or more attributes need to be sent/received */ + IPP_DATA /* IPP request data needs to be sent/received */ +} ipp_state_t; + +typedef enum /**** IPP operations... ****/ +{ + IPP_PRINT_JOB = 0x0002, + IPP_PRINT_URI, + IPP_VALIDATE_JOB, + IPP_CREATE_JOB, + IPP_SEND_DOCUMENT, + IPP_SEND_URI, + IPP_CANCEL_JOB, + IPP_GET_JOB_ATTRIBUTES, + IPP_GET_JOBS, + IPP_GET_PRINTER_ATTRIBUTES, + IPP_HOLD_JOB = 0x000c, + IPP_RELEASE_JOB, + IPP_RESTART_JOB, + IPP_PAUSE_PRINTER = 0x0010, + IPP_RESUME_PRINTER, + IPP_PURGE_JOBS, + IPP_PRIVATE = 0x4000, + CUPS_GET_DEFAULT, + CUPS_GET_PRINTERS, + CUPS_ADD_PRINTER, + CUPS_DELETE_PRINTER, + CUPS_GET_CLASSES, + CUPS_ADD_CLASS, + CUPS_DELETE_CLASS, + CUPS_ACCEPT_JOBS, + CUPS_REJECT_JOBS +} ipp_op_t; + +typedef enum /**** IPP status codes... ****/ +{ + IPP_OK = 0x0000, + IPP_OK_SUBST, + IPP_OK_CONFLICT, + IPP_BAD_REQUEST = 0x0400, + IPP_FORBIDDEN, + IPP_NOT_AUTHENTICATED, + IPP_NOT_AUTHORIZED, + IPP_NOT_POSSIBLE, + IPP_TIMEOUT, + IPP_NOT_FOUND, + IPP_GONE, + IPP_REQUEST_ENTITY, + IPP_REQUEST_VALUE, + IPP_DOCUMENT_FORMAT, + IPP_ATTRIBUTES, + IPP_URI_SCHEME, + IPP_CHARSET, + IPP_CONFLICT, + IPP_INTERNAL_ERROR = 0x0500, + IPP_OPERATION_NOT_SUPPORTED, + IPP_SERVICE_UNAVAILABLE, + IPP_VERSION_NOT_SUPPORTED, + IPP_DEVICE_UNAVAILABLE, + IPP_TEMPORARY_ERROR, + IPP_NOT_ACCEPTING, + IPP_PRINTER_BUSY +} ipp_status_t; + +typedef unsigned char ipp_uchar_t;/**** Unsigned 8-bit integer/character ****/ + +typedef union /**** Request Header ****/ +{ + struct /* Any Header */ + { + ipp_uchar_t version[2]; /* Protocol version number */ + int op_status; /* Operation ID or status code*/ + int request_id; /* Request ID */ + } any; + + struct /* Operation Header */ + { + ipp_uchar_t version[2]; /* Protocol version number */ + ipp_op_t operation_id; /* Operation ID */ + int request_id; /* Request ID */ + } op; + + struct /* Status Header */ + { + ipp_uchar_t version[2]; /* Protocol version number */ + ipp_status_t status_code; /* Status code */ + int request_id; /* Request ID */ + } status; +} ipp_request_t; + + +typedef union /**** Attribute Value ****/ +{ + int integer; /* Integer/enumerated value */ + + char boolean; /* Boolean value */ + + ipp_uchar_t date[11]; /* Date/time value */ + + struct + { + int xres, /* Horizontal resolution */ + yres; /* Vertical resolution */ + ipp_res_t units; /* Resolution units */ + } resolution; /* Resolution value */ + + struct + { + int lower, /* Lower value */ + upper; /* Upper value */ + } range; /* Range of integers value */ + + struct + { + char *charset; /* Character set */ + char *text; /* String */ + } string; /* String with language value */ +} ipp_value_t; + +typedef struct ipp_attribute_s /**** Attribute ****/ +{ + struct ipp_attribute_s *next; + /* Next atrtribute in list */ + ipp_tag_t group_tag, /* Job/Printer/Operation group tag */ + value_tag; /* What type of value is it? */ + char *name; /* Name of attribute */ + int num_values; /* Number of values */ + ipp_value_t values[1]; /* Values */ +} ipp_attribute_t; + +typedef struct /**** Request State ****/ +{ + ipp_state_t state; /* State of request */ + ipp_request_t request; /* Request header */ + ipp_attribute_t *attrs, /* Attributes */ + *last, /* Last attribute in list */ + *current; /* Current attribute (for read/write) */ + ipp_tag_t curtag; /* Current attribute group tag */ +} ipp_t; + + +/* + * Prototypes... + */ + +extern time_t ippDateToTime(ipp_uchar_t *date); +extern ipp_attribute_t *ippAddBoolean(ipp_t *ipp, ipp_tag_t group, char *name, char value); +extern ipp_attribute_t *ippAddBooleans(ipp_t *ipp, ipp_tag_t group, char *name, int num_values, char *values); +extern ipp_attribute_t *ippAddDate(ipp_t *ipp, ipp_tag_t group, char *name, ipp_uchar_t *value); +extern ipp_attribute_t *ippAddInteger(ipp_t *ipp, ipp_tag_t group, ipp_tag_t type, char *name, int value); +extern ipp_attribute_t *ippAddIntegers(ipp_t *ipp, ipp_tag_t group, ipp_tag_t type, char *name, int num_values, int *values); +extern ipp_attribute_t *ippAddRange(ipp_t *ipp, ipp_tag_t group, char *name, int lower, int upper); +extern ipp_attribute_t *ippAddRanges(ipp_t *ipp, ipp_tag_t group, char *name, int num_values, int *lower, int *upper); +extern ipp_attribute_t *ippAddResolution(ipp_t *ipp, ipp_tag_t group, char *name, ipp_res_t units, int xres, int yres); +extern ipp_attribute_t *ippAddResolutions(ipp_t *ipp, ipp_tag_t group, char *name, int num_values, ipp_res_t units, int *xres, int *yres); +extern ipp_attribute_t *ippAddSeparator(ipp_t *ipp); +extern ipp_attribute_t *ippAddString(ipp_t *ipp, ipp_tag_t group, ipp_tag_t type, char *name, char *charset, char *value); +extern ipp_attribute_t *ippAddStrings(ipp_t *ipp, ipp_tag_t group, ipp_tag_t type, char *name, int num_values, char *charset, char **values); +extern void ippDelete(ipp_t *ipp); +extern ipp_attribute_t *ippFindAttribute(ipp_t *ipp, char *name, ipp_tag_t type); +extern size_t ippLength(ipp_t *ipp); +extern ipp_t *ippNew(void); +extern ipp_state_t ippRead(http_t *http, ipp_t *ipp); +extern ipp_uchar_t *ippTimeToDate(time_t t); +extern ipp_state_t ippWrite(http_t *http, ipp_t *ipp); +extern int ippPort(void); + +/* + * C++ magic... + */ + +# ifdef __cplusplus +} +# endif /* __cplusplus */ +#endif /* !_CUPS_IPP_H_ */ + +/* + * End of "$Id$". + */ diff --git a/cups/language.c b/cups/language.c new file mode 100644 index 0000000000..ba272930f8 --- /dev/null +++ b/cups/language.c @@ -0,0 +1,370 @@ +/* + * "$Id$" + * + * I18N/language support for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44145 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * cupsLangEncoding() - Return the character encoding (us-ascii, etc.) + * for the given language. + * cupsLangFlush() - Flush all language data out of the cache. + * cupsLangFree() - Free language data. + * cupsLangGet() - Get a language. + */ + +/* + * Include necessary headers... + */ + +#include +#include +#include +#include "string.h" +#include "language.h" + + +/* + * Local globals... + */ + +static cups_lang_t *lang_cache = NULL; /* Language string cache */ +static char *lang_blank = ""; /* Blank constant string */ +static char *lang_encodings[] = /* Encoding strings */ + { + "us-ascii", + "iso8859-1", + "iso8859-2", + "iso8859-3", + "iso8859-4", + "iso8859-5", + "iso8859-6", + "iso8859-7", + "iso8859-8", + "iso8859-9", + "iso8859-10", + "utf8" + }; +static char *lang_default[] = /* Default POSIX locale */ + { +#include "cups_C.h" + NULL + }; + + +/* + * 'cupsLangEncoding()' - Return the character encoding (us-ascii, etc.) + * for the given language. + */ + +char * /* O - Character encoding */ +cupsLangEncoding(cups_lang_t *lang) /* I - Language data */ +{ + if (lang == NULL) + return (lang_encodings[0]); + else + return (lang_encodings[lang->encoding]); +} + + +/* + * 'cupsLangFlush()' - Flush all language data out of the cache. + */ + +void +cupsLangFlush(void) +{ + int i; /* Looping var */ + cups_lang_t *lang, /* Current language */ + *next; /* Next language */ + + + for (lang = lang_cache; lang != NULL; lang = next) + { + for (i = 0; i < CUPS_MSG_MAX; i ++) + if (lang->messages[i] != NULL && lang->messages[i] != lang_blank) + free(lang->messages[i]); + + next = lang->next; + free(lang); + } +} + + +/* + * 'cupsLangFree()' - Free language data. + * + * This does not actually free anything; use cupsLangFlush() for that. + */ + +void +cupsLangFree(cups_lang_t *lang) /* I - Language to free */ +{ + if (lang != NULL && lang->used > 0) + lang->used --; +} + + +/* + * 'cupsLangGet()' - Get a language. + */ + +cups_lang_t * /* O - Language data */ +cupsLangGet(char *language) /* I - Language or locale */ +{ + int i, count; /* Looping vars */ + char real[16], /* Real language name */ + filename[1024], /* Filename for language locale file */ + *localedir; /* Directory for locale files */ + FILE *fp; /* Language locale file pointer */ + char line[1024]; /* Line from file */ + cups_msg_t msg; /* Message number */ + char *text; /* Message text */ + cups_lang_t *lang; /* Current language... */ + + + /* + * Convert the language string passed in to a locale string. "C" is the + * standard POSIX locale and is copied unchanged. Otherwise the + * language string is converted from ll-cc (language-country) to ll_CC + * to match the file naming convention used by all POSIX-compliant + * operating systems. + */ + + if (language == NULL || language[0] == '\0') + language = "C"; + + if (strlen(language) < 2) + strcpy(real, "C"); + else + { + real[0] = tolower(language[0]); + real[1] = tolower(language[1]); + + if (language[2] == '_' || language[2] == '-') + { + real[2] = '_'; + real[3] = toupper(language[3]); + real[4] = toupper(language[4]); + real[5] = '\0'; + language[5] = '\0'; + } + else + { + language[2] = '\0'; + real[2] = '\0'; + } + } + + /* + * Next try to open a locale file; we will try the country-localized file + * first, and then look for generic language file. If all else fails we + * will use the POSIX locale. + */ + + if ((localedir = getenv("LOCALEDIR")) == NULL) + localedir = CUPS_LOCALEDIR; + + sprintf(filename, "%s/%s/cups_%s", localedir, real, real); + + if ((fp = fopen(filename, "r")) == NULL) + if (strlen(real) > 2) + { + /* + * Nope, see if we can open a generic language file... + */ + + real[2] = '\0'; + sprintf(filename, "%s/%s/cups_%s", localedir, real, real); + fp = fopen(filename, "r"); + } + + /* + * Then see if we already have this language loaded... + */ + + for (lang = lang_cache; lang != NULL; lang = lang->next) + if (strcmp(lang->language, language) == 0) + { + lang->used ++; + + if (fp != NULL) + fclose(fp); + + return (lang); + } + + /* + * OK, we have an open messages file; the first line will contain the + * language encoding (us-ascii, iso-8859-1, etc.), and the rest will + * be messages consisting of: + * + * #### SP message text + * + * or: + * + * message text + * + * If the line starts with a number, then message processing picks up + * where the number indicates. Otherwise the last message number is + * incremented. + * + * All leading whitespace is deleted. + */ + + if (fp == NULL) + strcpy(line, lang_default[0]); + else if (fgets(line, sizeof(line), fp) == NULL) + { + /* + * Can't read encoding! + */ + + fclose(fp); + return (NULL); + } + + i = strlen(line) - 1; + if (line[i] == '\n') + line[i] = '\0'; /* Strip LF */ + + /* + * See if there is a free language available; if so, use that + * record... + */ + + for (lang = lang_cache; lang != NULL; lang = lang->next) + if (lang->used == 0) + break; + + if (lang == NULL) + { + /* + * Allocate memory for the language and add it to the cache. + */ + + if ((lang = calloc(sizeof(cups_lang_t), 1)) == NULL) + { + fclose(fp); + return (NULL); + } + + lang->next = lang_cache; + lang_cache = lang; + } + + + /* + * Free all old strings as needed... + */ + + for (i = 0; i < CUPS_MSG_MAX; i ++) + { + if (lang->messages[i] != NULL && lang->messages[i] != lang_blank) + free(lang->messages[i]); + + lang->messages[i] = lang_blank; + } + + /* + * Then assign the language and encoding fields... + */ + + lang->used ++; + strcpy(lang->language, language); + + for (i = 0; i < (sizeof(lang_encodings) / sizeof(lang_encodings[0])); i ++) + if (strcmp(lang_encodings[i], line) == 0) + { + lang->encoding = (cups_encoding_t)i; + break; + } + + /* + * Read the strings from the file... + */ + + msg = (cups_msg_t)-1; + count = 1; + + for (;;) + { + /* + * Read a line from memory or from a file... + */ + + if (fp == NULL) + { + if (lang_default[count] == NULL) + break; + + strcpy(line, lang_default[count]); + } + else if (fgets(line, sizeof(line), fp) == NULL) + break; + + count ++; + + /* + * Ignore blank lines... + */ + + i = strlen(line) - 1; + if (line[i] == '\n') + line[i] = '\0'; /* Strip LF */ + + if (line[0] == '\0') + continue; + + /* + * Grab the message number and text... + */ + + if (isdigit(line[0])) + msg = (cups_msg_t)atoi(line); + else + msg ++; + + if (msg < 0 || msg >= CUPS_MSG_MAX) + continue; + + text = line; + while (isdigit(*text)) + text ++; + while (isspace(*text)) + text ++; + + lang->messages[msg] = strdup(text); + } + + /* + * Close the file and return... + */ + + if (fp != NULL) + fclose(fp); + + return (lang); +} + + +/* + * End of "$Id$". + */ diff --git a/cups/language.h b/cups/language.h new file mode 100644 index 0000000000..93263c9c51 --- /dev/null +++ b/cups/language.h @@ -0,0 +1,188 @@ +/* + * "$Id$" + * + * Multi-language support for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44145 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + */ + +#ifndef _CUPS_LANGUAGE_H_ +# define _CUPS_LANGUAGE_H_ + +/* + * Include necessary headers... + */ + +# include + +# ifdef __cplusplus +extern "C" { +# endif /* __cplusplus */ + +/* + * Messages... + */ + +typedef enum /**** Message Indices ****/ +{ + CUPS_MSG_OK, + CUPS_MSG_CANCEL, + CUPS_MSG_HELP, + CUPS_MSG_QUIT, + CUPS_MSG_CLOSE, + CUPS_MSG_YES, + CUPS_MSG_NO, + CUPS_MSG_AUTO, + CUPS_MSG_ON, + CUPS_MSG_OFF, + CUPS_MSG_SAVE, + CUPS_MSG_DISCARD, + CUPS_MSG_DEFAULT, + CUPS_MSG_USER_DEFINED, + CUPS_MSG_OPTIONS, + CUPS_MSG_MORE_INFO, + CUPS_MSG_BLACK, + CUPS_MSG_COLOR, + CUPS_MSG_CYAN, + CUPS_MSG_MAGENTA, + CUPS_MSG_YELLOW, + CUPS_MSG_COPYRIGHT, + CUPS_MSG_ALL_RIGHTS_RESERVED, + CUPS_MSG_GENERAL, + CUPS_MSG_PRINTER, + CUPS_MSG_POSTSCRIPT, + CUPS_MSG_IMAGE, + CUPS_MSG_TEXT, + CUPS_MSG_HPGL, + CUPS_MSG_ADVANCED, + CUPS_MSG_PRINT_BANNER_PAGE, + CUPS_MSG_VERBOSE_LOGGING, + CUPS_MSG_PRINT_PAGES, + CUPS_MSG_DOCUMENT, + CUPS_MSG_ENTIRE_DOCUMENT, + CUPS_MSG_PAGE_RANGE, + CUPS_MSG_REVERSE_ORDER, + CUPS_MSG_PAGE_FORMAT, + CUPS_MSG_1_UP, + CUPS_MSG_2_UP, + CUPS_MSG_4_UP, + CUPS_MSG_IMAGE_SCALING, + CUPS_MSG_USE_NATURAL_IMAGE_SIZE, + CUPS_MSG_ZOOM_BY_PERCENT, + CUPS_MSG_ZOOM_BY_PPI, + CUPS_MSG_MIRROR_IMAGE, + CUPS_MSG_ROTATE_IMAGE, + CUPS_MSG_BEST_FIT, + CUPS_MSG_COLOR_SATURATION, + CUPS_MSG_COLOR_HUE, + CUPS_MSG_NUMBER_OF_COLUMNS, + CUPS_MSG_MARGINS, + CUPS_MSG_WRAP_TEXT, + CUPS_MSG_FIT_TO_PAGE, + CUPS_MSG_SHADING, + CUPS_MSG_DEFAULT_PEN_WIDTH, + CUPS_MSG_GAMMA_CORRECTION, + CUPS_MSG_BRIGHTNESS, + CUPS_MSG_COLOR_PROFILE, + CUPS_MSG_ADD_PRINTER, + CUPS_MSG_DELETE_PRINTER, + CUPS_MSG_MODIFY_PRINTER, + CUPS_MSG_PRINTER_URI, + CUPS_MSG_PRINTER_NAME, + CUPS_MSG_PRINTER_LOCATION, + CUPS_MSG_PRINTER_INFO, + CUPS_MSG_PRINTER_MAKE_AND_MODEL, + CUPS_MSG_DEVICE_URI, + CUPS_MSG_FORMATTING_PAGE, + CUPS_MSG_PRINTING_PAGE, + CUPS_MSG_INITIALIZING_PRINTER, + CUPS_MSG_PRINTER_STATE, + CUPS_MSG_ACCEPTING_JOBS, + CUPS_MSG_NOT_ACCEPTING_JOBS, + CUPS_MSG_PRINT_JOBS, + CUPS_MSG_CLASS, + CUPS_MSG_LOCAL, + CUPS_MSG_REMOTE, + CUPS_MSG_DUPLEXING, + CUPS_MSG_STAPLING, + CUPS_MSG_FAST_COPIES, + CUPS_MSG_COLLATED_COPIES, + CUPS_MSG_PUNCHING, + CUPS_MSG_COVERING, + CUPS_MSG_BINDING, + CUPS_MSG_SORTING, + CUPS_MSG_SMALL, + CUPS_MSG_MEDIUM, + CUPS_MSG_LARGE, + CUPS_MSG_VARIABLE, + CUPS_MSG_IDLE, + CUPS_MSG_PROCESSING, + CUPS_MSG_STOPPED, + CUPS_MSG_HTTP_BASE = 200, + CUPS_MSG_HTTP_END = 505, + CUPS_MSG_MAX +} cups_msg_t; + +typedef enum /**** Language Encodings ****/ +{ + CUPS_US_ASCII, + CUPS_ISO8859_1, + CUPS_ISO8859_2, + CUPS_ISO8859_3, + CUPS_ISO8859_4, + CUPS_ISO8859_5, + CUPS_ISO8859_6, + CUPS_ISO8859_7, + CUPS_ISO8859_8, + CUPS_ISO8859_9, + CUPS_ISO8859_10, + CUPS_UTF8 +} cups_encoding_t; + +typedef struct cups_lang_str /**** Language Cache Structure ****/ +{ + struct cups_lang_str *next; /* Next language in cache */ + int used; /* Number of times this entry has been used. */ + cups_encoding_t encoding; /* Text encoding */ + char language[16]; /* Language/locale name */ + char *messages[CUPS_MSG_MAX]; + /* Message array */ +} cups_lang_t; + + +/* + * Prototypes... + */ + +# define cupsLangDefault() cupsLangGet(setlocale(LC_ALL, 0)) +extern char *cupsLangEncoding(cups_lang_t *lang); +extern void cupsLangFlush(void); +extern void cupsLangFree(cups_lang_t *lang); +extern cups_lang_t *cupsLangGet(char *language); +# define cupsLangString(lang,msg) (lang)->messages[(msg)] + +# ifdef __cplusplus +} +# endif /* __cplusplus */ + +#endif /* !_CUPS_LANGUAGE_H_ */ + +/* + * End of "$Id$". + */ diff --git a/cups/mark.c b/cups/mark.c new file mode 100644 index 0000000000..261e2bbda5 --- /dev/null +++ b/cups/mark.c @@ -0,0 +1,418 @@ +/* + * "$Id$" + * + * Option marking routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-1999 by Easy Software Products, all rights reserved. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * PostScript is a trademark of Adobe Systems, Inc. + * + * Contents: + * + * ppdConflicts() - Check to see if there are any conflicts. + * ppdFindChoice() - Return a pointer to an option choice. + * ppdFindMarkedChoice() - Return the marked choice for the specified option. + * ppdFindOption() - Return a pointer to the specified option. + * ppdIsMarked() - Check to see if an option is marked... + * ppdMarkDefaults() - Mark all default options in the PPD file. + * ppdMarkOption() - Mark an option in a PPD file. + * ppd_defaults() - Set the defaults for this group and all sub-groups. + * ppd_default() - Set the default choice for an option. + */ + +/* + * Include necessary headers... + */ + +#include "ppd.h" +#include "string.h" + + +/* + * Local functions... + */ + +static void ppd_defaults(ppd_group_t *g); +static void ppd_default(ppd_option_t *o); + + +/* + * 'ppdConflicts()' - Check to see if there are any conflicts. + */ + +int /* O - Number of conflicts found */ +ppdConflicts(ppd_file_t *ppd) /* I - PPD to check */ +{ + int i, j, /* Looping variables */ + conflicts; /* Number of conflicts */ + ppd_const_t *c; /* Current constraint */ + ppd_option_t *o1, *o2; /* Options */ + ppd_choice_t *c1, *c2; /* Choices */ + + + if (ppd == NULL) + return (0); + + conflicts = 0; + + /* + * Loop through all of the UI constraints and flag any options + * that conflict... + */ + + for (i = ppd->num_consts, c = ppd->consts; i > 0; i --, c ++) + { + /* + * Grab pointers to the first option... + */ + + o1 = ppdFindOption(ppd, c->option1); + + if (o1 == NULL) + continue; + else if (c->choice1[0] != '\0') + { + /* + * This constraint maps to a specific choice. + */ + + c1 = ppdFindChoice(o1, c->choice1); + } + else + { + /* + * This constraint applies to any choice for this option. + */ + + for (j = o1->num_choices, c1 = o1->choices; j > 0; j --, c1 ++) + if (c1->marked) + break; + + if (j == 0) + c1 = NULL; + } + + /* + * Grab pointers to the second option... + */ + + o2 = ppdFindOption(ppd, c->option2); + + if (o2 == NULL) + continue; + else if (c->choice2[0] != '\0') + { + /* + * This constraint maps to a specific choice. + */ + + c2 = ppdFindChoice(o2, c->choice2); + } + else + { + /* + * This constraint applies to any choice for this option. + */ + + for (j = o2->num_choices, c2 = o2->choices; j > 0; j --, c2 ++) + if (c2->marked) + break; + + if (j == 0) + c2 = NULL; + } + + /* + * If both options are marked then there is a conflict... + */ + + if (c1 != NULL && c1->marked && + c2 != NULL && c2->marked) + { + conflicts ++; + o1->conflicted = 1; + o2->conflicted = 1; + } + else + { + o1->conflicted = 0; + o2->conflicted = 0; + } + } + + /* + * Return the number of conflicts found... + */ + + return (conflicts); +} + + +/* + * 'ppdFindChoice()' - Return a pointer to an option choice. + */ + +ppd_choice_t * /* O - Choice pointer or NULL */ +ppdFindChoice(ppd_option_t *o, /* I - Pointer to option */ + char *choice) /* I - Name of choice */ +{ + int i; /* Looping var */ + ppd_choice_t *c; /* Current choice */ + + + if (o == NULL || choice == NULL) + return (NULL); + + for (i = o->num_choices, c = o->choices; i > 0; i --, c ++) + if (strcmp(c->choice, choice) == 0) + return (c); + + return (NULL); +} + + +/* + * 'ppdFindMarkedChoice()' - Return the marked choice for the specified option. + */ + +ppd_choice_t * /* O - Pointer to choice or NULL */ +ppdFindMarkedChoice(ppd_file_t *ppd, /* I - PPD file */ + char *option) /* I - Keyword/option name */ +{ + int i; /* Looping var */ + ppd_option_t *o; /* Pointer to option */ + ppd_choice_t *c; /* Pointer to choice */ + + + if ((o = ppdFindOption(ppd, option)) == NULL) + return (NULL); + + for (i = o->num_choices, c = o->choices; i > 0; i --, c ++) + if (c->marked) + return (c); + + return (NULL); +} + + +/* + * 'ppdFindOption()' - Return a pointer to the specified option. + */ + +ppd_option_t * /* O - Pointer to option or NULL */ +ppdFindOption(ppd_file_t *ppd, /* I - PPD file data */ + char *option) /* I - Option/Keyword name */ +{ + int i, j, k; /* Looping vars */ + ppd_option_t *o; /* Pointer to option */ + ppd_group_t *g, /* Pointer to group */ + *sg; /* Pointer to subgroup */ + + + if (ppd == NULL || option == NULL) + return (NULL); + + for (i = ppd->num_groups, g = ppd->groups; i > 0; i --, g ++) + { + for (j = g->num_options, o = g->options; j > 0; j --, o ++) + if (strcmp(o->keyword, option) == 0) + return (o); + + for (j = g->num_subgroups, sg = g->subgroups; j > 0; j --, sg ++) + for (k = sg->num_options, o = sg->options; k > 0; k --, o ++) + if (strcmp(o->keyword, option) == 0) + return (o); + } + + return (NULL); +} + + +/* + * 'ppdIsMarked()' - Check to see if an option is marked... + */ + +int /* O - Non-zero if option is marked */ +ppdIsMarked(ppd_file_t *ppd, /* I - PPD file data */ + char *option, /* I - Option/Keyword name */ + char *choice) /* I - Choice name */ +{ + ppd_option_t *o; /* Option pointer */ + ppd_choice_t *c; /* Choice pointer */ + + + if (ppd == NULL) + return (0); + + if ((o = ppdFindOption(ppd, option)) == NULL) + return (0); + + if ((c = ppdFindChoice(o, choice)) == NULL) + return (0); + + return (c->marked); +} + + +/* + * 'ppdMarkDefaults()' - Mark all default options in the PPD file. + */ + +void +ppdMarkDefaults(ppd_file_t *ppd)/* I - PPD file record */ +{ + int i; /* Looping variables */ + ppd_group_t *g; /* Current group */ + ppd_option_t *o; /* PageSize option */ + + + if (ppd == NULL) + return; + + for (i = ppd->num_groups, g = ppd->groups; i > 0; i --, g ++) + ppd_defaults(g); + + o = ppdFindOption(ppd, "PageSize"); + + for (i = 0; i < ppd->num_sizes; i ++) + ppd->sizes[i].marked = strcmp(ppd->sizes[i].name, o->defchoice) == 0; +} + + +/* + * 'ppdMarkOption()' - Mark an option in a PPD file. + * + * Notes: + * + * -1 is returned if the given option would conflict with any currently + * selected option. + */ + +int /* O - Number of conflicts */ +ppdMarkOption(ppd_file_t *ppd, /* I - PPD file record */ + char *option, /* I - Keyword */ + char *choice) /* I - Option name */ +{ + int i; /* Looping var */ + ppd_option_t *o; /* Option pointer */ + ppd_choice_t *c; /* Choice pointer */ + + + if (ppd == NULL) + return (0); + + if (strcmp(option, "PageSize") == 0 && strncmp(choice, "Custom.", 7) == 0) + { + /* + * Handle variable page sizes... + */ + + ppdPageSize(ppd, choice); + choice = "Custom"; + } + + if ((o = ppdFindOption(ppd, option)) == NULL) + return (0); + + for (i = o->num_choices, c = o->choices; i > 0; i --, c ++) + if (strcmp(c->choice, choice) == 0) + c->marked = 1; + else if (o->ui != PPD_UI_PICKMANY) + c->marked = 0; + + if (strcmp(option, "PageSize") == 0 || strcmp(option, "PageRegion") == 0) + { + /* + * Mark current page size... + */ + + for (i = 0; i < ppd->num_sizes; i ++) + ppd->sizes[i].marked = strcmp(ppd->sizes[i].name, choice) == 0; + + /* + * Unmark the current PageSize or PageRegion setting, as appropriate... + */ + + if (strcmp(option, "PageSize") == 0) + { + o = ppdFindOption(ppd, "PageRegion"); + for (i = 0; i < o->num_choices; i ++) + o->choices[i].marked = 0; + } + else + { + o = ppdFindOption(ppd, "PageSize"); + for (i = 0; i < o->num_choices; i ++) + o->choices[i].marked = 0; + } + } + + return (ppdConflicts(ppd)); +} + + +/* + * 'ppd_defaults()' - Set the defaults for this group and all sub-groups. + */ + +static void +ppd_defaults(ppd_group_t *g) /* I - Group to default */ +{ + int i; /* Looping var */ + ppd_option_t *o; /* Current option */ + ppd_group_t *sg; /* Current sub-group */ + + + if (g == NULL) + return; + + for (i = g->num_options, o = g->options; i > 0; i --, o ++) + if (strcmp(o->keyword, "PageRegion") != 0) + ppd_default(o); + + for (i = g->num_subgroups, sg = g->subgroups; i > 0; i --, sg ++) + ppd_defaults(sg); +} + + +/* + * 'ppd_default()' - Set the default choice for an option. + */ + +static void +ppd_default(ppd_option_t *o) /* I - Option to default */ +{ + int i; /* Looping var */ + ppd_choice_t *c; /* Current choice */ + + + if (o == NULL) + return; + + for (i = o->num_choices, c = o->choices; i > 0; i --, c ++) + if (strcmp(c->choice, o->defchoice) == 0) + c->marked = 1; + else + c->marked = 0; +} + + +/* + * End of "$Id$". + */ diff --git a/cups/mime.c b/cups/mime.c new file mode 100644 index 0000000000..a98efece90 --- /dev/null +++ b/cups/mime.c @@ -0,0 +1,611 @@ +/* + * "$Id$" + * + * MIME database file routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-1999 by Easy Software Products, all rights reserved. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44145 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * mimeDelete() - Delete (free) a MIME database. + * mimeMerge() - Merge a MIME database from disk with the current one. + * mimeNew() - Create a new, empty MIME database. + * load_types() - Load a xyz.types file... + * delete_rules() - Free all memory for the given rule tree. + * load_convs() - Load a xyz.convs file... + * + * Revision History: + * + * $Log: mime.c,v $ + * Revision 1.12 1999/04/21 21:19:33 mike + * Changes for HP-UX. + * + * Revision 1.11 1999/04/21 19:31:29 mike + * Changed the directory header stuff to use the autoconf-recommended + * sequence of #ifdef's. + * + * Changed the language routines to look for the LOCALEDIR environment + * variable, and if it is not defined to use the LOCALEDIR string defined + * in config.h. + * + * Revision 1.10 1999/03/01 20:51:53 mike + * Code cleanup - removed extraneous semi-colons... + * + * Revision 1.9 1999/02/26 22:00:51 mike + * Added more debug statements. + * + * Fixed bugs in cupsPrintFile() - wasn't setting the IPP_TAG_MIMETYPE + * value tag for the file type. + * + * Updated conversion filter code to handle wildcards for super-type. + * + * Revision 1.8 1999/02/20 16:04:38 mike + * Updated mime.c to scan directories under WIN32. + * + * Fixed some compiler warnings under WIN32. + * + * Updated VC++ project files. + * + * Updated mime.types and mime.convs files for actual registered + * MIME type names. + * + * Revision 1.7 1999/02/05 17:40:53 mike + * Added IPP client read/write code. + * + * Added string functions missing from some UNIXs. + * + * Added option parsing functions. + * + * Added IPP convenience functions (not implemented yet). + * + * Updated source files to use local string.h as needed (for + * missing string functions) + * + * Revision 1.6 1999/02/01 22:08:39 mike + * Restored original directory-scanning functionality of mimeLoad(). + * + * Revision 1.4 1999/01/27 18:31:56 mike + * Updated PPD routines to handle emulations and patch files. + * + * Added DSC comments to emit output as appropriate. + * + * Revision 1.3 1999/01/24 14:18:43 mike + * Check-in prior to CVS use. + * + * Revision 1.2 1998/08/06 14:38:38 mike + * Finished coding and testing for CUPS 1.0. + * + * Revision 1.1 1998/06/11 20:50:53 mike + * Initial revision + */ + +/* + * Include necessary headers... + */ + +#include +#include +#include + +#include "string.h" +#include "mime.h" + +#if defined(WIN32) || defined(__EMX__) +# include +#elif HAVE_DIRENT_H +# include +typedef struct dirent DIRENT; +# define NAMLEN(dirent) strlen((dirent)->d_name) +#else +# if HAVE_SYS_NDIR_H +# include +# endif +# if HAVE_SYS_DIR_H +# include +# endif +# if HAVE_NDIR_H +# include +# endif +typedef struct direct DIRENT; +# define NAMLEN(dirent) (dirent)->d_namlen +#endif + + +/* + * Local functions... + */ + +static void load_types(mime_t *mime, char *filename); +static void load_convs(mime_t *mime, char *filename); +static void delete_rules(mime_magic_t *rules); + + +/* + * 'mimeDelete()' - Delete (free) a MIME database. + */ + +void +mimeDelete(mime_t *mime) /* I - MIME database */ +{ + int i; /* Looping var */ + + + if (mime == NULL) + return; + + /* + * Loop through the file types and delete any rules... + */ + + for (i = 0; i < mime->num_types; i ++) + { + delete_rules(mime->types[i]->rules); + free(mime->types[i]); + } + + /* + * Free the types and filters arrays, and then the MIME database structure. + */ + + free(mime->types); + free(mime->filters); + free(mime); +} + + +/* + * 'mimeMerge()' - Merge a MIME database from disk with the current one. + */ + +mime_t * /* O - Updated MIME database */ +mimeMerge(mime_t *mime, /* I - MIME database to add to */ + char *pathname) /* I - Directory to load */ +{ +#if defined(WIN32) || defined(__EMX__) + HANDLE dir; /* Directory handle */ + WIN32_FIND_DATA dent; /* Directory entry */ + char filename[1024], /* Full filename of types/converts file */ + *pathsep; /* Last character in path */ + + + /* + * First open the directory specified by pathname... Return NULL if nothing + * was read or if the pathname is NULL... + */ + + if (pathname == NULL) + return (NULL); + + strcpy(filename, pathname); + pathsep = filename + strlen(filename); + if (pathsep == filename || + (pathsep[-1] != '/' && pathsep[-1] != '\\')) + { + strcpy(pathsep, "/"); + pathsep ++; + } + + strcpy(pathsep, "*.types"); + + if ((dir = FindFirstFile(filename, &dent)) == 0) + return (NULL); + + /* + * If "mime" is NULL, make a new, blank database... + */ + + if (mime == NULL) + if ((mime = mimeNew()) == NULL) + return (NULL); + + /* + * Read all the .types files... + */ + + do + { + /* + * Load a mime.types file... + */ + + strcpy(pathsep, dent.cFileName); + load_types(mime, filename); + } + while (FindNextFile(dir, &dent)); + + FindClose(dir); + + /* + * Read all the .convs files... + */ + + strcpy(pathsep, "*.convs"); + + if ((dir = FindFirstFile(filename, &dent)) == 0) + return (mime); + + do + { + /* + * Load a mime.convs file... + */ + + strcpy(pathsep, dent.cFileName); + load_convs(mime, filename); + } + while (FindNextFile(dir, &dent)); + + FindClose(dir); + + return (mime); +#else + DIR *dir; /* Directory */ + DIRENT *dent; /* Directory entry */ + char filename[1024]; /* Full filename of types/converts file */ + + + /* + * First open the directory specified by pathname... Return NULL if nothing + * was read or if the pathname is NULL... + */ + + if (pathname == NULL) + return (NULL); + + if ((dir = opendir(pathname)) == NULL) + return (NULL); + + /* + * If "mime" is NULL, make a new, blank database... + */ + + if (mime == NULL) + if ((mime = mimeNew()) == NULL) + return (NULL); + + /* + * Read all the .types files... + */ + + while ((dent = readdir(dir)) != NULL) + { + if (NAMLEN(dent) > 6 && + strcmp(dent->d_name + NAMLEN(dent) - 6, ".types") == 0) + { + /* + * Load a mime.types file... + */ + + sprintf(filename, "%s/%s", pathname, dent->d_name); + load_types(mime, filename); + } + } + + rewinddir(dir); + + /* + * Read all the .convs files... + */ + + while ((dent = readdir(dir)) != NULL) + { + if (NAMLEN(dent) > 6 && + strcmp(dent->d_name + NAMLEN(dent) - 6, ".convs") == 0) + { + /* + * Load a mime.convs file... + */ + + sprintf(filename, "%s/%s", pathname, dent->d_name); + load_convs(mime, filename); + } + } + + closedir(dir); + + return (mime); +#endif /* WIN32 || __EMX__ */ +} + + +/* + * 'mimeNew()' - Create a new, empty MIME database. + */ + +mime_t * /* O - MIME database */ +mimeNew(void) +{ + return ((mime_t *)calloc(1, sizeof(mime_t))); +} + + +/* + * 'load_types()' - Load a xyz.types file... + */ + +static void +load_types(mime_t *mime, /* I - MIME database */ + char *filename) /* I - Types file to load */ +{ + FILE *fp; /* Types file */ + int linelen; /* Length of line */ + char line[65536], /* Input line from file */ + *lineptr, /* Current position in line */ + super[MIME_MAX_SUPER], /* Super-type name */ + type[MIME_MAX_TYPE], /* Type name */ + *temp; /* Temporary pointer */ + mime_type_t *typeptr; /* New MIME type */ + + + /* + * First try to open the file... + */ + + if ((fp = fopen(filename, "r")) == NULL) + return; + + /* + * Then read each line from the file, skipping any comments in the file... + */ + + while (fgets(line, sizeof(line), fp) != NULL) + { + linelen = strlen(line); + + /* + * While the last character in the line is a backslash, continue on to the + * next line (and the next, etc.) + */ + + if (line[linelen - 1] == '\n') + { + line[linelen - 1] = '\0'; + linelen --; + } + + while (line[linelen - 1] == '\\') + { + linelen --; + + if (fgets(line + linelen, sizeof(line) - linelen, fp) == NULL) + line[linelen] = '\0'; + else + { + linelen += strlen(line + linelen); + if (line[linelen - 1] == '\n') + { + line[linelen - 1] = '\0'; + linelen --; + } + } + } + + /* + * Skip blank lines and lines starting with a #... + */ + + if (line[0] == '\n' || line[0] == '#') + continue; + + /* + * Extract the super-type and type names from the beginning of the line. + */ + + lineptr = line; + temp = super; + + while (*lineptr != '/' && *lineptr != '\n' && *lineptr != '\0' && + (temp - super + 1) < MIME_MAX_SUPER) + *temp++ = tolower(*lineptr++); + + *temp = '\0'; + + if (*lineptr != '/') + continue; + + lineptr ++; + temp = type; + + while (*lineptr != ' ' && *lineptr != '\t' && *lineptr != '\n' && + *lineptr != '\0' && (temp - type + 1) < MIME_MAX_TYPE) + *temp++ = tolower(*lineptr++); + + *temp = '\0'; + + /* + * Add the type and rules to the MIME database... + */ + + typeptr = mimeAddType(mime, super, type); + mimeAddTypeRule(typeptr, lineptr); + } +} + + +/* + * 'load_convs()' - Load a xyz.convs file... + */ + +static void +load_convs(mime_t *mime, /* I - MIME database */ + char *filename) /* I - Convs file to load */ +{ + int i; /* Looping var */ + FILE *fp; /* Convs file */ + char line[1024], /* Input line from file */ + *lineptr, /* Current position in line */ + super[MIME_MAX_SUPER], /* Super-type name */ + type[MIME_MAX_TYPE], /* Type name */ + *temp, /* Temporary pointer */ + *filter; /* Filter program */ + mime_type_t **temptype, /* MIME type looping var */ + *dsttype; /* Destination MIME type */ + int cost; /* Cost of filter */ + + + /* + * First try to open the file... + */ + + if ((fp = fopen(filename, "r")) == NULL) + return; + + /* + * Then read each line from the file, skipping any comments in the file... + */ + + while (fgets(line, sizeof(line), fp) != NULL) + { + /* + * Skip blank lines and lines starting with a #... + */ + + if (line[0] == '\n' || line[0] == '#') + continue; + + /* + * Extract the destination super-type and type names from the middle of + * the line. + */ + + lineptr = line; + while (*lineptr != ' ' && *lineptr != '\t' && *lineptr != '\0') + lineptr ++; + + while (*lineptr == ' ' || *lineptr == '\t') + lineptr ++; + + temp = super; + + while (*lineptr != '/' && *lineptr != '\n' && *lineptr != '\0' && + (temp - super + 1) < MIME_MAX_SUPER) + *temp++ = tolower(*lineptr++); + + *temp = '\0'; + + if (*lineptr != '/') + continue; + + lineptr ++; + temp = type; + + while (*lineptr != ' ' && *lineptr != '\t' && *lineptr != '\n' && + *lineptr != '\0' && (temp - type + 1) < MIME_MAX_TYPE) + *temp++ = tolower(*lineptr++); + + *temp = '\0'; + + if (*lineptr == '\0' || *lineptr == '\n') + continue; + + if ((dsttype = mimeType(mime, super, type)) == NULL) + continue; + + /* + * Then get the cost and filter program... + */ + + while (*lineptr == ' ' || *lineptr == '\t') + lineptr ++; + + if (*lineptr < '0' || *lineptr > '9') + continue; + + cost = atoi(lineptr); + + while (*lineptr != ' ' && *lineptr != '\t' && *lineptr != '\0') + lineptr ++; + while (*lineptr == ' ' || *lineptr == '\t') + lineptr ++; + + if (*lineptr == '\0' || *lineptr == '\n') + continue; + + filter = lineptr; + if (filter[strlen(filter) - 1] == '\n') + filter[strlen(filter) - 1] = '\0'; + + /* + * Finally, get the source super-type and type names from the beginning of + * the line. We do it here so we can support wildcards... + */ + + lineptr = line; + temp = super; + + while (*lineptr != '/' && *lineptr != '\n' && *lineptr != '\0' && + (temp - super + 1) < MIME_MAX_SUPER) + *temp++ = tolower(*lineptr++); + + *temp = '\0'; + + if (*lineptr != '/') + continue; + + lineptr ++; + temp = type; + + while (*lineptr != ' ' && *lineptr != '\t' && *lineptr != '\n' && + *lineptr != '\0' && (temp - type + 1) < MIME_MAX_TYPE) + *temp++ = tolower(*lineptr++); + + *temp = '\0'; + + /* + * Add the filter to the MIME database, supporting wildcards as needed... + */ + + for (temptype = mime->types, i = 0; i < mime->num_types; i ++, temptype ++) + if ((super[0] == '*' || strcmp((*temptype)->super, super) == 0) && + (type[0] == '*' || strcmp((*temptype)->type, type) == 0)) + mimeAddFilter(mime, *temptype, dsttype, cost, filter); + } +} + + +/* + * 'delete_rules()' - Free all memory for the given rule tree. + */ + +static void +delete_rules(mime_magic_t *rules) /* I - Rules to free */ +{ + mime_magic_t *next; /* Next rule to free */ + + + /* + * Free the rules list, descending recursively to free any child rules. + */ + + while (rules != NULL) + { + next = rules->next; + + if (rules->child != NULL) + delete_rules(rules->child); + + free(rules); + rules = next; + } +} + + +/* + * End of "$Id$". + */ diff --git a/cups/mime.h b/cups/mime.h new file mode 100644 index 0000000000..78672400be --- /dev/null +++ b/cups/mime.h @@ -0,0 +1,137 @@ +/* + * "$Id$" + * + * MIME type/conversion database definitions for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-1999 by Easy Software Products, all rights reserved. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44145 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + */ + +#ifndef _MIME_H_ +# define _MIME_H_ + +/* + * C++ magic... + */ + +# ifdef _cplusplus +extern "C" { +# endif /* _cplusplus */ + + +/* + * Constants... + */ + +# define MIME_MAX_SUPER 16 /* Maximum size of supertype name */ +# define MIME_MAX_TYPE 32 /* Maximum size of type name */ +# define MIME_MAX_FILTER 256 /* Maximum size of filter pathname */ +# define MIME_MAX_BUFFER 8192 /* Maximum size of file buffer */ + + +/* + * Types/structures... + */ + +typedef enum +{ + MIME_MAGIC_NOP, /* No operation */ + MIME_MAGIC_AND, /* Logical AND of all children */ + MIME_MAGIC_OR, /* Logical OR of all children */ + MIME_MAGIC_MATCH, /* Filename match */ + MIME_MAGIC_ASCII, /* ASCII characters in range */ + MIME_MAGIC_PRINTABLE, /* Printable characters (32-255) in range */ + MIME_MAGIC_STRING, /* String matches */ + MIME_MAGIC_CHAR, /* Character/byte matches */ + MIME_MAGIC_SHORT, /* Short/16-bit word matches */ + MIME_MAGIC_INT, /* Integer/32-bit word matches */ + MIME_MAGIC_LOCALE /* Current locale matches string */ +} mime_op_t; + +typedef struct mime_magic_str /**** MIME Magic Data ****/ +{ + struct mime_magic_str *prev, /* Previous rule */ + *next, /* Next rule */ + *parent, /* Parent rules */ + *child; /* Child rules */ + short op, /* Operation code (see above) */ + invert; /* Invert the result */ + int offset, /* Offset in file */ + length; /* Length of data */ + union + { + char matchv[64]; /* Match value */ + char localev[64]; /* Locale value */ + char stringv[64]; /* String value */ + char charv; /* Byte value */ + short shortv; /* Short value */ + int intv; /* Integer value */ + } value; +} mime_magic_t; + +typedef struct /**** MIME Type Data ****/ +{ + char super[MIME_MAX_SUPER], /* Super-type name ("image", "application", etc.) */ + type[MIME_MAX_TYPE]; /* Type name ("png", "postscript", etc.) */ + mime_magic_t *rules; /* Rules used to detect this type */ +} mime_type_t; + +typedef struct /**** MIME Conversion Filter Data ****/ +{ + mime_type_t *src, /* Source type */ + *dst; /* Destination type */ + int cost; /* Relative cost */ + char filter[MIME_MAX_FILTER];/* Filter program to use */ +} mime_filter_t; + +typedef struct /**** MIME Database ****/ +{ + int num_types; /* Number of file types */ + mime_type_t **types; /* File types */ + int num_filters; /* Number of type conversion filters */ + mime_filter_t *filters; /* Type conversion filters */ +} mime_t; + + +/* + * Functions... + */ + +extern void mimeDelete(mime_t *mime); +#define mimeLoad(pathname) mimeMerge((mime_t *)0, (pathname)); +extern mime_t *mimeMerge(mime_t *mime, char *pathname); +extern mime_t *mimeNew(void); + +extern mime_type_t *mimeAddType(mime_t *mime, char *super, char *type); +extern int mimeAddTypeRule(mime_type_t *mt, char *rule); +extern mime_type_t *mimeFileType(mime_t *mime, char *pathname); +extern mime_type_t *mimeType(mime_t *mime, char *super, char *type); + +extern mime_filter_t *mimeAddFilter(mime_t *mime, mime_type_t *src, mime_type_t *dst, + int cost, char *filter); +extern mime_filter_t *mimeFilter(mime_t *mime, mime_type_t *src, mime_type_t *dst, + int *num_filters); + +# ifdef _cplusplus +} +# endif /* _cplusplus */ +#endif /* !_MIME_H_ */ + +/* + * End of "$Id$". + */ diff --git a/cups/options.c b/cups/options.c new file mode 100644 index 0000000000..dd5c3dd879 --- /dev/null +++ b/cups/options.c @@ -0,0 +1,333 @@ +/* + * "$Id$" + * + * Option routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * cupsAddOption() - Add an option to an option array. + * cupsFreeOptions() - Free all memory used by options. + * cupsGetOption() - Get an option value. + * cupsParseOptions() - Parse options from a command-line argument. + * cupsMarkOptions() - Mark command-line options in a PPD file. + */ + +/* + * Include necessary headers... + */ + +#include "cups.h" +#include +#include +#include "string.h" + + +/* + * 'cupsAddOption()' - Add an option to an option array. + */ + +int /* O - Number of options */ +cupsAddOption(char *name, /* I - Name of option */ + char *value, /* I - Value of option */ + int num_options, /* I - Number of options */ + cups_option_t **options) /* IO - Pointer to options */ +{ + int i; /* Looping var */ + cups_option_t *temp; /* Pointer to new option */ + + + if (name == NULL || value == NULL || options == NULL) + return (0); + + /* + * Look for an existing option with the same name... + */ + + for (i = 0, temp = *options; i < num_options; i ++, temp ++) + if (strcmp(temp->name, name) == 0) + break; + + if (i >= num_options) + { + /* + * No matching option name... + */ + + if (num_options == 0) + temp = (cups_option_t *)malloc(sizeof(cups_option_t)); + else + temp = (cups_option_t *)realloc(*options, sizeof(cups_option_t) * + (num_options + 1)); + + if (temp == NULL) + return (0); + + *options = temp; + temp += num_options; + temp->name = strdup(name); + num_options ++; + } + else + { + /* + * Match found; free the old value... + */ + + free(temp->value); + } + + temp->value = strdup(value); + + return (num_options); +} + + +/* + * 'cupsFreeOptions()' - Free all memory used by options. + */ + +void +cupsFreeOptions(int num_options, /* I - Number of options */ + cups_option_t *options) /* I - Pointer to options */ +{ + int i; /* Looping var */ + + + if (num_options == 0 || options == NULL) + return; + + for (i = 0; i < num_options; i ++) + { + free(options[i].name); + free(options[i].value); + } + + free(options); +} + + +/* + * 'cupsGetOption()' - Get an option value. + */ + +char * /* O - Option value or NULL */ +cupsGetOption(char *name, /* I - Name of option */ + int num_options,/* I - Number of options */ + cups_option_t *options) /* I - Options */ +{ + int i; /* Looping var */ + + + if (name == NULL || num_options == 0 || options == NULL) + return (NULL); + + for (i = 0; i < num_options; i ++) + if (strcmp(options[i].name, name) == 0) + return (options[i].value); + + return (NULL); +} + + +/* + * 'cupsParseOptions()' - Parse options from a command-line argument. + */ + +int /* O - Number of options found */ +cupsParseOptions(char *arg, /* I - Argument to parse */ + int num_options, /* I - Number of options */ + cups_option_t **options) /* O - Options found */ +{ + char *copyarg, /* Copy of input string */ + *ptr, /* Pointer into string */ + *name, /* Pointer to name */ + *value; /* Pointer to value */ + + + if (arg == NULL || options == NULL) + return (0); + + /* + * Make a copy of the argument string and then divide it up... + */ + + copyarg = strdup(arg); + ptr = copyarg; + + while (*ptr != '\0') + { + /* + * Get the name up to a SPACE, =, or end-of-string... + */ + + name = ptr; + while (!isspace(*ptr) && *ptr != '=' && *ptr != '\0') + ptr ++; + + /* + * Skip trailing spaces... + */ + + while (isspace(*ptr)) + *ptr++ = '\0'; + + if (*ptr != '=') + { + /* + * Start of another option... + */ + + num_options = cupsAddOption(name, "", num_options, options); + continue; + } + + /* + * Remove = and parse the value... + */ + + *ptr++ = '\0'; + + if (*ptr == '\'') + { + /* + * Quoted string constant... + */ + + ptr ++; + value = ptr; + + while (*ptr != '\'' && *ptr != '\0') + ptr ++; + + if (*ptr != '\0') + *ptr++ = '\0'; + } + else if (*ptr == '\"') + { + /* + * Double-quoted string constant... + */ + + ptr ++; + value = ptr; + + while (*ptr != '\"' && *ptr != '\0') + ptr ++; + + if (*ptr != '\0') + *ptr++ = '\0'; + } + else + { + /* + * Normal space-delimited string... + */ + + value = ptr; + + while (!isspace(*ptr) && *ptr != '\0') + ptr ++; + + while (isspace(*ptr)) + *ptr++ = '\0'; + } + + /* + * Add the string value... + */ + + num_options = cupsAddOption(name, value, num_options, options); + } + + /* + * Free the copy of the argument we made and return the number of options + * found. + */ + + free(copyarg); + + return (num_options); +} + + +/* + * 'cupsMarkOptions()' - Mark command-line options in a PPD file. + */ + +int /* O - 1 if conflicting */ +cupsMarkOptions(ppd_file_t *ppd, /* I - PPD file */ + int num_options, /* I - Number of options */ + cups_option_t *options) /* I - Options */ +{ + int i; /* Looping var */ + int conflict; /* Option conflicts */ + char media_size[64]; /* Updated media size */ + + + conflict = 0; + + for (i = num_options; i > 0; i --, options ++) + if (strcmp(options->name, "media-size") == 0) + { + strcpy(media_size, options->value); + + if (strncmp(options->value, "us-", 3) == 0) + { + strcpy(media_size, media_size + 3); + media_size[0] = toupper(media_size[0]); + } + else if (strncmp(options->value, "iso-", 4) == 0) + { + strcpy(media_size, media_size + 4); + media_size[0] = toupper(media_size[0]); + } + + if (ppdMarkOption(ppd, "PageSize", media_size)) + conflict = 1; + } + else if (strcmp(options->name, "sides") == 0) + { + if (strcmp(options->value, "one-sided") == 0) + { + if (ppdMarkOption(ppd, "Duplex", "None")) + conflict = 1; + } + else if (strcmp(options->value, "two-sided-long-edge") == 0) + { + if (ppdMarkOption(ppd, "Duplex", "NoTumble")) + conflict = 1; + } + else if (strcmp(options->value, "two-sided-short-edge") == 0) + { + if (ppdMarkOption(ppd, "Duplex", "Tumble")) + conflict = 1; + } + } + else if (ppdMarkOption(ppd, options->name, options->value)) + conflict = 1; + + return (conflict); +} + + +/* + * End of "$Id$". + */ diff --git a/cups/page.c b/cups/page.c new file mode 100644 index 0000000000..46c5745812 --- /dev/null +++ b/cups/page.c @@ -0,0 +1,179 @@ +/* + * "$Id$" + * + * Page size functions for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-1999 by Easy Software Products, all rights reserved. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * PostScript is a trademark of Adobe Systems, Inc. + * + * Contents: + * + * ppdPageSize() - Get the page size record for the given size. + * ppdPageWidth() - Get the page width for the given size. + * ppdPageLength() - Get the page length for the given size. + */ + +/* + * Include necessary headers... + */ + +#include "ppd.h" +#include "string.h" +#include + + +/* + * 'ppdPageSize()' - Get the page size record for the given size. + */ + +ppd_size_t * /* O - Size record for page or NULL */ +ppdPageSize(ppd_file_t *ppd, /* I - PPD file record */ + char *name) /* I - Size name */ +{ + int i; /* Looping var */ + float w, l; /* Width and length of page */ + char units[255]; /* Page size units... */ + + + if (ppd == NULL) + return (NULL); + + if (name != NULL) + { + if (strncmp(name, "Custom.", 7) == 0 && + strcmp(ppd->sizes[0].name, "Custom") == 0) + { + /* + * Variable size; size name can be one of the following: + * + * Custom.WIDTHxLENGTHin - Size in inches + * Custom.WIDTHxLENGTHcm - Size in centimeters + * Custom.WIDTHxLENGTHmm - Size in millimeters + * Custom.WIDTHxLENGTH[pt] - Size in points + */ + + units[0] = '\0'; + if (sscanf(name + 7, "%fx%f%s", &w, &l, units) < 2) + return (NULL); + + if (strcasecmp(units, "in") == 0) + { + ppd->sizes[0].width = w * 72.0; + ppd->sizes[0].length = l * 72.0; + ppd->sizes[0].left = ppd->custom_margins[0]; + ppd->sizes[0].bottom = ppd->custom_margins[1]; + ppd->sizes[0].right = w * 72.0 - ppd->custom_margins[2]; + ppd->sizes[0].top = l * 72.0 - ppd->custom_margins[3]; + } + else if (strcasecmp(units, "cm") == 0) + { + ppd->sizes[0].width = w * 2.54 * 72.0; + ppd->sizes[0].length = l * 2.54 * 72.0; + ppd->sizes[0].left = ppd->custom_margins[0]; + ppd->sizes[0].bottom = ppd->custom_margins[1]; + ppd->sizes[0].right = w * 2.54 * 72.0 - ppd->custom_margins[2]; + ppd->sizes[0].top = l * 2.54 * 72.0 - ppd->custom_margins[3]; + } + else if (strcasecmp(units, "mm") == 0) + { + ppd->sizes[0].width = w * 25.4 * 72.0; + ppd->sizes[0].length = l * 25.4 * 72.0; + ppd->sizes[0].left = ppd->custom_margins[0]; + ppd->sizes[0].bottom = ppd->custom_margins[1]; + ppd->sizes[0].right = w * 25.4 * 72.0 - ppd->custom_margins[2]; + ppd->sizes[0].top = l * 25.4 * 72.0 - ppd->custom_margins[3]; + } + else + { + ppd->sizes[0].width = w; + ppd->sizes[0].length = l; + ppd->sizes[0].left = ppd->custom_margins[0]; + ppd->sizes[0].bottom = ppd->custom_margins[1]; + ppd->sizes[0].right = w - ppd->custom_margins[2]; + ppd->sizes[0].top = l - ppd->custom_margins[3]; + } + + return (ppd->sizes); + } + else + { + /* + * Lookup by name... + */ + + for (i = 0; i < ppd->num_sizes; i ++) + if (strcmp(name, ppd->sizes[i].name) == 0) + return (ppd->sizes + i); + } + } + else + { + /* + * Find default... + */ + + for (i = 0; i < ppd->num_sizes; i ++) + if (ppd->sizes[i].marked) + return (ppd->sizes + i); + } + + return (NULL); +} + + +/* + * 'ppdPageWidth()' - Get the page width for the given size. + */ + +float /* O - Width of page in points or 0.0 */ +ppdPageWidth(ppd_file_t *ppd, /* I - PPD file record */ + char *name) /* I - Size name */ +{ + ppd_size_t *size; /* Page size */ + + + if ((size = ppdPageSize(ppd, name)) == NULL) + return (0.0); + else + return (size->width); +} + + +/* + * 'ppdPageLength()' - Get the page length for the given size. + */ + +float /* O - Length of page in points or 0.0 */ +ppdPageLength(ppd_file_t *ppd, /* I - PPD file */ + char *name) /* I - Size name */ +{ + ppd_size_t *size; /* Page size */ + + + if ((size = ppdPageSize(ppd, name)) == NULL) + return (0.0); + else + return (size->length); +} + + +/* + * End of "$Id$". + */ diff --git a/cups/ppd.c b/cups/ppd.c new file mode 100644 index 0000000000..a0b3e7a6d6 --- /dev/null +++ b/cups/ppd.c @@ -0,0 +1,1483 @@ +/* + * "$Id$" + * + * PPD file routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-1999 by Easy Software Products, all rights reserved. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * PostScript is a trademark of Adobe Systems, Inc. + * + * This code and any derivative of it may be used and distributed + * freely under the terms of the GNU General Public License when + * used with GNU Ghostscript or its derivatives. Use of the code + * (or any derivative of it) with software other than GNU + * GhostScript (or its derivatives) is governed by the CUPS license + * agreement. + * + * Contents: + * + * ppdClose() - Free all memory used by the PPD file. + * ppd_free_group() - Free a single UI group. + * ppd_free_option() - Free a single option. + * ppdOpen() - Read a PPD file into memory. + * ppdOpenFd() - Read a PPD file into memory. + * ppdOpenFile() - Read a PPD file into memory. + * ppd_read() - Read a line from a PPD file, skipping comment lines + * as necessary. + */ + +/* + * Include necessary headers. + */ + +/*#define DEBUG*/ +#include "ppd.h" +#include +#include +#include "string.h" + + +/* + * Definitions... + */ + +#if defined(WIN32) || defined(__EMX__) +# define READ_BINARY "rb" /* Open a binary file for reading */ +# define WRITE_BINARY "wb" /* Open a binary file for writing */ +#else +# define READ_BINARY "r" /* Open a binary file for reading */ +# define WRITE_BINARY "w" /* Open a binary file for writing */ +#endif /* WIN32 || __EMX__ */ + +#define PPD_KEYWORD 1 /* Line contained a keyword */ +#define PPD_OPTION 2 /* Line contained an option name */ +#define PPD_TEXT 4 /* Line contained human-readable text */ +#define PPD_STRING 8 /* Line contained a string or code */ + + +/* + * Local functions... + */ + +static int ppd_read(FILE *fp, char *keyword, char *option, + char *text, char **string); +static void ppd_decode(char *string); +static void ppd_free_group(ppd_group_t *group); +static void ppd_free_option(ppd_option_t *option); +static ppd_group_t *ppd_get_group(ppd_file_t *ppd, char *name); +static ppd_option_t *ppd_get_option(ppd_group_t *group, char *name); +static ppd_choice_t *ppd_add_choice(ppd_option_t *option, char *name); + + +/* + * 'ppdClose()' - Free all memory used by the PPD file. + */ + +void +ppdClose(ppd_file_t *ppd) /* I - PPD file record */ +{ + int i; /* Looping var */ + ppd_emul_t *emul; /* Current emulation */ + ppd_group_t *group; /* Current group */ + char **font; /* Current font */ + + + /* + * Range check the PPD file record... + */ + + if (ppd == NULL) + return; + + /* + * Free all strings at the top level... + */ + + free(ppd->lang_encoding); + free(ppd->lang_version); + free(ppd->modelname); + free(ppd->ttrasterizer); + free(ppd->manufacturer); + free(ppd->product); + free(ppd->nickname); + free(ppd->shortnickname); + + /* + * Free any emulations... + */ + + if (ppd->num_emulations > 0) + { + for (i = ppd->num_emulations, emul = ppd->emulations; i > 0; i --, emul ++) + { + free(emul->start); + free(emul->stop); + } + + free(ppd->emulations); + } + + /* + * Free any UI groups, subgroups, and options... + */ + + if (ppd->num_groups > 0) + { + for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++) + ppd_free_group(group); + + free(ppd->groups); + } + + /* + * Free any page sizes... + */ + + if (ppd->num_sizes > 0) + free(ppd->sizes); + + /* + * Free any constraints... + */ + + if (ppd->num_consts > 0) + free(ppd->consts); + + /* + * Free any fonts... + */ + + if (ppd->num_fonts > 0) + { + for (i = ppd->num_fonts, font = ppd->fonts; i > 0; i --, font ++) + free(*font); + + free(ppd->fonts); + } + + /* + * Free any profiles... + */ + + if (ppd->num_profiles > 0) + free(ppd->profiles); + + /* + * Free the whole record... + */ + + free(ppd); +} + + +/* + * 'ppd_free_group()' - Free a single UI group. + */ + +static void +ppd_free_group(ppd_group_t *group) /* I - Group to free */ +{ + int i; /* Looping var */ + ppd_option_t *option; /* Current option */ + ppd_group_t *subgroup; /* Current sub-group */ + + + if (group->num_options > 0) + { + for (i = group->num_options, option = group->options; + i > 0; + i --, option ++) + ppd_free_option(option); + + free(group->options); + } + + if (group->num_subgroups > 0) + { + for (i = group->num_subgroups, subgroup = group->subgroups; + i > 0; + i --, subgroup ++) + ppd_free_group(subgroup); + + free(group->subgroups); + } +} + + +/* + * 'ppd_free_option()' - Free a single option. + */ + +static void +ppd_free_option(ppd_option_t *option) /* I - Option to free */ +{ + int i; /* Looping var */ + ppd_choice_t *choice; /* Current choice */ + + + if (option->num_choices > 0) + { + for (i = option->num_choices, choice = option->choices; + i > 0; + i --, choice ++) + free(choice->code); + + free(option->choices); + } +} + + +/* + * 'ppd_get_group()' - Find or create the named group as needed. + */ + +static ppd_group_t * /* O - Named group */ +ppd_get_group(ppd_file_t *ppd, /* I - PPD file */ + char *name) /* I - Name of group */ +{ + int i; /* Looping var */ + ppd_group_t *group; /* Group */ + + + for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++) + if (strcmp(group->text, name) == 0) + break; + + if (i == 0) + { + if (ppd->num_groups == 0) + group = malloc(sizeof(ppd_group_t)); + else + group = realloc(ppd->groups, + (ppd->num_groups + 1) * sizeof(ppd_group_t)); + + if (group == NULL) + return (NULL); + + ppd->groups = group; + group += ppd->num_groups; + ppd->num_groups ++; + + memset(group, 0, sizeof(ppd_group_t)); + strcpy(group->text, name); + } + + return (group); +} + + +/* + * 'ppd_get_option()' - Find or create the named option as needed. + */ + +static ppd_option_t * /* O - Named option */ +ppd_get_option(ppd_group_t *group, /* I - Group */ + char *name) /* I - Name of option */ +{ + int i; /* Looping var */ + ppd_option_t *option; /* Option */ + + + for (i = group->num_options, option = group->options; i > 0; i --, option ++) + if (strcmp(option->keyword, name) == 0) + break; + + if (i == 0) + { + if (group->num_options == 0) + option = malloc(sizeof(ppd_option_t)); + else + option = realloc(group->options, + (group->num_options + 1) * sizeof(ppd_option_t)); + + if (option == NULL) + return (NULL); + + group->options = option; + option += group->num_options; + group->num_options ++; + + memset(option, 0, sizeof(ppd_option_t)); + strcpy(option->keyword, name); + } + + return (option); +} + + +/* + * 'ppd_add_choice()' - Add a choice to an option. + */ + +static ppd_choice_t * /* O - Named choice */ +ppd_add_choice(ppd_option_t *option, /* I - Option */ + char *name) /* I - Name of choice */ +{ + ppd_choice_t *choice; /* Choice */ + + + if (option->num_choices == 0) + choice = malloc(sizeof(ppd_choice_t)); + else + choice = realloc(option->choices, + sizeof(ppd_choice_t) * (option->num_choices + 1)); + + if (choice == NULL) + return (NULL); + + option->choices = choice; + choice += option->num_choices; + option->num_choices ++; + + memset(choice, 0, sizeof(ppd_choice_t)); + strcpy(choice->choice, name); + + return (choice); +} + + +/* + * 'ppd_add_size()' - Add a page size. + */ + +static ppd_size_t * /* O - Named size */ +ppd_add_size(ppd_file_t *ppd, /* I - PPD file */ + char *name) /* I - Name of size */ +{ + ppd_size_t *size; /* Size */ + + + if (ppd->num_sizes == 0) + size = malloc(sizeof(ppd_size_t)); + else + size = realloc(ppd->sizes, sizeof(ppd_size_t) * (ppd->num_sizes + 1)); + + if (size == NULL) + return (NULL); + + ppd->sizes = size; + size += ppd->num_sizes; + ppd->num_sizes ++; + + memset(size, 0, sizeof(ppd_size_t)); + strcpy(size->name, name); + + return (size); +} + + +/* + * 'ppdOpen()' - Read a PPD file into memory. + */ + +ppd_file_t * /* O - PPD file record */ +ppdOpen(FILE *fp) /* I - File to read from */ +{ + int i, j, k, m; /* Looping vars */ + int count; /* Temporary count */ + ppd_file_t *ppd; /* PPD file record */ + ppd_group_t *group, /* Current group */ + *subgroup; /* Current sub-group */ + ppd_option_t *option; /* Current option */ + ppd_choice_t *choice; /* Current choice */ + ppd_const_t *constraint; /* Current constraint */ + ppd_size_t *size; /* Current page size */ + int mask; /* Line data mask */ + char keyword[41], /* Keyword from file */ + name[41], /* Option from file */ + text[81], /* Human-readable text from file */ + *string, /* Code/text from file */ + *sptr, /* Pointer into string */ + *nameptr; /* Pointer into name */ + float order; /* Order dependency number */ + ppd_section_t section; /* Order dependency section */ + ppd_profile_t *profile; /* Pointer to color profile */ + + + /* + * Range check input... + */ + + if (fp == NULL) + return (NULL); + + /* + * Grab the first line and make sure it reads '*PPD-Adobe: "major.minor"'... + */ + + mask = ppd_read(fp, keyword, name, text, &string); + + if (mask == 0 || + strcmp(keyword, "PPD-Adobe") != 0 || + string == NULL || string[0] != '4') + { + /* + * Either this is not a PPD file, or it is not a 4.x PPD file. + */ + + if (string != NULL) + free(string); + + return (NULL); + } + + if (string != NULL) + free(string); + + /* + * Allocate memory for the PPD file record... + */ + + if ((ppd = calloc(sizeof(ppd_file_t), 1)) == NULL) + return (NULL); + + ppd->language_level = 1; + ppd->color_device = 0; + ppd->colorspace = PPD_CS_GRAY; + ppd->landscape = 90; + + /* + * Read lines from the PPD file and add them to the file record... + */ + + group = NULL; + subgroup = NULL; + option = NULL; + choice = NULL; + + while ((mask = ppd_read(fp, keyword, name, text, &string)) != 0) + { +#ifdef DEBUG + printf("mask = %x, keyword = \"%s\"", mask, keyword); + + if (name[0] != '\0') + printf(", name = \"%s\"", name); + + if (text[0] != '\0') + printf(", text = \"%s\"", text); + + if (string != NULL) + { + if (strlen(string) > 40) + printf(", string = %08x", string); + else + printf(", string = \"%s\"", string); + } + + puts(""); +#endif /* DEBUG */ + + if (strcmp(keyword, "LanguageLevel") == 0) + ppd->language_level = atoi(string); + else if (strcmp(keyword, "LanguageEncoding") == 0) + { + ppd->lang_encoding = string; + string = NULL; /* Don't free this string below */ + } + else if (strcmp(keyword, "LanguageVersion") == 0) + { + ppd->lang_version = string; + string = NULL; /* Don't free this string below */ + } + else if (strcmp(keyword, "Manufacturer") == 0) + { + ppd->manufacturer = string; + string = NULL; /* Don't free this string below */ + } + else if (strcmp(keyword, "ModelName") == 0) + { + ppd->modelname = string; + string = NULL; /* Don't free this string below */ + } + else if (strcmp(keyword, "NickName") == 0) + { + ppd->nickname = string; + string = NULL; /* Don't free this string below */ + } + else if (strcmp(keyword, "Product") == 0) + { + ppd->product = string; + string = NULL; /* Don't free this string below */ + } + else if (strcmp(keyword, "ShortNickName") == 0) + { + ppd->shortnickname = string; + string = NULL; /* Don't free this string below */ + } + else if (strcmp(keyword, "TTRasterizer") == 0) + { + ppd->ttrasterizer = string; + string = NULL; /* Don't free this string below */ + } + else if (strcmp(keyword, "JCLBegin") == 0) + { + ppd_decode(string); /* Decode quoted string */ + ppd->jcl_begin = string; + string = NULL; /* Don't free this string below */ + } + else if (strcmp(keyword, "JCLEnd") == 0) + { + ppd_decode(string); /* Decode quoted string */ + ppd->jcl_end = string; + string = NULL; /* Don't free this string below */ + } + else if (strcmp(keyword, "JCLToPSInterpreter") == 0) + { + ppd_decode(string); /* Decode quoted string */ + ppd->jcl_ps = string; + string = NULL; /* Don't free this string below */ + } + else if (strcmp(keyword, "AccurateScreensSupport") == 0) + ppd->accurate_screens = strcmp(string, "True") == 0; + else if (strcmp(keyword, "ColorDevice") == 0) + ppd->color_device = strcmp(string, "True") == 0; + else if (strcmp(keyword, "ContoneOnly") == 0) + ppd->contone_only = strcmp(string, "True") == 0; + else if (strcmp(keyword, "DefaultColorSpace") == 0) + { + if (strcmp(string, "CMY") == 0) + ppd->colorspace = PPD_CS_CMY; + else if (strcmp(string, "CMYK") == 0) + ppd->colorspace = PPD_CS_CMYK; + else if (strcmp(string, "RGB") == 0) + ppd->colorspace = PPD_CS_RGB; + else if (strcmp(string, "RGBK") == 0) + ppd->colorspace = PPD_CS_RGBK; + else if (strcmp(string, "N") == 0) + ppd->colorspace = PPD_CS_N; + else + ppd->colorspace = PPD_CS_GRAY; + } + else if (strcmp(keyword, "cupsManualCopies") == 0) + ppd->manual_copies = strcmp(string, "True") == 0; + else if (strcmp(keyword, "cupsModelNumber") == 0) + ppd->model_number = atoi(string); + else if (strcmp(keyword, "cupsColorProfile") == 0) + { + if (ppd->num_profiles == 0) + profile = malloc(sizeof(ppd_profile_t)); + else + profile = realloc(ppd->profiles, sizeof(ppd_profile_t) * + (ppd->num_profiles + 1)); + + ppd->profiles = profile; + profile += ppd->num_profiles; + ppd->num_profiles ++; + + memset(profile, 0, sizeof(ppd_profile_t)); + strcpy(profile->resolution, name); + strcpy(profile->media_type, text); + sscanf(string, "%f%f%f%f%f%f%f%f%f%f", &(profile->density), + profile->matrix[0] + 0, profile->matrix[0] + 1, + profile->matrix[0] + 2, profile->matrix[1] + 0, + profile->matrix[1] + 1, profile->matrix[1] + 2, + profile->matrix[2] + 0, profile->matrix[2] + 1, + profile->matrix[2] + 2); + } + else if (strcmp(keyword, "VariablePaperSize") == 0 && + strcmp(string, "True") == 0) + { + ppd->variable_sizes = 1; + + /* + * Add a "Custom" page size entry... + */ + + ppd_add_size(ppd, "Custom"); + + /* + * Add a "Custom" page size option... + */ + + if ((group = ppd_get_group(ppd, "General")) == NULL) + { + ppdClose(ppd); + free(string); + return (NULL); + } + + if ((option = ppd_get_option(group, "PageSize")) == NULL) + { + ppdClose(ppd); + free(string); + return (NULL); + } + + if ((choice = ppd_add_choice(option, "Custom")) == NULL) + { + ppdClose(ppd); + free(string); + return (NULL); + } + + strcpy(choice->text, "Custom Size"); + group = NULL; + option = NULL; + } + else if (strcmp(keyword, "MaxMediaWidth") == 0) + ppd->custom_max[0] = atof(string); + else if (strcmp(keyword, "MaxMediaHeight") == 0) + ppd->custom_max[1] = atof(string); + else if (strcmp(keyword, "ParamCustomPageSize") == 0) + { + if (strcmp(name, "Width") == 0) + sscanf(string, "%*s%*s%f%f", ppd->custom_min + 0, + ppd->custom_max + 0); + else if (strcmp(name, "Height") == 0) + sscanf(string, "%*s%*s%f%f", ppd->custom_min + 1, + ppd->custom_max + 1); + } + else if (strcmp(keyword, "HWMargins") == 0) + sscanf(string, "%f%f%f%f", ppd->custom_margins + 0, + ppd->custom_margins + 1, ppd->custom_margins + 2, + ppd->custom_margins + 3); + else if (strcmp(keyword, "CustomPageSize") == 0 && + strcmp(name, "True") == 0 && + ppd->variable_sizes) + { + if ((option = ppdFindOption(ppd, "PageSize")) == NULL) + { + ppdClose(ppd); + free(string); + return (NULL); + } + + if ((choice = ppdFindChoice(option, "Custom")) == NULL) + { + ppdClose(ppd); + free(string); + return (NULL); + } + + choice->code = string; + string = NULL; + option = NULL; + } + else if (strcmp(keyword, "LandscapeOrientation") == 0) + { + if (strcmp(string, "Minus90") == 0) + ppd->landscape = -90; + else + ppd->landscape = 90; + } + else if (strcmp(keyword, "Emulators") == 0) + { + for (count = 1, sptr = string; sptr != NULL;) + if ((sptr = strchr(sptr, ' ')) != NULL) + { + count ++; + while (*sptr == ' ') + sptr ++; + } + + ppd->num_emulations = count; + ppd->emulations = calloc(sizeof(ppd_emul_t), count); + + for (i = 0, sptr = string; i < count; i ++) + { + for (nameptr = ppd->emulations[i].name; *sptr != '\0' && *sptr != ' ';) + *nameptr ++ = *sptr ++; + + *nameptr = '\0'; + + while (*sptr == ' ') + sptr ++; + } + } + else if (strncmp(keyword, "StartEmulator_", 14) == 0) + { + ppd_decode(string); + + for (i = 0; i < ppd->num_emulations; i ++) + if (strcmp(keyword + 14, ppd->emulations[i].name) == 0) + { + ppd->emulations[i].start = string; + string = NULL; + } + } + else if (strncmp(keyword, "StopEmulator_", 13) == 0) + { + ppd_decode(string); + + for (i = 0; i < ppd->num_emulations; i ++) + if (strcmp(keyword + 13, ppd->emulations[i].name) == 0) + { + ppd->emulations[i].stop = string; + string = NULL; + } + } + else if (strcmp(keyword, "JobPatchFile") == 0) + { + if (ppd->patches == NULL) + { + ppd->patches = string; + string = NULL; + } + else + { + ppd->patches = realloc(ppd->patches, strlen(ppd->patches) + + strlen(string) + 1); + + strcpy(ppd->patches + strlen(ppd->patches), string); + } + } + else if (strcmp(keyword, "OpenUI") == 0) + { + /* + * Add an option record to the current sub-group, group, or file... + */ + + if (name[0] == '*') + strcpy(name, name + 1); + + if (string == NULL) + { + ppdClose(ppd); + return (NULL); + } + + if (subgroup != NULL) + option = ppd_get_option(subgroup, name); + else + { + if (group == NULL) + { + if (strcmp(name, "Collate") != 0 && + strcmp(name, "Duplex") != 0 && + strcmp(name, "InputSlot") != 0 && + strcmp(name, "ManualFeed") != 0 && + strcmp(name, "MediaType") != 0 && + strcmp(name, "MediaColor") != 0 && + strcmp(name, "MediaWeight") != 0 && + strcmp(name, "OutputBin") != 0 && + strcmp(name, "OutputMode") != 0 && + strcmp(name, "OutputOrder") != 0 && + strcmp(name, "PageSize") != 0 && + strcmp(name, "PageRegion") != 0) + group = ppd_get_group(ppd, "Printer"); + else + group = ppd_get_group(ppd, "General"); + + if (group == NULL) + { + ppdClose(ppd); + free(string); + return (NULL); + } + + option = ppd_get_option(group, name); + group = NULL; + } + else + option = ppd_get_option(group, name); + group = NULL; + } + + if (option == NULL) + { + ppdClose(ppd); + free(string); + return (NULL); + } + + /* + * Now fill in the initial information for the option... + */ + + if (strcmp(string, "PickMany") == 0) + option->ui = PPD_UI_PICKMANY; + else if (strcmp(string, "Boolean") == 0) + option->ui = PPD_UI_BOOLEAN; + else + option->ui = PPD_UI_PICKONE; + + strcpy(option->text, text); + + option->section = PPD_ORDER_ANY; + } + else if (strcmp(keyword, "JCLOpenUI") == 0) + { + /* + * Find the JCL group, and add if needed... + */ + + if (group != NULL) + { + ppdClose(ppd); + free(string); + return (NULL); + } + + group = ppd_get_group(ppd, "JCL"); + + if (group == NULL) + { + ppdClose(ppd); + free(string); + return (NULL); + } + + /* + * Add an option record to the current JCLs... + */ + + if (name[0] == '*') + strcpy(name, name + 1); + + option = ppd_get_option(group, name); + + if (option == NULL) + { + ppdClose(ppd); + free(string); + return (NULL); + } + + /* + * Now fill in the initial information for the option... + */ + + if (strcmp(string, "PickMany") == 0) + option->ui = PPD_UI_PICKMANY; + else if (strcmp(string, "Boolean") == 0) + option->ui = PPD_UI_BOOLEAN; + else + option->ui = PPD_UI_PICKONE; + + strcpy(option->text, text); + + option->section = PPD_ORDER_JCL; + group = NULL; + } + else if (strcmp(keyword, "CloseUI") == 0 || + strcmp(keyword, "JCLCloseUI") == 0) + option = NULL; + else if (strcmp(keyword, "OpenGroup") == 0) + { + /* + * Open a new group... + */ + + if (group != NULL) + { + ppdClose(ppd); + free(string); + return (NULL); + } + + if (strchr(string, '/') != NULL) /* Just show human readable text */ + strcpy(string, strchr(string, '/') + 1); + + group = ppd_get_group(ppd, string); + } + else if (strcmp(keyword, "CloseGroup") == 0) + group = NULL; + else if (strcmp(keyword, "OpenSubGroup") == 0) + { + /* + * Open a new sub-group... + */ + + if (group == NULL || subgroup != NULL) + { + ppdClose(ppd); + free(string); + return (NULL); + } + + if (group->num_subgroups == 0) + subgroup = malloc(sizeof(ppd_group_t)); + else + subgroup = realloc(group->subgroups, + (group->num_subgroups + 1) * sizeof(ppd_group_t)); + + if (subgroup == NULL) + { + ppdClose(ppd); + free(string); + return (NULL); + } + + group->subgroups = subgroup; + subgroup += group->num_subgroups; + group->num_subgroups ++; + + memset(subgroup, 0, sizeof(ppd_group_t)); + strcpy(subgroup->text, string); + } + else if (strcmp(keyword, "CloseSubGroup") == 0) + subgroup = NULL; + else if (strcmp(keyword, "OrderDependency") == 0 || + strcmp(keyword, "NonUIOrderDependency") == 0) + { + if (sscanf(string, "%f%s%s", &order, name, keyword) != 3) + { + ppdClose(ppd); + free(string); + return (NULL); + } + + if (keyword[0] == '*') + strcpy(keyword, keyword + 1); + + if (strcmp(name, "ExitServer") == 0) + section = PPD_ORDER_EXIT; + else if (strcmp(name, "Prolog") == 0) + section = PPD_ORDER_PROLOG; + else if (strcmp(name, "DocumentSetup") == 0) + section = PPD_ORDER_DOCUMENT; + else if (strcmp(name, "PageSetup") == 0) + section = PPD_ORDER_PAGE; + else if (strcmp(name, "JCLSetup") == 0) + section = PPD_ORDER_JCL; + else + section = PPD_ORDER_ANY; + + if (option == NULL) + { + /* + * Only valid for Non-UI options... + */ + + for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++) + if (group->text[0] == '\0') + break; + + if (i > 0) + for (i = 0; i < group->num_options; i ++) + if (strcmp(keyword, group->options[i].keyword) == 0) + { + group->options[i].section = section; + group->options[i].order = order; + break; + } + + group = NULL; + } + else + { + option->section = section; + option->order = order; + } + } + else if (strncmp(keyword, "Default", 7) == 0) + { + if (strchr(string, '/') != NULL) + *strchr(string, '/') = '\0'; + + if (option == NULL) + { + /* + * Only valid for Non-UI options... + */ + + for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++) + if (group->text[0] == '\0') + break; + + if (i > 0) + for (i = 0; i < group->num_options; i ++) + if (strcmp(keyword, group->options[i].keyword) == 0) + { + strcpy(group->options[i].defchoice, string); + break; + } + + group = NULL; + } + else + strcpy(option->defchoice, string); + } + else if (strcmp(keyword, "UIConstraints") == 0 || + strcmp(keyword, "NonUIConstraints") == 0) + { + if (ppd->num_consts == 0) + constraint = calloc(sizeof(ppd_const_t), 1); + else + constraint = realloc(ppd->consts, + (ppd->num_consts + 1) * sizeof(ppd_const_t)); + + if (constraint == NULL) + { + ppdClose(ppd); + free(string); + return (NULL); + } + + ppd->consts = constraint; + constraint += ppd->num_consts; + ppd->num_consts ++; + + switch (sscanf(string, "%s%s%s%s", constraint->option1, + constraint->choice1, constraint->option2, + constraint->choice2)) + { + case 0 : /* Error */ + case 1 : /* Error */ + ppdClose(ppd); + free(string); + break; + + case 2 : /* Two options... */ + if (constraint->option1[0] == '*') + strcpy(constraint->option1, constraint->option1 + 1); + + if (constraint->choice1[0] == '*') + strcpy(constraint->option2, constraint->choice1 + 1); + else + strcpy(constraint->option2, constraint->choice1); + + constraint->choice1[0] = '\0'; + constraint->choice2[0] = '\0'; + break; + + case 3 : /* Two options, one choice... */ + if (constraint->option1[0] == '*') + strcpy(constraint->option1, constraint->option1 + 1); + + if (constraint->choice1[0] == '*') + { + strcpy(constraint->option2, constraint->choice1 + 1); + constraint->choice1[0] = '\0'; + } + else if (constraint->option2[0] == '*') + strcpy(constraint->option2, constraint->option2 + 1); + + constraint->choice2[0] = '\0'; + break; + + case 4 : /* Two options, two choices... */ + if (constraint->option1[0] == '*') + strcpy(constraint->option1, constraint->option1 + 1); + + if (constraint->option2[0] == '*') + strcpy(constraint->option2, constraint->option2 + 1); + break; + } + } + else if (strcmp(keyword, "PaperDimension") == 0) + { + if ((size = ppdPageSize(ppd, name)) != NULL) + sscanf(string, "%f%f", &(size->width), &(size->length)); + } + else if (strcmp(keyword, "ImageableArea") == 0) + { + if ((size = ppdPageSize(ppd, name)) != NULL) + sscanf(string, "%f%f%f%f", &(size->left), &(size->bottom), + &(size->right), &(size->top)); + } + else if (option != NULL && + (mask & (PPD_KEYWORD | PPD_OPTION | PPD_STRING)) == + (PPD_KEYWORD | PPD_OPTION | PPD_STRING)) + { + if (strcmp(keyword, "PageSize") == 0) + { + /* + * Add a page size... + */ + + ppd_add_size(ppd, name); + } + + /* + * Add the option choice... + */ + + choice = ppd_add_choice(option, name); + + if (mask & PPD_TEXT) + strcpy(choice->text, text); + else if (strcmp(name, "True") == 0) + strcpy(choice->text, "Yes"); + else if (strcmp(name, "False") == 0) + strcpy(choice->text, "No"); + else + strcpy(choice->text, name); + + if (strncmp(keyword, "JCL", 3) == 0) + ppd_decode(string); /* Decode quoted string */ + + choice->code = string; + string = NULL; /* Don't free this string below */ + } + + if (string != NULL) + free(string); + } + +#ifdef DEBUG + if (!feof(fp)) + printf("Premature EOF at %d...\n", ftell(fp)); +#endif /* DEBUG */ + + /* + * Set the option back-pointer for each choice... + */ + + for (i = ppd->num_groups, group = ppd->groups; + i > 0; + i --, group ++) + { + for (j = group->num_options, option = group->options; + j > 0; + j --, option ++) + for (k = 0; k < option->num_choices; k ++) + option->choices[k].option = (void *)option; + + for (j = group->num_subgroups, subgroup = group->subgroups; + j > 0; + j --, subgroup ++) + for (k = group->num_options, option = group->options; + k > 0; + k --, option ++) + for (m = 0; m < option->num_choices; m ++) + option->choices[m].option = (void *)option; + } + + return (ppd); +} + + +/* + * 'ppdOpenFd()' - Read a PPD file into memory. + */ + +ppd_file_t * /* O - PPD file record */ +ppdOpenFd(int fd) /* I - File to read from */ +{ + FILE *fp; /* File pointer */ + ppd_file_t *ppd; /* PPD file record */ + + + /* + * Range check input... + */ + + if (fd < 0) + return (NULL); + + /* + * Try to open the file and parse it... + */ + + if ((fp = fdopen(fd, "r")) != NULL) + { + setbuf(fp, NULL); + + ppd = ppdOpen(fp); + + free(fp); + } + else + ppd = NULL; + + return (ppd); +} + + +/* + * 'ppdOpenFile()' - Read a PPD file into memory. + */ + +ppd_file_t * /* O - PPD file record */ +ppdOpenFile(char *filename) /* I - File to read from */ +{ + FILE *fp; /* File pointer */ + ppd_file_t *ppd; /* PPD file record */ + + + /* + * Range check input... + */ + + if (filename == NULL) + return (NULL); + + /* + * Try to open the file and parse it... + */ + + if ((fp = fopen(filename, "r")) != NULL) + { + ppd = ppdOpen(fp); + + fclose(fp); + } + else + ppd = NULL; + + return (ppd); +} + + +/* + * 'ppd_read()' - Read a line from a PPD file, skipping comment lines as + * necessary. + */ + +static int /* O - Bitmask of fields read */ +ppd_read(FILE *fp, /* I - File to read from */ + char *keyword, /* O - Keyword from line */ + char *option, /* O - Option from line */ + char *text, /* O - Human-readable text from line */ + char **string) /* O - Code/string data */ +{ + int ch, /* Character from file */ + endquote, /* Waiting for an end quote */ + mask; /* Mask to be returned */ + char *keyptr, /* Keyword pointer */ + *optptr, /* Option pointer */ + *textptr, /* Text pointer */ + *strptr, /* Pointer into string */ + *lineptr, /* Current position in line buffer */ + line[262144]; /* Line buffer (256k) */ + + + /* + * Range check everything... + */ + + if (fp == NULL || keyword == NULL || option == NULL || text == NULL || + string == NULL) + return (0); + + /* + * Now loop until we have a valid line... + */ + + do + { + /* + * Read the line... + */ + + lineptr = line; + endquote = 0; + + while ((ch = getc(fp)) != EOF && + (lineptr - line) < (sizeof(line) - 1)) + { + if (ch == '\r' || ch == '\n') + { + /* + * Line feed or carriage return... + */ + + if (lineptr == line) /* Skip blank lines */ + continue; + + if (ch == '\r') + { + /* + * Check for a trailing line feed... + */ + + if ((ch = getc(fp)) == EOF) + break; + if (ch != 0x0a) + ungetc(ch, fp); + } + + *lineptr++ = '\n'; + + if (!endquote) /* Continue for multi-line text */ + break; + } + else + { + /* + * Any other character... + */ + + *lineptr++ = ch; + + if (ch == '\"') + endquote = !endquote; + } + } + + if (lineptr > line && lineptr[-1] == '\n') + lineptr --; + + *lineptr = '\0'; + + if (ch == EOF && lineptr == line) + return (0); + + /* + * Now parse it... + */ + + mask = 0; + lineptr = line + 1; + + keyword[0] = '\0'; + option[0] = '\0'; + text[0] = '\0'; + *string = NULL; + + if (line[0] != '*') /* All lines start with an asterisk */ + continue; + + if (strncmp(line, "*%", 2) == 0 || /* Comment line */ + strncmp(line, "*?", 2) == 0 || /* Query line */ + strcmp(line, "*End") == 0) /* End of multi-line string */ + continue; + + /* + * Get a keyword... + */ + + keyptr = keyword; + + while (*lineptr != '\0' && *lineptr != ':' && !isspace(*lineptr) && + (keyptr - keyword) < 40) + *keyptr++ = *lineptr++; + + *keyptr = '\0'; + mask |= PPD_KEYWORD; + + if (*lineptr == ' ' || *lineptr == '\t') + { + /* + * Get an option name... + */ + + while (*lineptr == ' ' || *lineptr == '\t') + lineptr ++; + + optptr = option; + + while (*lineptr != '\0' && *lineptr != '\n' && *lineptr != ':' && + *lineptr != '/' && (optptr - option) < 40) + *optptr++ = *lineptr++; + + *optptr = '\0'; + mask |= PPD_OPTION; + + if (*lineptr == '/') + { + /* + * Get human-readable text... + */ + + lineptr ++; + + textptr = text; + + while (*lineptr != '\0' && *lineptr != '\n' && *lineptr != ':' && + (textptr - text) < 80) + *textptr++ = *lineptr++; + + *textptr = '\0'; + ppd_decode(text); + + mask |= PPD_TEXT; + } + } + + if (*lineptr == ':') + { + /* + * Get string... + */ + + *string = malloc(strlen(lineptr) + 1); + + while (*lineptr == ':' || isspace(*lineptr)) + lineptr ++; + + strptr = *string; + + while (*lineptr != '\0') + { + if (*lineptr != '\"') + *strptr++ = *lineptr++; + else + lineptr ++; + } + + *strptr = '\0'; + + mask |= PPD_STRING; + } + } + while (mask == 0); + + return (mask); +} + + +/* + * 'ppd_decode()' - Decode a string value... + */ + +static void +ppd_decode(char *string) /* I - String to decode */ +{ + char *inptr, /* Input pointer */ + *outptr; /* Output pointer */ + + + inptr = string; + outptr = string; + + while (*inptr != '\0') + if (*inptr == '<' && isxdigit(inptr[1])) + { + /* + * Convert hex to 8-bit values... + */ + + inptr ++; + while (isxdigit(*inptr)) + { + if (isalpha(*inptr)) + *outptr = (tolower(*inptr) - 'a' + 10) << 4; + else + *outptr = (*inptr - '0') << 4; + + inptr ++; + + if (isalpha(*inptr)) + *outptr |= tolower(*inptr) - 'a' + 10; + else + *outptr |= *inptr - '0'; + + inptr ++; + outptr ++; + } + + while (*inptr != '>' && *inptr != '\0') + inptr ++; + while (*inptr == '>') + inptr ++; + } + else + *outptr++ = *inptr++; + + *outptr = '\0'; +} + + + + +/* + * End of "$Id$". + */ diff --git a/cups/ppd.h b/cups/ppd.h new file mode 100644 index 0000000000..fea81f209f --- /dev/null +++ b/cups/ppd.h @@ -0,0 +1,236 @@ +/* + * "$Id$" + * + * PostScript Printer Description definitions for the Common UNIX Printing + * System (CUPS). + * + * Copyright 1997-1999 by Easy Software Products, all rights reserved. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * PostScript is a trademark of Adobe Systems, Inc. + * + * This code and any derivative of it may be used and distributed + * freely under the terms of the GNU General Public License when + * used with GNU Ghostscript or its derivatives. Use of the code + * (or any derivative of it) with software other than GNU + * GhostScript (or its derivatives) is governed by the CUPS license + * agreement. + */ + +#ifndef _CUPS_PPD_H_ +# define _CUPS_PPD_H_ + +/* + * Include necessary headers... + */ + +# include + + +/* + * C++ magic... + */ + +# ifdef __cplusplus +extern "C" { +# endif /* __cplusplus */ + + +/* + * PPD version... + */ + +# define PPD_VERSION 4.3 /* Kept in sync with Adobe version number */ + + +/* + * Types and structures... + */ + +typedef enum /**** UI types ****/ +{ + PPD_UI_BOOLEAN, /* True or False option */ + PPD_UI_PICKONE, /* Pick one from a list */ + PPD_UI_PICKMANY /* Pick zero or more from a list */ +} ppd_ui_t; + +typedef enum /**** Order dependency sections ****/ +{ + PPD_ORDER_ANY, /* Option code can be anywhere in the file */ + PPD_ORDER_DOCUMENT, /* ... must be in the DocumentSetup section */ + PPD_ORDER_EXIT, /* ... must be sent prior to the document */ + PPD_ORDER_JCL, /* ... must be sent as a JCL command */ + PPD_ORDER_PAGE, /* ... must be in the PageSetup section */ + PPD_ORDER_PROLOG /* ... must be in the Prolog section */ +} ppd_section_t; + +typedef enum /**** Colorspaces ****/ +{ + PPD_CS_CMYK = -4, /* CMYK colorspace */ + PPD_CS_CMY, /* CMY colorspace */ + PPD_CS_GRAY = 1, /* Grayscale colorspace */ + PPD_CS_RGB = 3, /* RGB colorspace */ + PPD_CS_RGBK, /* RGBK (K = gray) colorspace */ + PPD_CS_N /* DeviceN colorspace */ +} ppd_cs_t; + +typedef struct /**** Option choices ****/ +{ + char marked, /* 0 if not selected, 1 otherwise */ + choice[41], /* Computer-readable option name */ + text[81], /* Human-readable option name */ + *code; /* Code to send for this option */ + void *option; /* Pointer to parent option structure */ +} ppd_choice_t; + +typedef struct /**** Options ****/ +{ + char conflicted, /* 0 if no conflicts exist, 1 otherwise */ + keyword[41], /* Option keyword name ("PageSize", etc.) */ + defchoice[41], /* Default option choice */ + text[81]; /* Human-readable text */ + ppd_ui_t ui; /* Type of UI option */ + ppd_section_t section; /* Section for command */ + float order; /* Order number */ + int num_choices; /* Number of option choices */ + ppd_choice_t *choices; /* Option choices */ +} ppd_option_t; + +typedef struct ppd_group_str /**** Groups ****/ +{ + char text[81]; /* Human-readable group name */ + int num_options; /* Number of options */ + ppd_option_t *options; /* Options */ + int num_subgroups; /* Number of sub-groups */ + struct ppd_group_str *subgroups; + /* Sub-groups (max depth = 1) */ +} ppd_group_t; + +typedef struct /**** Constraints ****/ +{ + char option1[41], /* First keyword */ + choice1[41], /* First option/choice (blank for all) */ + option2[41], /* Second keyword */ + choice2[41]; /* Second option/choice (blank for all) */ +} ppd_const_t; + +typedef struct /**** Page Sizes ****/ +{ + int marked; /* Page size selected? */ + char name[41]; /* Media size option */ + float width, /* Width of media in points */ + length, /* Length of media in points */ + left, /* Left printable margin in points */ + bottom, /* Bottom printable margin in points */ + right, /* Right printable margin in points */ + top; /* Top printable margin in points */ +} ppd_size_t; + +typedef struct /**** Emulators ****/ +{ + char name[41], /* Emulator name */ + *start, /* Code to switch to this emulation */ + *stop; /* Code to stop this emulation */ +} ppd_emul_t; + +typedef struct /**** sRGB Color Profiles ****/ +{ + char resolution[41], /* Resolution or "-" */ + media_type[41]; /* Media type of "-" */ + float density, /* Ink density to use */ + matrix[3][3]; /* Transform matrix */ +} ppd_profile_t; + +typedef struct /**** Files ****/ +{ + int language_level, /* Language level of device */ + color_device, /* 1 = color device, 0 = grayscale */ + variable_sizes, /* 1 = supports variable sizes, 0 = doesn't */ + accurate_screens,/* 1 = supports accurate screens, 0 = not */ + contone_only, /* 1 = continuous tone only, 0 = not */ + landscape, /* -90 or 90 */ + model_number, /* Device-specific model number */ + manual_copies; /* 1 = Copies done manually, 0 = hardware */ + ppd_cs_t colorspace; /* Default colorspace */ + char *patches; /* Patch commands to be sent to printer */ + int num_emulations; /* Number of emulations supported */ + ppd_emul_t *emulations; /* Emulations and the code to invoke them */ + char *jcl_begin, /* Start JCL commands */ + *jcl_ps, /* Enter PostScript interpreter */ + *jcl_end, /* End JCL commands */ + *lang_encoding, /* Language encoding */ + *lang_version, /* Language version (English, Spanish, etc.) */ + *modelname, /* Model name (general) */ + *ttrasterizer, /* Truetype rasterizer */ + *manufacturer, /* Manufacturer name */ + *product, /* Product name (from PS RIP/interpreter) */ + *nickname, /* Nickname (specific) */ + *shortnickname; /* Short version of nickname */ + int num_groups; /* Number of UI groups */ + ppd_group_t *groups; /* UI groups */ + int num_sizes; /* Number of page sizes */ + ppd_size_t *sizes; /* Page sizes */ + float custom_min[2], /* Minimum variable page size */ + custom_max[2], /* Maximum variable page size */ + custom_margins[4];/* Margins around page */ + int num_consts; /* Number of UI/Non-UI constraints */ + ppd_const_t *consts; /* UI/Non-UI constraints */ + int num_fonts; /* Number of pre-loaded fonts */ + char **fonts; /* Pre-loaded fonts */ + int num_profiles; /* Number of sRGB color profiles */ + ppd_profile_t *profiles; /* sRGB color profiles */ +} ppd_file_t; + + +/* + * Prototypes... + */ + +extern void ppdClose(ppd_file_t *ppd); +extern int ppdConflicts(ppd_file_t *ppd); +extern int ppdEmit(ppd_file_t *ppd, FILE *fp, + ppd_section_t section); +extern int ppdEmitFd(ppd_file_t *ppd, int fd, + ppd_section_t section); +extern int ppdIsMarked(ppd_file_t *ppd, char *keyword, + char *option); +extern void ppdMarkDefaults(ppd_file_t *ppd); +extern int ppdMarkOption(ppd_file_t *ppd, char *keyword, + char *option); +extern ppd_choice_t *ppdFindChoice(ppd_option_t *o, char *option); +extern ppd_choice_t *ppdFindMarkedChoice(ppd_file_t *ppd, char *keyword); +extern ppd_option_t *ppdFindOption(ppd_file_t *ppd, char *keyword); +extern ppd_file_t *ppdOpen(FILE *fp); +extern ppd_file_t *ppdOpenFd(int fd); +extern ppd_file_t *ppdOpenFile(char *filename); +extern float ppdPageLength(ppd_file_t *ppd, char *name); +extern ppd_size_t *ppdPageSize(ppd_file_t *ppd, char *name); +extern float ppdPageWidth(ppd_file_t *ppd, char *name); + +/* + * C++ magic... + */ + +# ifdef __cplusplus +} +# endif /* __cplusplus */ +#endif /* !_CUPS_PPD_H_ */ + +/* + * End of "$Id$". + */ diff --git a/cups/raster.c b/cups/raster.c new file mode 100644 index 0000000000..665472fdfd --- /dev/null +++ b/cups/raster.c @@ -0,0 +1,252 @@ +/* + * "$Id$" + * + * Raster file routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights for the CUPS Raster source + * files are outlined in the GNU Library General Public License, located + * in the "pstoraster" directory. If this file is missing or damaged + * please contact Easy Software Products at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * This code and any derivative of it may be used and distributed + * freely under the terms of the GNU General Public License when + * used with GNU Ghostscript or its derivatives. Use of the code + * (or any derivative of it) with software other than GNU + * GhostScript (or its derivatives) is governed by the CUPS license + * agreement. + * + * Contents: + * + * cupsRasterClose() - Close a raster stream. + * cupsRasterOpen() - Open a raster stream. + * cupsRasterReadHeader() - Read a raster page header. + * cupsRasterReadPixels() - Read raster pixels. + * cupsRasterWriteHeader() - Write a raster page header. + * cupsRasterWritePixels() - Write raster pixels. + */ + +/* + * Include necessary headers... + */ + +#include "raster.h" +#include +#include +#include + +#if defined(WIN32) || defined(__EMX__) +# include +#else +# include +#endif /* WIN32 || __EMX__ */ + + +/* + * 'cupsRasterClose()' - Close a raster stream. + */ + +void +cupsRasterClose(cups_raster_t *r) /* I - Stream to close */ +{ + if (r != NULL) + free(r); +} + + +/* + * 'cupsRasterOpen()' - Open a raster stream. + */ + +cups_raster_t * /* O - New stream */ +cupsRasterOpen(int fd, /* I - File descriptor */ + cups_mode_t mode) /* I - Mode */ +{ + cups_raster_t *r; /* New stream */ + + + if ((r = calloc(sizeof(cups_raster_t), 1)) == NULL) + return (NULL); + + r->fd = fd; + r->mode = mode; + + if (mode == CUPS_RASTER_READ) + { + /* + * Open for read - get sync word... + */ + + if (read(fd, &(r->sync), sizeof(r->sync)) < sizeof(r->sync)) + { + free(r); + return (NULL); + } + + if (r->sync != CUPS_RASTER_SYNC && + r->sync != CUPS_RASTER_REVSYNC) + { + free(r); + return (NULL); + } + } + else + { + /* + * Open for write - put sync word... + */ + + r->sync = CUPS_RASTER_SYNC; + if (write(fd, &(r->sync), sizeof(r->sync)) < sizeof(r->sync)) + { + free(r); + return (NULL); + } + } + + return (r); +} + + +/* + * 'cupsRasterReadHeader()' - Read a raster page header. + */ + +unsigned /* O - 1 on success, 0 on fail */ +cupsRasterReadHeader(cups_raster_t *r, /* I - Raster stream */ + cups_page_header_t *h) /* I - Pointer to header data */ +{ + int len; /* Number of words to swap */ + union swap_s /* Swapping structure */ + { + unsigned char b[4]; + unsigned v; + } *s; + + + if (r == NULL || r->mode != CUPS_RASTER_READ) + return (0); + + if (cupsRasterReadPixels(r, (unsigned char *)h, sizeof(cups_page_header_t)) < + sizeof(cups_page_header_t)) + return (0); + + if (r->sync == CUPS_RASTER_REVSYNC) + for (len = (sizeof(cups_page_header_t) - 256) / 4, + s = (union swap_s *)&(h->AdvanceDistance); + len > 0; + len --, s ++) + s->v = (((((s->b[3] << 8) | s->b[2]) << 8) | s->b[1]) << 8) | s->b[0]; + + return (1); +} + + +/* + * 'cupsRasterReadPixels()' - Read raster pixels. + */ + +unsigned /* O - Number of bytes read */ +cupsRasterReadPixels(cups_raster_t *r, /* I - Raster stream */ + unsigned char *p, /* I - Pointer to pixel buffer */ + unsigned len) /* I - Number of bytes to read */ +{ + int bytes; /* Bytes read */ + unsigned remaining; /* Bytes remaining */ + + + if (r == NULL || r->mode != CUPS_RASTER_READ) + return (0); + + remaining = len; + + while (remaining > 0) + { + bytes = read(r->fd, p, remaining); + + if (bytes <= 0) + { + if (errno != EAGAIN && errno != EINTR) + return (0); + else + continue; + } + + remaining -= bytes; + p += bytes; + } + + return (len); +} + + +/* + * 'cupsRasterWriteHeader()' - Write a raster page header. + */ + +unsigned +cupsRasterWriteHeader(cups_raster_t *r, + cups_page_header_t *h) +{ + if (r == NULL || r->mode != CUPS_RASTER_WRITE) + return (0); + + return (cupsRasterWritePixels(r, (unsigned char *)h, + sizeof(cups_page_header_t)) == + sizeof(cups_page_header_t)); +} + + +/* + * 'cupsRasterWritePixels()' - Write raster pixels. + */ + +unsigned /* O - Number of bytes written */ +cupsRasterWritePixels(cups_raster_t *r, /* I - Raster stream */ + unsigned char *p, /* I - Bytes to write */ + unsigned len)/* I - Number of bytes to write */ +{ + int bytes; /* Bytes read */ + unsigned remaining; /* Bytes remaining */ + + + if (r == NULL || r->mode != CUPS_RASTER_WRITE) + return (0); + + remaining = len; + + while (remaining > 0) + { + bytes = write(r->fd, p, remaining); + + if (bytes <= 0) + { + if (errno != EAGAIN && errno != EINTR) + return (0); + else + continue; + } + + remaining -= bytes; + p += bytes; + } + + return (len); +} + + +/* + * End of "$Id$". + */ diff --git a/cups/raster.h b/cups/raster.h new file mode 100644 index 0000000000..d9227dbdfd --- /dev/null +++ b/cups/raster.h @@ -0,0 +1,228 @@ +/* + * "$Id$" + * + * Raster file definitions for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights for the CUPS Raster source + * files are outlined in the GNU Library General Public License, located + * in the "pstoraster" directory. If this file is missing or damaged + * please contact Easy Software Products at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * This code and any derivative of it may be used and distributed + * freely under the terms of the GNU General Public License when + * used with GNU Ghostscript or its derivatives. Use of the code + * (or any derivative of it) with software other than GNU + * GhostScript (or its derivatives) is governed by the CUPS license + * agreement. + */ + +#ifndef _CUPS_RASTER_H_ +# define _CUPS_RASTER_H_ + +# ifdef __cplusplus +extern "C" { +# endif /* __cplusplus */ + +/* + * Every non-PostScript printer driver that supports raster images should + * use the application/vnd.cups-raster image file format. Since both the + * PostScript RIP (pstoraster, based on GNU Ghostscript 4.03) and Image RIP + * (imagetoraster, located in the filter directory) use it, using this format + * saves you a lot of work. Also, the PostScript RIP passes any printer + * options that are in a PS file to your driver this way as well... + */ + +/* + * Constants... + */ + +# define CUPS_RASTER_SYNC 0x52615374 /* RaSt */ +# define CUPS_RASTER_REVSYNC 0x74536152 /* tSaR */ + + +/* + * Types... + */ + +typedef enum +{ + CUPS_RASTER_READ, /* Open stream for reading */ + CUPS_RASTER_WRITE /* Open stream for writing */ +} cups_mode_t; + +typedef enum +{ + CUPS_FALSE, /* Logical false */ + CUPS_TRUE /* Logical true */ +} cups_bool_t; + +typedef enum +{ + CUPS_JOG_NONE, /* Never move pages */ + CUPS_JOG_FILE, /* Move pages after this file */ + CUPS_JOG_JOB, /* Move pages after this job */ + CUPS_JOG_SET /* Move pages after this set */ +} cups_jog_t; + +typedef enum +{ + CUPS_ORIENT_0, /* Don't rotate the page */ + CUPS_ORIENT_90, /* Rotate the page counter-clockwise */ + CUPS_ORIENT_180, /* Turn the page upside down */ + CUPS_ORIENT_270 /* Rotate the page clockwise */ +} cups_orient_t; + +typedef enum +{ + CUPS_CUT_NONE, /* Never cut the roll */ + CUPS_CUT_FILE, /* Cut the roll after this file */ + CUPS_CUT_JOB, /* Cut the roll after this job */ + CUPS_CUT_SET, /* Cut the roll after this set */ + CUPS_CUT_PAGE /* Cut the roll after this page */ +} cups_cut_t; + +typedef enum +{ + CUPS_ADVANCE_NONE, /* Never advance the roll */ + CUPS_ADVANCE_FILE, /* Advance the roll after this file */ + CUPS_ADVANCE_JOB, /* Advance the roll after this job */ + CUPS_ADVANCE_SET, /* Advance the roll after this set */ + CUPS_ADVANCE_PAGE /* Advance the roll after this page */ +} cups_adv_t; + +typedef enum +{ + CUPS_EDGE_TOP, /* Leading edge is the top of the page */ + CUPS_EDGE_RIGHT, /* Leading edge is the right of the page */ + CUPS_EDGE_BOTTOM, /* Leading edge is the bottom of the page */ + CUPS_EDGE_LEFT /* Leading edge is the left of the page */ +} cups_edge_t; + +typedef enum +{ + CUPS_ORDER_CHUNKED, /* CMYK CMYK CMYK ... */ + CUPS_ORDER_BANDED, /* CCC MMM YYY KKK ... */ + CUPS_ORDER_PLANAR /* CCC ... MMM ... YYY ... KKK ... */ +} cups_order_t; + +typedef enum +{ + CUPS_CSPACE_W, /* Luminance */ + CUPS_CSPACE_RGB, /* Red, green, blue */ + CUPS_CSPACE_RGBA, /* Red, green, blue, alpha */ + CUPS_CSPACE_K, /* Black */ + CUPS_CSPACE_CMY, /* Cyan, magenta, yellow */ + CUPS_CSPACE_YMC, /* Yellow, magenta, cyan */ + CUPS_CSPACE_CMYK, /* Cyan, magenta, yellow, black */ + CUPS_CSPACE_YMCK, /* Yellow, magenta, cyan, black */ + CUPS_CSPACE_KCMY, /* Black, cyan, magenta, yellow */ + CUPS_CSPACE_KCMYcm /* Black, cyan, magenta, yellow, * + * light-cyan, light-magenta */ +} cups_cspace_t; + + +/* + * The page header structure contains the standard PostScript page device + * dictionary, along with some CUPS-specific parameters that are provided + * by the RIPs... + */ + +typedef struct +{ + /**** Standard Page Device Dictionary String Values ****/ + char MediaClass[64]; /* MediaClass string */ + char MediaColor[64]; /* MediaColor string */ + char MediaType[64]; /* MediaType string */ + char OutputType[64]; /* OutputType string */ + + /**** Standard Page Device Dictionary Integer Values ****/ + unsigned AdvanceDistance; /* AdvanceDistance value in points */ + cups_adv_t AdvanceMedia; /* AdvanceMedia value (see above) */ + cups_bool_t Collate; /* Collated copies value */ + cups_cut_t CutMedia; /* CutMedia value (see above) */ + cups_bool_t Duplex; /* Duplexed (double-sided) value */ + unsigned HWResolution[2]; /* Resolution in dots-per-inch */ + unsigned ImagingBoundingBox[4]; /* Pixel region that is painted (points) */ + cups_bool_t InsertSheet; /* InsertSheet value */ + cups_jog_t Jog; /* Jog value (see above) */ + cups_edge_t LeadingEdge; /* LeadingEdge value (see above) */ + unsigned Margins[2]; /* Lower-lefthand margins in points */ + cups_bool_t ManualFeed; /* ManualFeed value */ + unsigned MediaPosition; /* MediaPosition value */ + unsigned MediaWeight; /* MediaWeight value in grams/m^2 */ + cups_bool_t MirrorPrint; /* MirrorPrint value */ + cups_bool_t NegativePrint; /* NegativePrint value */ + unsigned NumCopies; /* Number of copies to produce */ + cups_orient_t Orientation; /* Orientation value (see above) */ + cups_bool_t OutputFaceUp; /* OutputFaceUp value */ + unsigned PageSize[2]; /* Width and length of page in points */ + cups_bool_t Separations; /* Separations value */ + cups_bool_t TraySwitch; /* TraySwitch value */ + cups_bool_t Tumble; /* Tumble value */ + + /**** CUPS Page Device Dictionary Values ****/ + unsigned cupsWidth; /* Width of page image in pixels */ + unsigned cupsHeight; /* Height of page image in pixels */ + unsigned cupsMediaType; /* Media type code */ + unsigned cupsBitsPerColor; /* Number of bits for each color */ + unsigned cupsBitsPerPixel; /* Number of bits for each pixel */ + unsigned cupsBytesPerLine; /* Number of bytes per line */ + cups_order_t cupsColorOrder; /* Order of colors */ + cups_cspace_t cupsColorSpace; /* True colorspace */ + unsigned cupsCompression; /* Device compression to use */ + unsigned cupsRowCount; /* Rows per band */ + unsigned cupsRowFeed; /* Feed between bands */ + unsigned cupsRowStep; /* Spacing between lines */ +} cups_page_header_t; + + +/* + * The raster structure maintains information about a raster data + * stream... + */ + +typedef struct +{ + unsigned sync; /* Sync word from start of stream */ + int fd; /* File descriptor */ + cups_mode_t mode; /* Read/write mode */ +} cups_raster_t; + + +/* + * Prototypes... + */ + +extern void cupsRasterClose(cups_raster_t *r); +extern cups_raster_t *cupsRasterOpen(int fd, cups_mode_t mode); +extern unsigned cupsRasterReadHeader(cups_raster_t *r, + cups_page_header_t *h); +extern unsigned cupsRasterReadPixels(cups_raster_t *r, + unsigned char *p, unsigned len); +extern unsigned cupsRasterWriteHeader(cups_raster_t *r, + cups_page_header_t *h); +extern unsigned cupsRasterWritePixels(cups_raster_t *r, + unsigned char *p, unsigned len); + +# ifdef __cplusplus +} +# endif /* __cplusplus */ + +#endif /* !_CUPS_RASTER_H_ */ + +/* + * End of "$Id$". + */ diff --git a/cups/string.c b/cups/string.c new file mode 100644 index 0000000000..6730e90680 --- /dev/null +++ b/cups/string.c @@ -0,0 +1,125 @@ +/* + * "$Id$" + * + * String functions for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44145 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * strdup() - Duplicate a string. + * strcasecmp() - Do a case-insensitive comparison. + * strncasecmp() - Do a case-insensitive comparison on up to N chars. + */ + +/* + * Include necessary headers... + */ + +#include "string.h" + + +/* + * 'strdup()' - Duplicate a string. + */ + +# ifndef HAVE_STRDUP +char * /* O - New string pointer */ +strdup(const char *s) /* I - String to duplicate */ +{ + char *t; /* New string pointer */ + + + if (s == NULL) + return (NULL); + + if ((t = malloc(strlen(s) + 1)) == NULL) + return (NULL); + + return (strcpy(t, s)); +} +# endif /* !HAVE_STRDUP */ + + +/* + * 'strcasecmp()' - Do a case-insensitive comparison. + */ + +# ifndef HAVE_STRCASECMP +int /* O - Result of comparison (-1, 0, or 1) */ +strcasecmp(const char *s, /* I - First string */ + const char *t) /* I - Second string */ +{ + while (*s != '\0' && *t != '\0') + { + if (tolower(*s) < tolower(*t)) + return (-1); + else if (tolower(*s) > tolower(*t)) + return (1); + + s ++; + t ++; + } + + if (*s == '\0' && *t == '\0') + return (0); + else if (*s != '\0') + return (1); + else + return (-1); +} +# endif /* !HAVE_STRCASECMP */ + +/* + * 'strncasecmp()' - Do a case-insensitive comparison on up to N chars. + */ + +# ifndef HAVE_STRNCASECMP +int /* O - Result of comparison (-1, 0, or 1) */ +strncasecmp(const char *s, /* I - First string */ + const char *t, /* I - Second string */ + size_t n) /* I - Maximum number of characters to compare */ +{ + while (*s != '\0' && *t != '\0' && n > 0) + { + if (tolower(*s) < tolower(*t)) + return (-1); + else if (tolower(*s) > tolower(*t)) + return (1); + + s ++; + t ++; + n --; + } + + if (n == 0) + return (0); + else if (*s == '\0' && *t == '\0') + return (0); + else if (*s != '\0') + return (1); + else + return (-1); +} +# endif /* !HAVE_STRNCASECMP */ + + +/* + * End of "$Id$". + */ diff --git a/cups/string.h b/cups/string.h new file mode 100644 index 0000000000..01dc28368c --- /dev/null +++ b/cups/string.h @@ -0,0 +1,66 @@ +/* + * "$Id$" + * + * String definitions for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44145 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + */ + +#ifndef _CUPS_STRING_H_ +# define _CUPS_STRING_H_ + +/* + * Include necessary headers... + */ + +# include +# include + + +/* + * Stuff for WIN32 and OS/2... + */ + +# if defined(WIN32) || defined(__EMX__) +# define strcasecmp stricmp +# define strncasecmp strnicmp +# endif /* WIN32 || __EMX__ */ + + +/* + * Prototypes... + */ + +# ifndef HAVE_STRDUP +extern char *strdup(const char *); +# endif /* !HAVE_STRDUP */ + +# ifndef HAVE_STRCASECMP +extern int strcasecmp(const char *, const char *); +# endif /* !HAVE_STRCASECMP */ + +# ifndef HAVE_STRNCASECMP +extern int strncasecmp(const char *, const char *, size_t n); +# endif /* !HAVE_STRNCASECMP */ + +#endif /* !_CUPS_STRING_H_ */ + +/* + * End of "$Id$". + */ diff --git a/cups/testhttp.c b/cups/testhttp.c new file mode 100644 index 0000000000..3eb3f20d3d --- /dev/null +++ b/cups/testhttp.c @@ -0,0 +1,109 @@ +/* + * "$Id$" + * + * HTTP test program for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44145 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * main() - Main entry. + */ + +/* + * Include necessary headers... + */ + +#include +#include "http.h" + + +/* + * 'main()' - Main entry. + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line arguments */ + char *argv[]) /* I - Command-line arguments */ +{ + int i; /* Looping var */ + http_t *http; /* HTTP connection */ + http_status_t status; /* Status of GET command */ + char buffer[1024]; /* Input buffer */ + int bytes; /* Number of bytes read */ + FILE *out; /* Output file */ + +#define HOST "dns.easysw.com" +#define PORT 80 + + puts("Connecting to " HOST "..."); + + httpInitialize(); + http = httpConnect(HOST, PORT); + if (http == NULL) + { + puts("Unable to connect to " HOST "!"); + return (1); + } + + puts("Connected to " HOST "..."); + + out = stdout; + + for (i = 1; i < argc; i ++) + { + if (strcmp(argv[i], "-o") == 0) + { + i ++; + out = fopen(argv[i], "wb"); + continue; + } + + printf("Requesting file \"%s\"...\n", argv[i]); + httpClearFields(http); + httpSetField(http, HTTP_FIELD_ACCEPT_LANGUAGE, "en"); + httpGet(http, argv[i]); + status = httpUpdate(http); + + if (status == HTTP_OK) + puts("GET OK:"); + else + printf("GET failed with status %d...\n", status); + + while ((bytes = httpRead(http, buffer, sizeof(buffer))) > 0) + { + fwrite(buffer, bytes, 1, out); + if (out != stdout) + printf("Read %d bytes, %d total...\n", bytes, ftell(out)); + } + } + + puts("Closing connection to server..."); + httpClose(http); + + if (out != stdout) + fclose(out); + + return (0); +} + + +/* + * End of "$Id$". + */ diff --git a/cups/testmime.c b/cups/testmime.c new file mode 100644 index 0000000000..7217bb2a2b --- /dev/null +++ b/cups/testmime.c @@ -0,0 +1,199 @@ +/* + * "$Id$" + * + * MIME test program for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-1999 by Easy Software Products, all rights reserved. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44145 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * main() - Main entry for the test program. + */ + +/* + * Include necessary headers... + */ + +#include +#include "mime.h" + + +/* + * Local functions... + */ + +static void print_rules(mime_magic_t *rules); + + +/* + * 'main()' - Main entry for the test program. + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line args */ + char *argv[]) /* I - Command-line arguments */ +{ + int i; /* Looping var */ + char super[MIME_MAX_SUPER], /* Super-type name */ + type[MIME_MAX_TYPE]; /* Type name */ + mime_t *mime; /* MIME database */ + mime_type_t *src, /* Source type */ + *dst, /* Destination type */ + **types; /* File type array pointer */ + mime_filter_t *filters; /* Filters for the file */ + int num_filters; /* Number of filters for the file */ + + + mime = mimeLoad("../conf"); + + puts("MIME database types:"); + for (i = 0, types = mime->types; i < mime->num_types; i ++, types ++) + { + printf("\t%s/%s: ", (*types)->super, (*types)->type); + print_rules((*types)->rules); + puts(""); + } + + puts(""); + + puts("MIME database filters:"); + for (i = 0, filters = mime->filters; i < mime->num_filters; i ++, filters ++) + printf("\t%s/%s to %s/%s: %s (%d)\n", + filters->src->super, filters->src->type, + filters->dst->super, filters->dst->type, + filters->filter, filters->cost); + + puts(""); + + switch (argc) + { + default : + fputs("Usage: testmime source-file [destination-type]\n", stderr); + return (1); + + case 2 : + src = mimeFileType(mime, argv[1]); + + if (src != NULL) + { + printf("%s: %s/%s\n", argv[1], src->super, src->type); + return (0); + } + else + { + printf("%s: unknown\n", argv[1]); + return (1); + } + + case 3 : + src = mimeFileType(mime, argv[1]); + + sscanf(argv[2], "%[^/]/%s", super, type); + dst = mimeType(mime, super, type); + + filters = mimeFilter(mime, src, dst, &num_filters); + + if (filters == NULL) + { + printf("No filters to convert from %s to %s.\n", argv[1], argv[2]); + return (1); + } + else + { + for (i = 0; i < num_filters; i ++) + if (i < (num_filters - 1)) + printf("%s | ", filters[i].filter); + else + puts(filters[i].filter); + + return (0); + } + } +} + + +/* + * 'print_rules()' - Print the rules for a file type... + */ + +static void +print_rules(mime_magic_t *rules) /* I - Rules to print */ +{ + char logic; /* Logic separator */ + + + if (rules == NULL) + return; + + if (rules->parent == NULL || + rules->parent->op == MIME_MAGIC_OR) + logic = ','; + else + logic = '+'; + + while (rules != NULL) + { + if (rules->prev != NULL) + putchar(logic); + + switch (rules->op) + { + case MIME_MAGIC_MATCH : + printf("match(%s)", rules->value.matchv); + break; + case MIME_MAGIC_LOCALE : + printf("locale(%s)", rules->value.localev); + break; + case MIME_MAGIC_ASCII : + printf("ascii(%d,%d)", rules->offset, rules->length); + break; + case MIME_MAGIC_PRINTABLE : + printf("printable(%d,%d)", rules->offset, rules->length); + break; + case MIME_MAGIC_STRING : + printf("string(%d,%s)", rules->offset, rules->value.stringv); + break; + case MIME_MAGIC_CHAR : + printf("char(%d,%d)", rules->offset, rules->value.charv); + break; + case MIME_MAGIC_SHORT : + printf("short(%d,%d)", rules->offset, rules->value.shortv); + break; + case MIME_MAGIC_INT : + printf("int(%d,%d)", rules->offset, rules->value.intv); + break; + default : + if (rules->child != NULL) + { + putchar('('); + print_rules(rules->child); + putchar(')'); + } + break; + } + + rules = rules->next; + } +} + + + +/* + * End of "$Id$". + */ diff --git a/cups/testmime.dsp b/cups/testmime.dsp new file mode 100644 index 0000000000..d41065c5d9 --- /dev/null +++ b/cups/testmime.dsp @@ -0,0 +1,102 @@ +# Microsoft Developer Studio Project File - Name="testmime" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=testmime - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "testmime.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "testmime.mak" CFG="testmime - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "testmime - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "testmime - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "testmime - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 cups.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"testmime.exe" + +!ELSEIF "$(CFG)" == "testmime - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "testmime___Win32_Debug" +# PROP BASE Intermediate_Dir "testmime___Win32_Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 cupsd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"testmimed.exe" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "testmime - Win32 Release" +# Name "testmime - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\testmime.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\mime.h +# End Source File +# End Group +# End Target +# End Project diff --git a/cups/testppd.c b/cups/testppd.c new file mode 100644 index 0000000000..8195b7e6f0 --- /dev/null +++ b/cups/testppd.c @@ -0,0 +1,183 @@ +/* + * "$Id$" + * + * PPD test program for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-1999 by Easy Software Products, all rights reserved. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44145 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * PostScript is a trademark of Adobe Systems, Inc. + * + * Contents: + * + * main() - Main entry for test program. + */ + +/* + * Include necessary headers... + */ + +#include "cups.h" +#include "string.h" + + +/* + * 'main()' - Main entry for test program. + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line arguments */ + char *argv[]) /* I - Command-line arguments */ +{ + int i, j, k, m, n; /* Looping vars */ + char *filename; /* File to load */ + ppd_file_t *ppd; /* PPD file record */ + ppd_size_t *size; /* Size record */ + ppd_group_t *group; /* UI group */ + ppd_option_t *option; /* Standard UI option */ + ppd_choice_t *choice; /* Standard UI option choice */ + static char *uis[] = { "BOOLEAN", "PICKONE", "PICKMANY" }; + static char *sections[] = { "ANY", "DOCUMENT", "EXIT", + "JCL", "PAGE", "PROLOG" }; + + + /* + * Display PPD files for each file listed on the command-line... + */ + + if (argc == 1) + { + fputs("Usage: ppdtest filename1.ppd [... filenameN.ppd]\n", stderr); + return (1); + } + + for (i = 1; i < argc; i ++) + { + if (strstr(argv[i], ".ppd")) + filename = argv[i]; + else + filename = cupsGetPPD(argv[i]); + + if ((ppd = ppdOpenFile(filename)) == NULL) + { + fprintf(stderr, "Unable to open \'%s\' as a PPD file!\n", filename); + continue; + } + + printf("FILE: %s\n", filename); + printf(" language_level = %d\n", ppd->language_level); + printf(" color_device = %s\n", ppd->color_device ? "TRUE" : "FALSE"); + printf(" variable_sizes = %s\n", ppd->variable_sizes ? "TRUE" : "FALSE"); + printf(" landscape = %d\n", ppd->landscape); + + switch (ppd->colorspace) + { + case PPD_CS_CMYK : + puts(" colorspace = PPD_CS_CMYK"); + break; + case PPD_CS_CMY : + puts(" colorspace = PPD_CS_CMY"); + break; + case PPD_CS_GRAY : + puts(" colorspace = PPD_CS_GRAY"); + break; + case PPD_CS_RGB : + puts(" colorspace = PPD_CS_RGB"); + break; + default : + puts(" colorspace = "); + break; + } + + printf(" num_emulations = %d\n", ppd->num_emulations); + for (j = 0; j < ppd->num_emulations; j ++) + printf(" emulations[%d] = %s\n", j, ppd->emulations[j].name); + + printf(" lang_encoding = %s\n", ppd->lang_encoding); + printf(" lang_version = %s\n", ppd->lang_version); + printf(" modelname = %s\n", ppd->modelname); + printf(" ttrasterizer = %s\n", + ppd->ttrasterizer == NULL ? "None" : ppd->ttrasterizer); + printf(" manufacturer = %s\n", ppd->manufacturer); + printf(" product = %s\n", ppd->product); + printf(" nickname = %s\n", ppd->nickname); + printf(" shortnickname = %s\n", ppd->shortnickname); + printf(" patches = %d bytes\n", + ppd->patches == NULL ? 0 : strlen(ppd->patches)); + + printf(" num_groups = %d\n", ppd->num_groups); + for (j = 0, group = ppd->groups; j < ppd->num_groups; j ++, group ++) + { + printf(" group[%d] = %s\n", j, group->text); + + for (k = 0, option = group->options; k < group->num_options; k ++, option ++) + { + printf(" options[%d] = %s (%s) %s %s %.0f\n", k, + option->keyword, option->text, uis[option->ui], + sections[option->section], option->order); + + if (strcmp(option->keyword, "PageSize") == 0 || + strcmp(option->keyword, "PageRegion") == 0) + { + for (m = option->num_choices, choice = option->choices; + m > 0; + m --, choice ++) + { + size = ppdPageSize(ppd, choice->choice); + + if (size == NULL) + printf(" %s (%s) = ERROR", choice->choice, choice->text); + else + printf(" %s (%s) = %.2fx%.2fin (%.1f,%.1f,%.1f,%.1f)", choice->choice, + choice->text, size->width / 72.0, size->length / 72.0, + size->left / 72.0, size->bottom / 72.0, + size->right / 72.0, size->top / 72.0); + + if (strcmp(option->defchoice, choice->choice) == 0) + puts(" *"); + else + putchar('\n'); + } + } + else + { + for (m = option->num_choices, choice = option->choices; + m > 0; + m --, choice ++) + { + printf(" %s (%s)", choice->choice, choice->text); + + if (strcmp(option->defchoice, choice->choice) == 0) + puts(" *"); + else + putchar('\n'); + } + } + } + } + + ppdClose(ppd); + } + + return (0); +} + + +/* + * End of "$Id$". + */ diff --git a/cups/testppd.dsp b/cups/testppd.dsp new file mode 100644 index 0000000000..18014f7989 --- /dev/null +++ b/cups/testppd.dsp @@ -0,0 +1,102 @@ +# Microsoft Developer Studio Project File - Name="testppd" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=testppd - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "testppd.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "testppd.mak" CFG="testppd - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "testppd - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "testppd - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "testppd - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 cups.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"testppd.exe" + +!ELSEIF "$(CFG)" == "testppd - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "testppd___Win32_Debug" +# PROP BASE Intermediate_Dir "testppd___Win32_Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 cupsd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"testppdd.exe" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "testppd - Win32 Release" +# Name "testppd - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\testppd.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\ppd.h +# End Source File +# End Group +# End Target +# End Project diff --git a/cups/type.c b/cups/type.c new file mode 100644 index 0000000000..f97b2b0be7 --- /dev/null +++ b/cups/type.c @@ -0,0 +1,1011 @@ +/* + * "$Id$" + * + * MIME typing routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-1999 by Easy Software Products, all rights reserved. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44145 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * mimeAddType() - Add a MIME type to a database. + * mimeAddRule() - Add a detection rule for a file type. + * mimeFileType() - Determine the type of a file. + * mimeType() - Lookup a file type. + * compare() - Compare two MIME super/type names. + * checkrules() - Check each rule in a list. + * patmatch() - Pattern matching... + */ + +/* + * Include necessary headers... + */ + +#include +#include +#include +#include + +#include "string.h" +#include "mime.h" + + +/* + * Local functions... + */ + +static int compare(mime_type_t **, mime_type_t **); +static int checkrules(char *, FILE *, mime_magic_t *); +static int patmatch(char *, char *); + + +/* + * 'mimeAddType()' - Add a MIME type to a database. + */ + +mime_type_t * /* O - New (or existing) MIME type */ +mimeAddType(mime_t *mime, /* I - MIME database */ + char *super, /* I - Super-type name */ + char *type) /* I - Type name */ +{ + mime_type_t *temp, /* New MIME type */ + **types; /* New MIME types array */ + + + /* + * Range check input... + */ + + if (mime == NULL || super == NULL || type == NULL) + return (NULL); + + if (strlen(super) > (MIME_MAX_SUPER - 1) || + strlen(type) > (MIME_MAX_TYPE - 1)) + return (NULL); + + /* + * See if the type already exists; if so, return the existing type... + */ + + if ((temp = mimeType(mime, super, type)) != NULL) + return (temp); + + /* + * The type doesn't exist; add it... + */ + + if ((temp = calloc(1, sizeof(mime_type_t))) == NULL) + return (NULL); + + if (mime->num_types == 0) + types = (mime_type_t **)malloc(sizeof(mime_type_t *)); + else + types = (mime_type_t **)realloc(mime->types, sizeof(mime_type_t *) * (mime->num_types + 1)); + + if (types == NULL) + { + free(temp); + return (NULL); + } + + mime->types = types; + types += mime->num_types; + mime->num_types ++; + + *types = temp; + strcpy(temp->super, super); + strcpy(temp->type, type); + + if (mime->num_types > 1) + qsort(mime->types, mime->num_types, sizeof(mime_type_t *), + (int (*)(const void *, const void *))compare); + + return (temp); +} + + +/* + * 'mimeAddRule()' - Add a detection rule for a file type. + */ + +int /* O - 0 on success, -1 on failure */ +mimeAddTypeRule(mime_type_t *mt, /* I - Type to add to */ + char *rule) /* I - Rule to add */ +{ + int num_values, /* Number of values seen */ + op, /* Operation code */ + logic, /* Logic for next rule */ + invert; /* Invert following rule? */ + char name[255], /* Name in rule string */ + value[2][255], /* Value in rule string */ + *ptr, /* Position in name or value */ + quote; /* Quote character */ + int length[2]; /* Length of each parameter */ + mime_magic_t *temp, /* New rule */ + *current; /* Current rule */ + + + /* + * Range check input... + */ + + if (mt == NULL || rule == NULL) + return (-1); + + /* + * Find the last rule in the top-level of the rules tree. + */ + + for (current = mt->rules; current != NULL; current = current->next) + if (current->next == NULL) + break; + + /* + * Parse the rules string. Most rules are either a file extension or a + * comparison function: + * + * extension + * function(parameters) + */ + + logic = MIME_MAGIC_NOP; + invert = 0; + + while (*rule != '\0') + { + while (isspace(*rule)) + rule ++; + + if (*rule == '(') + { + logic = MIME_MAGIC_NOP; + rule ++; + } + else if (*rule == ')') + { + if (current == NULL || current->parent == NULL) + return (-1); + + current = current->parent; + + if (current->parent == NULL) + logic = MIME_MAGIC_OR; + else + logic = current->parent->op; + + rule ++; + } + else if (*rule == '+' && current != NULL) + { + if (logic != MIME_MAGIC_AND && + current != NULL && current->prev != NULL && current->prev->prev != NULL) + { + /* + * OK, we have more than 1 rule in the current tree level... Make a + * new group tree and move the previous rule to it... + */ + + if ((temp = calloc(1, sizeof(mime_magic_t))) == NULL) + return (-1); + + temp->op = MIME_MAGIC_AND; + temp->child = current; + temp->parent = current->parent; + current->prev->next = temp; + temp->prev = current->prev; + + current->prev = NULL; + current->parent = temp; + } + else + current->parent->op = MIME_MAGIC_AND; + + logic = MIME_MAGIC_AND; + rule ++; + } + else if (*rule == ',') + { + if (logic != MIME_MAGIC_OR && current != NULL) + { + /* + * OK, we have two possibilities; either this is the top-level rule or + * we have a bunch of AND rules at this level. + */ + + if (current->parent == NULL) + { + /* + * This is the top-level rule; we have to move *all* of the AND rules + * down a level, as AND has precedence over OR. + */ + + if ((temp = calloc(1, sizeof(mime_magic_t))) == NULL) + return (-1); + + while (current->prev != NULL) + { + current->parent = temp; + current = current->prev; + } + + current->parent = temp; + temp->op = MIME_MAGIC_AND; + temp->child = current; + + mt->rules = current = temp; + } + else + { + /* + * This isn't the top rule, so go up one level... + */ + + current = current->parent; + } + } + + logic = MIME_MAGIC_OR; + rule ++; + } + else if (*rule == '!') + { + invert = 1; + rule ++; + } + else if (isalnum(*rule)) + { + /* + * Read an extension name or a function... + */ + + for (ptr = name; isalnum(*rule) && (ptr - name) < (sizeof(name) - 1);) + *ptr++ = *rule++; + + *ptr = '\0'; + num_values = 0; + + if (*rule == '(') + { + /* + * Read function parameters... + */ + + rule ++; + for (num_values = 0; num_values < 2; num_values ++) + { + ptr = value[num_values]; + + while ((ptr - value[num_values]) < (sizeof(value[0]) - 1) && + *rule != '\0' && *rule != ',' && *rule != ')') + { + if (isspace(*rule)) + { + /* + * Ignore whitespace... + */ + + rule ++; + continue; + } + else if (*rule == '\"' || *rule == '\'') + { + /* + * Copy quoted strings literally... + */ + + quote = *rule++; + + while (*rule != '\0' && *rule != quote) + *ptr++ = *rule++; + + if (*rule == quote) + rule ++; + else + return (-1); + } + else if (*rule == '<') + { + rule ++; + + while (*rule != '>' && *rule != '\0') + { + if (isxdigit(rule[0]) && isxdigit(rule[1])) + { + if (isdigit(*rule)) + *ptr = (*rule++ - '0') << 4; + else + *ptr = (tolower(*rule++) - 'a' + 10) << 4; + + if (isdigit(*rule)) + *ptr++ |= *rule++ - '0'; + else + *ptr++ |= tolower(*rule++) - 'a' + 10; + } + else + return (-1); + } + + if (*rule == '>') + rule ++; + else + return (-1); + } + else + *ptr++ = *rule++; + } + + *ptr = '\0'; + length[num_values] = ptr - value[num_values]; + + if (*rule != ',') + break; + + rule ++; + } + + if (*rule != ')') + return (-1); + + rule ++; + + /* + * Figure out the function... + */ + + if (strcmp(name, "match") == 0) + op = MIME_MAGIC_MATCH; + else if (strcmp(name, "ascii") == 0) + op = MIME_MAGIC_ASCII; + else if (strcmp(name, "printable") == 0) + op = MIME_MAGIC_PRINTABLE; + else if (strcmp(name, "string") == 0) + op = MIME_MAGIC_STRING; + else if (strcmp(name, "char") == 0) + op = MIME_MAGIC_CHAR; + else if (strcmp(name, "short") == 0) + op = MIME_MAGIC_SHORT; + else if (strcmp(name, "int") == 0) + op = MIME_MAGIC_INT; + else if (strcmp(name, "locale") == 0) + op = MIME_MAGIC_LOCALE; + else + return (-1); + } + else + { + /* + * This is just a filename match on the extension... + */ + + sprintf(value[0], "*.%s", name); + length[0] = strlen(value[0]); + num_values = 1; + op = MIME_MAGIC_MATCH; + } + + /* + * Add a rule for this operation. + */ + + if ((temp = calloc(1, sizeof(mime_magic_t))) == NULL) + return (-1); + + temp->invert = invert; + if (current != NULL) + { + temp->parent = current->parent; + current->next = temp; + } + else + mt->rules = temp; + + temp->prev = current; + + if (logic == MIME_MAGIC_NOP) + { + /* + * Add parenthetical grouping... + */ + + temp->op = MIME_MAGIC_OR; + + if ((temp->child = calloc(1, sizeof(mime_magic_t))) == NULL) + return (-1); + + temp->child->parent = temp; + + temp = temp->child; + logic = MIME_MAGIC_OR; + } + + /* + * Fill in data for the rule... + */ + + current = temp; + temp->op = op; + invert = 0; + + switch (op) + { + case MIME_MAGIC_MATCH : + if (length[0] > (sizeof(temp->value.matchv) - 1)) + return (-1); + strcpy(temp->value.matchv, value[0]); + break; + case MIME_MAGIC_ASCII : + case MIME_MAGIC_PRINTABLE : + temp->offset = atoi(value[0]); + temp->length = atoi(value[1]); + if (temp->length > MIME_MAX_BUFFER) + temp->length = MIME_MAX_BUFFER; + break; + case MIME_MAGIC_STRING : + temp->offset = atoi(value[0]); + if (length[1] > sizeof(temp->value.stringv)) + return (-1); + temp->length = length[1]; + memcpy(temp->value.stringv, value[1], length[1]); + break; + case MIME_MAGIC_CHAR : + temp->offset = atoi(value[0]); + if (length[1] == 1) + temp->value.charv = value[1][0]; + else + temp->value.charv = atoi(value[1]); + break; + case MIME_MAGIC_SHORT : + temp->offset = atoi(value[0]); + temp->value.shortv = atoi(value[1]); + break; + case MIME_MAGIC_INT : + temp->offset = atoi(value[0]); + temp->value.intv = atoi(value[1]); + break; + case MIME_MAGIC_LOCALE : + if (length[0] > (sizeof(temp->value.localev) - 1)) + return (-1); + + strcpy(temp->value.localev, value[0]); + break; + } + } + else + break; + } + + return (0); +} + + +/* + * 'mimeFileType()' - Determine the type of a file. + */ + +mime_type_t * /* O - Type of file */ +mimeFileType(mime_t *mime, /* I - MIME database */ + char *pathname) /* I - Name of file to check */ +{ + int i; /* Looping var */ + FILE *fp; /* File pointer */ + mime_type_t **types; /* File types */ + char *filename; /* Base filename of file */ + + + /* + * Range check input parameters... + */ + + if (mime == NULL || pathname == NULL) + return (NULL); + + /* + * Try to open the file... + */ + + if ((fp = fopen(pathname, "r")) == NULL) + return (NULL); + + /* + * Figure out the filename (without directory portion)... + */ + + if ((filename = strrchr(pathname, '/')) != NULL) + filename ++; + else + filename = pathname; + + /* + * Then check it against all known types... + */ + + for (i = mime->num_types, types = mime->types; i > 0; i --, types ++) + if (checkrules(filename, fp, (*types)->rules)) + break; + + /* + * Finally, close the file and return a match (if any)... + */ + + fclose(fp); + + if (i > 0) + return (*types); + else + return (NULL); +} + + +/* + * 'mimeType()' - Lookup a file type. + */ + +mime_type_t * /* O - Matching file type definition */ +mimeType(mime_t *mime, /* I - MIME database */ + char *super, /* I - Super-type name */ + char *type) /* I - Type name */ +{ + mime_type_t key, /* MIME type search key*/ + *keyptr, /* Key pointer... */ + **match; /* Matching pointer */ + + /* + * Range check input... + */ + + if (mime == NULL || super == NULL || type == NULL) + return (NULL); + + if (strlen(super) > (MIME_MAX_SUPER - 1) || + strlen(type) > (MIME_MAX_TYPE - 1)) + return (NULL); + + if (mime->num_types == 0) + return (NULL); + + /* + * Lookup the type in the array... + */ + + strcpy(key.super, super); + strcpy(key.type, type); + keyptr = &key; + + match = (mime_type_t **)bsearch(&keyptr, mime->types, mime->num_types, + sizeof(mime_type_t *), + (int (*)(const void *, const void *))compare); + + if (match == NULL) + return (NULL); + else + return (*match); +} + + +/* + * 'compare()' - Compare two MIME super/type names. + */ + +static int /* O - Result of comparison */ +compare(mime_type_t **t0, /* I - First type */ + mime_type_t **t1) /* I - Second type */ +{ + int i; /* Result of comparison */ + + + if ((i = strcasecmp((*t0)->super, (*t1)->super)) == 0) + i = strcasecmp((*t0)->type, (*t1)->type); + + return (i); +} + + +/* + * 'checkrules()' - Check each rule in a list. + */ + +static int /* O - 1 if match, 0 if no match */ +checkrules(char *filename, /* I - Filename */ + FILE *fp, /* I - File to check */ + mime_magic_t *rules) /* I - Rules to check */ +{ + int n; /* Looping var */ + int logic, /* Logic to apply */ + result, /* Result of test */ + intv; /* Integer value */ + short shortv; /* Short value */ + unsigned char buffer[MIME_MAX_BUFFER],/* Input buffer */ + *bufptr; /* Current buffer position */ + int bufoffset, /* Offset in file for buffer */ + buflength; /* Length of data in buffer */ + + + if (rules == NULL) + return (0); + + if (rules->parent == NULL) + logic = MIME_MAGIC_OR; + else + logic = rules->parent->op; + + bufoffset = -1; + + while (rules != NULL) + { + /* + * Compute the result of this rule... + */ + + switch (rules->op) + { + case MIME_MAGIC_MATCH : + result = patmatch(filename, rules->value.matchv); + break; + + case MIME_MAGIC_ASCII : + /* + * Load the buffer if necessary... + */ + + if (bufoffset < 0 || rules->offset < bufoffset || + (rules->offset + rules->length) > (bufoffset + buflength)) + { + /* + * Reload file buffer... + */ + + fseek(fp, rules->offset, SEEK_SET); + buflength = fread(buffer, 1, sizeof(buffer), fp); + bufoffset = rules->offset; + } + + /* + * Test for ASCII printable characters plus standard control chars. + */ + + if ((rules->offset + rules->length) > (bufoffset + buflength)) + n = bufoffset + buflength - rules->offset; + else + n = rules->length; + + bufptr = buffer + rules->offset - bufoffset; + while (n > 0) + if ((*bufptr >= 32 && *bufptr <= 126) || + (*bufptr >= 8 && *bufptr <= 10) || + *bufptr == 13 || *bufptr == 26) + { + n --; + bufptr ++; + } + else + break; + + result = (n == 0); + break; + + case MIME_MAGIC_PRINTABLE : + /* + * Load the buffer if necessary... + */ + + if (bufoffset < 0 || rules->offset < bufoffset || + (rules->offset + rules->length) > (bufoffset + buflength)) + { + /* + * Reload file buffer... + */ + + fseek(fp, rules->offset, SEEK_SET); + buflength = fread(buffer, 1, sizeof(buffer), fp); + bufoffset = rules->offset; + } + + /* + * Test for ASCII printable characters plus standard control chars. + */ + + if ((rules->offset + rules->length) > (bufoffset + buflength)) + n = bufoffset + buflength - rules->offset; + else + n = rules->length; + + bufptr = buffer + rules->offset - bufoffset; + + while (n > 0) + if ((*bufptr >= 160 && *bufptr <= 254) || + (*bufptr >= 32 && *bufptr <= 126) || + (*bufptr >= 8 && *bufptr <= 10) || + *bufptr == 13 || *bufptr == 26) + { + n --; + bufptr ++; + } + else + break; + + result = (n == 0); + break; + + case MIME_MAGIC_STRING : + /* + * Load the buffer if necessary... + */ + + if (bufoffset < 0 || rules->offset < bufoffset || + (rules->offset + rules->length) > (bufoffset + buflength)) + { + /* + * Reload file buffer... + */ + + fseek(fp, rules->offset, SEEK_SET); + buflength = fread(buffer, 1, sizeof(buffer), fp); + bufoffset = rules->offset; + } + + /* + * Compare the buffer against the string. If the file is too + * short then don't compare - it can't match... + */ + + if ((rules->offset + rules->length) > (bufoffset + buflength)) + result = 0; + else + result = (memcmp(buffer + rules->offset - bufoffset, + rules->value.stringv, rules->length) == 0); + break; + + case MIME_MAGIC_CHAR : + /* + * Load the buffer if necessary... + */ + + if (bufoffset < 0 || rules->offset < bufoffset) + { + /* + * Reload file buffer... + */ + + fseek(fp, rules->offset, SEEK_SET); + buflength = fread(buffer, 1, sizeof(buffer), fp); + bufoffset = rules->offset; + } + + /* + * Compare the character values; if the file is too short, it + * can't match... + */ + + if (buflength < 1) + result = 0; + else + result = (buffer[rules->offset - bufoffset] == rules->value.charv); + break; + + case MIME_MAGIC_SHORT : + /* + * Load the buffer if necessary... + */ + + if (bufoffset < 0 || rules->offset < bufoffset || + (rules->offset + 2) > (bufoffset + buflength)) + { + /* + * Reload file buffer... + */ + + fseek(fp, rules->offset, SEEK_SET); + buflength = fread(buffer, 1, sizeof(buffer), fp); + bufoffset = rules->offset; + } + + /* + * Compare the short values; if the file is too short, it + * can't match... + */ + + if (buflength < 2) + result = 0; + else + { + bufptr = buffer + rules->offset - bufoffset; + shortv = (bufptr[0] << 8) | bufptr[1]; + result = (shortv == rules->value.shortv); + } + break; + + case MIME_MAGIC_INT : + /* + * Load the buffer if necessary... + */ + + if (bufoffset < 0 || rules->offset < bufoffset || + (rules->offset + 4) > (bufoffset + buflength)) + { + /* + * Reload file buffer... + */ + + fseek(fp, rules->offset, SEEK_SET); + buflength = fread(buffer, 1, sizeof(buffer), fp); + bufoffset = rules->offset; + } + + /* + * Compare the int values; if the file is too short, it + * can't match... + */ + + if (buflength < 4) + result = 0; + else + { + bufptr = buffer + rules->offset - bufoffset; + intv = (((((bufptr[0] << 8) | bufptr[1]) << 8) | bufptr[2]) << 8) | + bufptr[3];; + result = (intv == rules->value.intv); + } + break; + + case MIME_MAGIC_LOCALE : + result = (strcmp(rules->value.localev, setlocale(LC_ALL, NULL)) == 0); + break; + + default : + if (rules->child != NULL) + result = checkrules(filename, fp, rules->child); + else + result = 0; + break; + } + + /* + * If the logic is inverted, invert the result... + */ + + if (rules->invert) + result = !result; + + /* + * OK, now if the current logic is OR and this result is true, the this + * rule set is true. If the current logic is AND and this result is false, + * the the rule set is false... + */ + + if ((result && logic == MIME_MAGIC_OR) || + (!result && logic == MIME_MAGIC_AND)) + return (result); + + /* + * Otherwise the jury is still out on this one, so move to the next rule. + */ + + rules = rules->next; + } + + return (result); +} + + +/* + * 'patmatch()' - Pattern matching... + */ + +static int /* O - 1 if match, 0 if no match */ +patmatch(char *s, /* I - String to match against */ + char *pat) /* I - Pattern to match against */ +{ + /* + * Range check the input... + */ + + if (s == NULL || pat == NULL) + return (0); + + /* + * Loop through the pattern and match strings, and stop if we come to a + * point where the strings don't match or we find a complete match. + */ + + while (*s != '\0' && *pat != '\0') + { + if (*pat == '*') + { + /* + * Wildcard - 0 or more characters... + */ + + pat ++; + if (*pat == '\0') + return (1); /* Last pattern char is *, so everything matches now... */ + + /* + * Test all remaining combinations until we get to the end of the string. + */ + + while (*s != '\0') + { + if (patmatch(s, pat)) + return (1); + + s ++; + } + } + else if (*pat == '?') + { + /* + * Wildcard - 1 character... + */ + + pat ++; + s ++; + continue; + } + else if (*pat == '[') + { + /* + * Match a character from the input set [chars]... + */ + + pat ++; + while (*pat != ']' && *pat != '\0') + if (*s == *pat) + break; + else + pat ++; + + if (*pat == ']' || *pat == '\0') + return (0); + + while (*pat != ']' && *pat != '\0') + pat ++; + + if (*pat == ']') + pat ++; + + continue; + } + else if (*pat == '\\') + { + /* + * Handle quoted characters... + */ + + pat ++; + } + + /* + * Stop if the pattern and string don't match... + */ + + if (*pat++ != *s++) + return (0); + } + + /* + * Done parsing the pattern and string; return 1 if the last character matches + * and 0 otherwise... + */ + + return (*s == *pat); +} + + +/* + * End of "$Id$". + */ diff --git a/cups/util.c b/cups/util.c new file mode 100644 index 0000000000..dac143401e --- /dev/null +++ b/cups/util.c @@ -0,0 +1,932 @@ +/* + * "$Id$" + * + * Printing utilities for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44145 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * cupsCancelJob() - Cancel a print job. + * cupsDoRequest() - Do an IPP request... + * cupsGetClasses() - Get a list of printer classes. + * cupsGetDefault() - Get the default printer or class. + * cupsGetPPD() - Get the PPD file for a printer. + * cupsGetPrinters() - Get a list of printers. + * cupsPrintFile() - Print a file to a printer or class. + * cups_connect() - Connect to the specified host... + */ + +/* + * Include necessary headers... + */ + +#include "cups.h" +#include "ipp.h" +#include "language.h" +#include "string.h" +#include "debug.h" +#include +#include +#include +#include +#if defined(WIN32) || defined(__EMX__) +# include +#else +# include +#endif /* WIN32 || __EMX__ */ + + +/* + * Local globals... + */ + +static http_t *cups_server = NULL; + + +/* + * Local functions... + */ + +static char *cups_connect(char *name, char *printer, char *hostname); + + +/* + * 'cupsCancelJob()' - Cancel a print job. + */ + +int /* O - 1 on success, 0 on failure */ +cupsCancelJob(char *name, /* I - Name of printer or class */ + int job) /* I - Job ID */ +{ + char printer[HTTP_MAX_URI], /* Printer name */ + hostname[HTTP_MAX_URI], /* Hostname */ + uri[HTTP_MAX_URI]; /* Printer URI */ + ipp_t *request, /* IPP request */ + *response; /* IPP response */ + cups_lang_t *language; /* Language info */ + + + /* + * See if we can connect to the server... + */ + + if (!cups_connect(name, printer, hostname)) + return (0); + + /* + * Build an IPP_CANCEL_JOB request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + * printer-uri + * job-id + */ + + request = ippNew(); + + request->request.op.operation_id = IPP_CANCEL_JOB; + request->request.op.request_id = 1; + + language = cupsLangDefault(); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, + "attributes-charset", NULL, cupsLangEncoding(language)); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, + "attributes-natural-language", NULL, + language != NULL ? language->language : "C"); + + sprintf(uri, "ipp://%s:%d/printers/%s", hostname, ippPort(), printer); + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", + NULL, uri); + + ippAddInteger(request, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-id", job); + + /* + * Do the request... + */ + + if ((response = cupsDoRequest(cups_server, request, "/jobs/")) == NULL) + return (0); + + ippDelete(response); + return (1); +} + + +/* + * 'cupsDoRequest()' - Do an IPP request... + */ + +ipp_t * /* O - Response data */ +cupsDoRequest(http_t *http, /* I - HTTP connection to server */ + ipp_t *request, /* I - IPP request */ + char *resource) /* I - HTTP resource for POST */ +{ + ipp_t *response; /* IPP response data */ + char length[255]; /* Content-Length field */ + http_status_t status; /* Status of HTTP request */ +#if !defined(WIN32) && !defined(__EMX__) + char *password, /* Password string */ + plain[255], /* Plaintext username:password */ + encode[255]; /* Encoded username:password */ + char junk[8192]; /* Junk buffer for error data */ +#endif /* !WIN32 && !__EMX__ */ + static char authstring[255] = ""; + /* Authorization string */ + + + DEBUG_printf(("cupsDoRequest(%08x, %08s, \'%s\')\n", http, request, resource)); + + /* + * Setup the HTTP variables needed... + */ + + sprintf(length, "%d", ippLength(request)); + httpClearFields(http); + httpSetField(http, HTTP_FIELD_CONTENT_LENGTH, length); + httpSetField(http, HTTP_FIELD_CONTENT_TYPE, "application/ipp"); + httpSetField(http, HTTP_FIELD_AUTHORIZATION, authstring); + + /* + * Try the request... + */ + + if (httpPost(http, resource)) + if (httpPost(http, resource)) + { + ippDelete(request); + return (NULL); + } + + /* + * Send the IPP data and wait for the response... + */ + + ippWrite(http, request); + + if ((status = httpUpdate(http)) == HTTP_UNAUTHORIZED) + { + /* + * Flush any error message... + */ + + httpFlush(http); + +#if !defined(WIN32) && !defined(__EMX__) + if ((password = getpass("Password:")) != NULL) + { + /* + * Got a password; now send it to the server... + */ + + sprintf(plain, "%s:%s", cuserid(NULL), password); + httpEncode64(encode, plain); + sprintf(authstring, "Basic %s", encode); + + httpClearFields(http); + httpSetField(http, HTTP_FIELD_CONTENT_LENGTH, length); + httpSetField(http, HTTP_FIELD_CONTENT_TYPE, "application/ipp"); + httpSetField(http, HTTP_FIELD_AUTHORIZATION, authstring); + + if (httpPost(http, resource)) + httpPost(http, resource); + request->state = IPP_IDLE; + ippWrite(http, request); + status = httpUpdate(http); + } +#endif /* !WIN32 && !__EMX__ */ + } + + if (status != HTTP_OK) + { + /* + * Flush any error message... + */ + + httpFlush(http); + + response = NULL; + } + else + { + /* + * Read the response... + */ + + response = ippNew(); + + if (ippRead(http, response) == IPP_ERROR) + { + ippDelete(response); + response = NULL; + + /* + * Flush any remaining data... + */ + + httpFlush(http); + } + } + + /* + * Delete the original request and return the response... + */ + + ippDelete(request); + + return (response); +} + + +/* + * 'cupsGetClasses()' - Get a list of printer classes. + */ + +int /* O - Number of classes */ +cupsGetClasses(char ***classes) /* O - Classes */ +{ + int n; /* Number of classes */ + ipp_t *request, /* IPP Request */ + *response; /* IPP Response */ + ipp_attribute_t *attr; /* Current attribute */ + cups_lang_t *language; /* Default language */ + + + /* + * Try to connect to the server... + */ + + if (!cups_connect("default", NULL, NULL)) + return (0); + + /* + * Build a CUPS_GET_CLASSES request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + */ + + request = ippNew(); + + request->request.op.operation_id = CUPS_GET_CLASSES; + request->request.op.request_id = 1; + + language = cupsLangDefault(); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, + "attributes-charset", NULL, cupsLangEncoding(language)); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, + "attributes-natural-language", NULL, language->language); + + /* + * Do the request and get back a response... + */ + + n = 0; + *classes = NULL; + + if ((response = cupsDoRequest(cups_server, request, "/classes/")) != NULL) + { + for (attr = response->attrs; attr != NULL; attr = attr->next) + if (strcmp(attr->name, "printer-name") == 0 && + attr->value_tag == IPP_TAG_NAME) + { + if (n == 0) + *classes = malloc(sizeof(char *)); + else + *classes = realloc(*classes, sizeof(char *) * (n + 1)); + + if (*classes == NULL) + { + ippDelete(response); + return (0); + } + + (*classes)[n] = strdup(attr->values[0].string.text); + n ++; + } + + ippDelete(response); + } + + return (n); +} + + +/* + * 'cupsGetDefault()' - Get the default printer or class. + */ + +char * /* O - Default printer or NULL */ +cupsGetDefault(void) +{ + ipp_t *request, /* IPP Request */ + *response; /* IPP Response */ + ipp_attribute_t *attr; /* Current attribute */ + cups_lang_t *language; /* Default language */ + static char def_printer[64];/* Default printer */ + + + /* + * First see if the LPDEST or PRINTER environment variables are + * set... + */ + + if (getenv("LPDEST") != NULL) + return (getenv("LPDEST")); + else if (getenv("PRINTER") != NULL) + return (getenv("PRINTER")); + + /* + * Try to connect to the server... + */ + + if (!cups_connect("default", NULL, NULL)) + return (NULL); + + /* + * Build a CUPS_GET_DEFAULT request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + */ + + request = ippNew(); + + request->request.op.operation_id = CUPS_GET_DEFAULT; + request->request.op.request_id = 1; + + language = cupsLangDefault(); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, + "attributes-charset", NULL, cupsLangEncoding(language)); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, + "attributes-natural-language", NULL, language->language); + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoRequest(cups_server, request, "/printers/")) != NULL) + { + if ((attr = ippFindAttribute(response, "printer-name", IPP_TAG_NAME)) != NULL) + { + strcpy(def_printer, attr->values[0].string.text); + ippDelete(response); + return (def_printer); + } + + ippDelete(response); + } + + return (NULL); +} + + +/* + * 'cupsGetPPD()' - Get the PPD file for a printer. + */ + +char * /* O - Filename for PPD file */ +cupsGetPPD(char *name) /* I - Printer name */ +{ + FILE *fp; /* PPD file */ + int bytes; /* Number of bytes read */ + char buffer[8192]; /* Buffer for file */ + char printer[HTTP_MAX_URI], /* Printer name */ + hostname[HTTP_MAX_URI], /* Hostname */ + resource[HTTP_MAX_URI]; /* Resource name */ + static char filename[HTTP_MAX_URI]; /* Local filename */ + char *tempdir; /* Temporary file directory */ + struct stat fileinfo; /* File information */ + + + /* + * See if we can connect to the server... + */ + + if (!cups_connect(name, printer, hostname)) + return (NULL); + + /* + * Then check for the cache file... + */ + +#if defined(WIN32) || defined(__EMX__) + tempdir = "C:/WINDOWS/TEMP"; +#else + if ((tempdir = getenv("TMPDIR")) == NULL) + tempdir = "/tmp"; +#endif /* WIN32 || __EMX__ */ + + sprintf(filename, "%s/%s.ppd", tempdir, printer); + if (stat(filename, &fileinfo)) + memset(&fileinfo, 0, sizeof(fileinfo)); + + /* + * And send a request to the HTTP server using "if-modified-since"... + */ + + sprintf(resource, "/printers/%s.ppd", printer); + + httpClearFields(cups_server); + httpSetField(cups_server, HTTP_FIELD_HOST, hostname); + httpSetField(cups_server, HTTP_FIELD_IF_MODIFIED_SINCE, + httpGetDateString(fileinfo.st_mtime)); + httpGet(cups_server, resource); + + switch (httpUpdate(cups_server)) + { + case HTTP_OK : /* New file - get it! */ + break; + case HTTP_NOT_MODIFIED : /* File hasn't been modified; use the current copy */ + return (filename); + default : + return (NULL); + } + + /* + * OK, we need to copy the file; open the file and copy it... + */ + + unlink(filename); + if ((fp = fopen(filename, "w")) == NULL) + { + /* + * Can't open file; close the server connection and return NULL... + */ + + httpClose(cups_server); + cups_server = NULL; + return (NULL); + } + + while ((bytes = httpRead(cups_server, buffer, sizeof(buffer))) > 0) + fwrite(buffer, bytes, 1, fp); + + fclose(fp); + + return (filename); +} + + +/* + * 'cupsGetPrinters()' - Get a list of printers. + */ + +int /* O - Number of printers */ +cupsGetPrinters(char ***printers) /* O - Printers */ +{ + int n; /* Number of printers */ + ipp_t *request, /* IPP Request */ + *response; /* IPP Response */ + ipp_attribute_t *attr; /* Current attribute */ + cups_lang_t *language; /* Default language */ + + + /* + * Try to connect to the server... + */ + + if (!cups_connect("default", NULL, NULL)) + return (0); + + /* + * Build a CUPS_GET_PRINTERS request, which requires the following + * attributes: + * + * attributes-charset + * attributes-natural-language + */ + + request = ippNew(); + + request->request.op.operation_id = CUPS_GET_PRINTERS; + request->request.op.request_id = 1; + + language = cupsLangDefault(); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, + "attributes-charset", NULL, cupsLangEncoding(language)); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, + "attributes-natural-language", NULL, language->language); + + /* + * Do the request and get back a response... + */ + + n = 0; + *printers = NULL; + + if ((response = cupsDoRequest(cups_server, request, "/printers/")) != NULL) + { + for (attr = response->attrs; attr != NULL; attr = attr->next) + if (strcmp(attr->name, "printer-name") == 0 && + attr->value_tag == IPP_TAG_NAME) + { + if (n == 0) + *printers = malloc(sizeof(char *)); + else + *printers = realloc(*printers, sizeof(char *) * (n + 1)); + + if (*printers == NULL) + { + ippDelete(response); + return (0); + } + + (*printers)[n] = strdup(attr->values[0].string.text); + n ++; + } + + ippDelete(response); + } + + return (n); +} + + +/* + * 'cupsPrintFile()' - Print a file to a printer or class. + */ + +int /* O - Job ID */ +cupsPrintFile(char *name, /* I - Printer or class name */ + char *filename, /* I - File to print */ + char *title, /* I - Title of job */ + int num_options,/* I - Number of options */ + cups_option_t *options) /* I - Options */ +{ + int i; /* Looping var */ + int n, n2; /* Attribute values */ + char *option, /* Name of option */ + *val, /* Pointer to option value */ + *s; /* Pointer into option value */ + ipp_t *request; /* IPP request */ + ipp_t *response; /* IPP response */ + ipp_attribute_t *attr; /* IPP job-id attribute */ + char hostname[HTTP_MAX_URI], /* Hostname */ + printer[HTTP_MAX_URI], /* Printer or class name */ + uri[HTTP_MAX_URI]; /* Printer URI */ + cups_lang_t *language; /* Language to use */ + struct stat filestats; /* File information */ + FILE *fp; /* File pointer */ + char buffer[8192]; /* Copy buffer */ + int jobid; /* New job ID */ + + + DEBUG_printf(("cupsPrintFile(\'%s\', \'%s\', %d, %08x)\n", + printer, filename, num_options, options)); + + if (name == NULL || filename == NULL) + return (0); + + /* + * See if the file exists and is readable... + */ + + if (stat(filename, &filestats)) + return (0); + + if ((fp = fopen(filename, "rb")) == NULL) + { + DEBUG_puts("cupsPrintFile: Unable to open file!"); + return (0); + } + + /* + * Setup a connection and request data... + */ + + if ((request = ippNew()) == NULL) + { + fclose(fp); + return (0); + } + + if (!cups_connect(name, printer, hostname)) + { + DEBUG_printf(("cupsPrintFile: Unable to open connection - %s.\n", + strerror(errno))); + fclose(fp); + ippDelete(request); + return (0); + } + + /* + * Build a standard CUPS URI for the printer and fill the standard IPP + * attributes... + */ + + request->request.op.operation_id = IPP_PRINT_JOB; + request->request.op.request_id = 1; + + sprintf(uri, "ipp://%s:%d/printers/%s", hostname, ippPort(), printer); + + language = cupsLangDefault(); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, + "attributes-charset", NULL, cupsLangEncoding(language)); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, + "attributes-natural-language", NULL, + language != NULL ? language->language : "C"); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", + NULL, uri); + + /* + * Handle raw print files... + */ + + if (cupsGetOption("raw", num_options, options)) + ippAddString(request, IPP_TAG_JOB, IPP_TAG_MIMETYPE, "document-format", + NULL, "application/vnd.cups-raw"); + else + ippAddString(request, IPP_TAG_JOB, IPP_TAG_MIMETYPE, "document-format", + NULL, "application/octet-stream"); + +#if defined(WIN32) || defined(__EMX__) + ippAddString(request, IPP_TAG_JOB, IPP_TAG_NAME, "requesting-user-name", + NULL, "WindowsUser"); +#else + ippAddString(request, IPP_TAG_JOB, IPP_TAG_NAME, "requesting-user-name", + NULL, cuserid(NULL)); +#endif /* WIN32 || __EMX__ */ + + if (title) + ippAddString(request, IPP_TAG_JOB, IPP_TAG_NAME, "job-name", NULL, title); + + /* + * Then add all options on the command-line... + */ + + for (i = 0; i < num_options; i ++) + { + /* + * Skip the "raw" option - handled above... + */ + + if (strcmp(options[i].name, "raw") == 0) + continue; + + /* + * See what the option value is; for compatibility with older interface + * scripts, we have to support single-argument options as well as + * option=value, option=low-high, and option=MxN. + */ + + option = options[i].name; + val = options[i].value; + + if (*val == '\0') + val = NULL; + + if (val != NULL) + { + if (strcasecmp(val, "true") == 0 || + strcasecmp(val, "on") == 0 || + strcasecmp(val, "yes") == 0) + { + /* + * Boolean value - true... + */ + + n = 1; + val = ""; + } + else if (strcasecmp(val, "false") == 0 || + strcasecmp(val, "off") == 0 || + strcasecmp(val, "no") == 0) + { + /* + * Boolean value - false... + */ + + n = 0; + val = ""; + } + + n = strtol(val, &s, 0); + } + else + { + if (strncmp(option, "no", 2) == 0) + { + option += 2; + n = 0; + } + else + n = 1; + + s = ""; + } + + if (*s != '\0' && *s != '-' && (*s != 'x' || s == val)) + { + /* + * String value(s)... + */ + + DEBUG_printf(("cupsPrintJob: Adding string option \'%s\' with value \'%s\'...\n", + option, val)); + + ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, option, NULL, val); + } + else if (val != NULL) + { + /* + * Numeric value, range, or resolution... + */ + + if (*s == '-') + { + n2 = strtol(s + 1, NULL, 0); + ippAddRange(request, IPP_TAG_JOB, option, n, n2); + + DEBUG_printf(("cupsPrintJob: Adding range option \'%s\' with value %d-%d...\n", + option, n, n2)); + } + else if (*s == 'x') + { + n2 = strtol(s + 1, &s, 0); + + if (strcmp(s, "dpc") == 0) + ippAddResolution(request, IPP_TAG_JOB, option, IPP_RES_PER_CM, n, n2); + else if (strcmp(s, "dpi") == 0) + ippAddResolution(request, IPP_TAG_JOB, option, IPP_RES_PER_INCH, n, n2); + else + ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, option, NULL, val); + + DEBUG_printf(("cupsPrintJob: Adding resolution option \'%s\' with value %s...\n", + option, val)); + } + else + { + ippAddInteger(request, IPP_TAG_JOB, IPP_TAG_INTEGER, option, n); + + DEBUG_printf(("cupsPrintJob: Adding integer option \'%s\' with value %d...\n", + option, n)); + } + } + else + { + /* + * Boolean value... + */ + + DEBUG_printf(("cupsPrintJob: Adding boolean option \'%s\' with value %d...\n", + option, n)); + ippAddBoolean(request, IPP_TAG_JOB, option, (char)n); + } + } + + /* + * Setup the necessary HTTP fields... + */ + + httpClearFields(cups_server); + httpSetField(cups_server, HTTP_FIELD_CONTENT_TYPE, "application/ipp"); + + sprintf(buffer, "%u", (unsigned)(ippLength(request) + filestats.st_size)); + httpSetField(cups_server, HTTP_FIELD_CONTENT_LENGTH, buffer); + + /* + * Finally, issue a POST request for the printer and send the IPP data and + * file. + */ + + sprintf(uri, "/printers/%s", printer); + + response = ippNew(); + + if (httpPost(cups_server, uri)) + { + DEBUG_puts("httpPost() failed."); + jobid = 0; + } + else if (ippWrite(cups_server, request) == IPP_ERROR) + { + DEBUG_puts("ippWrite() failed."); + jobid = 0; + } + else + { + while ((i = fread(buffer, 1, sizeof(buffer), fp)) > 0) + if (httpWrite(cups_server, buffer, i) < i) + { + DEBUG_puts("httpWrite() failed."); + + fclose(fp); + ippDelete(request); + ippDelete(response); + httpClose(cups_server); + return (0); + } + + if (httpUpdate(cups_server) == HTTP_ERROR) + { + DEBUG_puts("httpUpdate() failed."); + jobid = 0; + } + else if ((ippRead(cups_server, response)) == IPP_ERROR) + { + DEBUG_puts("ippRead() failed."); + jobid = 0; + } + else if (response->request.status.status_code > IPP_OK_CONFLICT) + { + DEBUG_printf(("IPP response code was 0x%x!\n", + response->request.status.status_code)); + jobid = 0; + } + else if ((attr = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER)) == NULL) + { + DEBUG_puts("No job ID!"); + jobid = 0; + } + else + jobid = attr->values[0].integer; + } + + fclose(fp); + ippDelete(request); + ippDelete(response); + + return (jobid); +} + + +/* + * 'cups_connect()' - Connect to the specified host... + */ + +static char * /* I - Printer name if success, NULL if fail */ +cups_connect(char *name, /* I - Destination (printer[@host]) */ + char *printer, /* O - Printer name */ + char *hostname) /* O - Hostname */ +{ + char hostbuf[HTTP_MAX_URI]; + /* Name of host */ + static char printerbuf[HTTP_MAX_URI]; + /* Name of printer or class */ + + + if (name == NULL) + return (NULL); + + if (sscanf(name, "%[^@]@%s", printerbuf, hostbuf) == 1) + strcpy(hostbuf, "localhost"); + + if (hostname != NULL) + strcpy(hostname, hostbuf); + else + hostname = hostbuf; + + if (printer != NULL) + strcpy(printer, printerbuf); + else + printer = printerbuf; + + if (cups_server != NULL) + { + if (strcasecmp(cups_server->hostname, hostname) == 0) + return (printer); + + httpClose(cups_server); + } + + if ((cups_server = httpConnect(hostname, ippPort())) == NULL) + return (NULL); + else + return (printer); +} + + +/* + * End of "$Id$". + */ diff --git a/data/HPGLprolog b/data/HPGLprolog new file mode 100644 index 0000000000..bd59e0f78b --- /dev/null +++ b/data/HPGLprolog @@ -0,0 +1,62 @@ +%%BeginResource: procset hpgltops 1.0 0 +% +% "$Id: HPGLprolog 312 1999-05-11 19:45:40Z mike $" +% +% HP-GL/2 filter procset for the Common UNIX Printing System (CUPS). +% +% This procset contains the basic drawing commands that are used to +% reduce output size. Note the 'MP' (make newpath) definition - this +% should be called 'NP' (newpath), but GhostScript uses the 'NP' name +% for 'noaccess put' in some of its font files... +% +% Copyright 1993-1999 Easy Software Products +% +% These coded instructions, statements, and computer programs are the +% property of Easy Software Products and are protected by Federal +% copyright law. Distribution and use rights are outlined in the file +% "LICENSE.txt" which should have been included with this file. If this +% file is missing or damaged please contact Easy Software Products +% at: +% +% Attn: CUPS Licensing Information +% Easy Software Products +% 44141 Airport View Drive, Suite 204 +% Hollywood, Maryland 20636-3111 USA +% +% Voice: (301) 373-9603 +% EMail: cups-info@cups.org +% WWW: http://www.cups.org +% +/MO { moveto } bind def +/LI { lineto } bind def +/FI { fill } bind def +/ST { stroke } bind def +/CP { closepath } bind def +/MP { newpath } bind def +% +% If you have more than 8 pens defined for your HP-GL/2 output you'll +% need to add P# definitions (# = pen number) to set the appropriate color. +% If you don't you'll get errors. The default 8 pens cover the primary +% colors (white, black, red, green, yellow, blue, magenta, cyan). Ditto +% for pen widths (W#). +% +% PC and PW commands in the input stream will define/redefine these +% appropriately, but some packages don't generate them... +% +/P0 { 1.0 1.0 1.0 setrgbcolor } bind def +/P1 { 0.0 0.0 0.0 setrgbcolor } bind def +/P2 { 1.0 0.0 0.0 setrgbcolor } bind def +/P3 { 0.0 1.0 0.0 setrgbcolor } bind def +/P4 { 1.0 1.0 0.0 setrgbcolor } bind def +/P5 { 0.0 0.0 1.0 setrgbcolor } bind def +/P6 { 1.0 0.0 1.0 setrgbcolor } bind def +/P7 { 0.0 1.0 1.0 setrgbcolor } bind def +/W0 { DefaultPenWidth PenScaling mul setlinewidth } bind def +/W1 { DefaultPenWidth PenScaling mul setlinewidth } bind def +/W2 { DefaultPenWidth PenScaling mul setlinewidth } bind def +/W3 { DefaultPenWidth PenScaling mul setlinewidth } bind def +/W4 { DefaultPenWidth PenScaling mul setlinewidth } bind def +/W5 { DefaultPenWidth PenScaling mul setlinewidth } bind def +/W6 { DefaultPenWidth PenScaling mul setlinewidth } bind def +/W7 { DefaultPenWidth PenScaling mul setlinewidth } bind def +%%EndResource diff --git a/data/Makefile b/data/Makefile new file mode 100644 index 0000000000..4c3db20909 --- /dev/null +++ b/data/Makefile @@ -0,0 +1,56 @@ +# +# "$Id$" +# +# Datafile makefile for the Common UNIX Printing System (CUPS). +# +# Copyright 1993-1999 by Easy Software Products. +# +# These coded instructions, statements, and computer programs are the +# property of Easy Software Products and are protected by Federal +# copyright law. Distribution and use rights are outlined in the file +# "LICENSE.txt" which should have been included with this file. If this +# file is missing or damaged please contact Easy Software Products +# at: +# +# Attn: CUPS Licensing Information +# Easy Software Products +# 44141 Airport View Drive, Suite 204 +# Hollywood, Maryland 20636-3111 USA +# +# Voice: (301) 373-9603 +# EMail: cups-info@cups.org +# WWW: http://www.cups.org +# + +include ../Makedefs + +# +# Data files... +# + +FILES = 8859-1 8859-14 8859-15 8859-2 8859-3 8859-4 8859-5 \ + 8859-6 8859-7 8859-8 8859-9 HPGLprolog + +# +# Make everything... +# + +all: + +# +# Clean all config and object files... +# + +clean: + +# +# Install files... +# + +install: + -$(MKDIR) $(DATADIR) + $(CP) $(FILES) $(DATADIR) + +# +# End of "$Id$". +# diff --git a/data/psglyphs b/data/psglyphs new file mode 100644 index 0000000000..7ba55ef5df --- /dev/null +++ b/data/psglyphs @@ -0,0 +1,1051 @@ +0x0020 space +0x0021 exclam +0x0022 quotedbl +0x0023 numbersign +0x0024 dollar +0x0025 percent +0x0026 ampersand +0x0027 quotesingle +0x0028 parenleft +0x0029 parenright +0x002a asterisk +0x002b plus +0x002c comma +0x002d minus +0x002e period +0x002f slash +0x0030 zero +0x0031 one +0x0032 two +0x0033 three +0x0034 four +0x0035 five +0x0036 six +0x0037 seven +0x0038 eight +0x0039 nine +0x003a colon +0x003b semicolon +0x003c less +0x003d equal +0x003e greater +0x003f question +0x0040 at +0x0041 A +0x0042 B +0x0043 C +0x0044 D +0x0045 E +0x0046 F +0x0047 G +0x0048 H +0x0049 I +0x004a J +0x004b K +0x004c L +0x004d M +0x004e N +0x004f O +0x0050 P +0x0051 Q +0x0052 R +0x0053 S +0x0054 T +0x0055 U +0x0056 V +0x0057 W +0x0058 X +0x0059 Y +0x005a Z +0x005b bracketleft +0x005c backslash +0x005d bracketright +0x005e asciicircum +0x005f underscore +0x0060 grave +0x0061 a +0x0062 b +0x0063 c +0x0064 d +0x0065 e +0x0066 f +0x0067 g +0x0068 h +0x0069 i +0x006a j +0x006b k +0x006c l +0x006d m +0x006e n +0x006f o +0x0070 p +0x0071 q +0x0072 r +0x0073 s +0x0074 t +0x0075 u +0x0076 v +0x0077 w +0x0078 x +0x0079 y +0x007a z +0x007b braceleft +0x007c bar +0x007d braceright +0x007e asciitilde +0x00a0 space +0x00a1 exclamdown +0x00a2 cent +0x00a3 sterling +0x00a4 currency +0x00a5 yen +0x00a6 brokenbar +0x00a7 section +0x00a8 dieresis +0x00a9 copyright +0x00aa ordfeminine +0x00ab guillemotleft +0x00ac logicalnot +0x00ad hyphen +0x00ae registered +0x00af macron +0x00b0 degree +0x00b1 plusminus +0x00b2 twosuperior +0x00b3 threesuperior +0x00b4 acute +0x00b5 mu +0x00b6 paragraph +0x00b7 periodcentered +0x00b8 cedilla +0x00b9 onesuperior +0x00ba ordmasculine +0x00bb guillemotright +0x00bc onequarter +0x00bd onehalf +0x00be threequarters +0x00bf questiondown +0x00c0 Agrave +0x00c1 Aacute +0x00c2 Acircumflex +0x00c3 Atilde +0x00c4 Adieresis +0x00c5 Aring +0x00c6 AE +0x00c7 Ccedilla +0x00c8 Egrave +0x00c9 Eacute +0x00ca Ecircumflex +0x00cb Edieresis +0x00cc Igrave +0x00cd Iacute +0x00ce Icircumflex +0x00cf Idieresis +0x00d0 Eth +0x00d1 Ntilde +0x00d2 Ograve +0x00d3 Oacute +0x00d4 Ocircumflex +0x00d5 Otilde +0x00d6 Odieresis +0x00d7 multiply +0x00d8 Oslash +0x00d9 Ugrave +0x00da Uacute +0x00db Ucircumflex +0x00dc Udieresis +0x00dd Yacute +0x00de Thorn +0x00df germandbls +0x00e0 agrave +0x00e1 aacute +0x00e2 acircumflex +0x00e3 atilde +0x00e4 adieresis +0x00e5 aring +0x00e6 ae +0x00e7 ccedilla +0x00e8 egrave +0x00e9 eacute +0x00ea ecircumflex +0x00eb edieresis +0x00ec igrave +0x00ed iacute +0x00ee icircumflex +0x00ef idieresis +0x00f0 eth +0x00f1 ntilde +0x00f2 ograve +0x00f3 oacute +0x00f4 ocircumflex +0x00f5 otilde +0x00f6 odieresis +0x00f7 divide +0x00f8 oslash +0x00f9 ugrave +0x00fa uacute +0x00fb ucircumflex +0x00fc udieresis +0x00fd yacute +0x00fe thorn +0x00ff ydieresis +0x0100 Amacron +0x0101 amacron +0x0102 Abreve +0x0103 abreve +0x0104 Aogonek +0x0105 aogonek +0x0106 Cacute +0x0107 cacute +0x0108 Ccircumflex +0x0109 ccircumflex +0x010a Cdotaccent +0x010b cdotaccent +0x010c Ccaron +0x010d ccaron +0x010e Dcaron +0x010f dcaron +0x0110 Dcroat +0x0111 dcroat +0x0112 Emacron +0x0113 emacron +0x0114 Ebreve +0x0115 ebreve +0x0116 Edotaccent +0x0117 edotaccent +0x0118 Eogonek +0x0119 eogonek +0x011a Ecaron +0x011b ecaron +0x011c Gcircumflex +0x011d gcircumflex +0x011e Gbreve +0x011f gbreve +0x0120 Gdotaccent +0x0121 gdotaccent +0x0122 Gcommaaccent +0x0123 gcommaaccent +0x0124 Hcircumflex +0x0125 hcircumflex +0x0126 Hbar +0x0127 hbar +0x0128 Itilde +0x0129 itilde +0x012a Imacron +0x012b imacron +0x012c Ibreve +0x012d ibreve +0x012e Iogonek +0x012f iogonek +0x0130 Idotaccent +0x0131 dotlessi +0x0132 IJ +0x0133 ij +0x0134 Jcircumflex +0x0135 jcircumflex +0x0136 Kcommaaccent +0x0137 kcommaaccent +0x0138 kgreenlandic +0x0139 Lacute +0x013a lacute +0x013b Lcommaaccent +0x013c lcommaaccent +0x013d Lcaron +0x013e lcaron +0x013f Ldot +0x0140 ldot +0x0141 Lslash +0x0142 lslash +0x0143 Nacute +0x0144 nacute +0x0145 Ncommaaccent +0x0146 ncommaaccent +0x0147 Ncaron +0x0148 ncaron +0x0149 napostrophe +0x014a Eng +0x014b eng +0x014c Omacron +0x014d omacron +0x014e Obreve +0x014f obreve +0x0150 Ohungarumlaut +0x0151 ohungarumlaut +0x0152 OE +0x0153 oe +0x0154 Racute +0x0155 racute +0x0156 Rcommaaccent +0x0157 rcommaaccent +0x0158 Rcaron +0x0159 rcaron +0x015a Sacute +0x015b sacute +0x015c Scircumflex +0x015d scircumflex +0x015e Scedilla +0x015f scedilla +0x0160 Scaron +0x0161 scaron +0x0162 Tcommaaccent +0x0163 tcommaaccent +0x0164 Tcaron +0x0165 tcaron +0x0166 Tbar +0x0167 tbar +0x0168 Utilde +0x0169 utilde +0x016a Umacron +0x016b umacron +0x016c Ubreve +0x016d ubreve +0x016e Uring +0x016f uring +0x0170 Uhungarumlaut +0x0171 uhungarumlaut +0x0172 Uogonek +0x0173 uogonek +0x0174 Wcircumflex +0x0175 wcircumflex +0x0176 Ycircumflex +0x0177 ycircumflex +0x0178 Ydieresis +0x0179 Zacute +0x017a zacute +0x017b Zdotaccent +0x017c zdotaccent +0x017d Zcaron +0x017e zcaron +0x017f longs +0x0192 florin +0x01a0 Ohorn +0x01a1 ohorn +0x01af Uhorn +0x01b0 uhorn +0x01e6 Gcaron +0x01e7 gcaron +0x01fa Aringacute +0x01fb aringacute +0x01fc AEacute +0x01fd aeacute +0x01fe Oslashacute +0x01ff oslashacute +0x0218 Scommaaccent +0x0219 scommaaccent +0x021a Tcommaaccent +0x021b tcommaaccent +0x02bc afii57929 +0x02bd afii64937 +0x02c6 circumflex +0x02c7 caron +0x02c9 macron +0x02d8 breve +0x02d9 dotaccent +0x02da ring +0x02db ogonek +0x02dc tilde +0x02dd hungarumlaut +0x0300 gravecomb +0x0301 acutecomb +0x0303 tildecomb +0x0309 hookabovecomb +0x0323 dotbelowcomb +0x0384 tonos +0x0385 dieresistonos +0x0386 Alphatonos +0x0387 anoteleia +0x0388 Epsilontonos +0x0389 Etatonos +0x038a Iotatonos +0x038c Omicrontonos +0x038e Upsilontonos +0x038f Omegatonos +0x0390 iotadieresistonos +0x0391 Alpha +0x0392 Beta +0x0393 Gamma +0x0394 Delta +0x0395 Epsilon +0x0396 Zeta +0x0397 Eta +0x0398 Theta +0x0399 Iota +0x039a Kappa +0x039b Lambda +0x039c Mu +0x039d Nu +0x039e Xi +0x039f Omicron +0x03a0 Pi +0x03a1 Rho +0x03a3 Sigma +0x03a4 Tau +0x03a5 Upsilon +0x03a6 Phi +0x03a7 Chi +0x03a8 Psi +0x03a9 Omega +0x03aa Iotadieresis +0x03ab Upsilondieresis +0x03ac alphatonos +0x03ad epsilontonos +0x03ae etatonos +0x03af iotatonos +0x03b0 upsilondieresistonos +0x03b1 alpha +0x03b2 beta +0x03b3 gamma +0x03b4 delta +0x03b5 epsilon +0x03b6 zeta +0x03b7 eta +0x03b8 theta +0x03b9 iota +0x03ba kappa +0x03bb lambda +0x03bc mu +0x03bd nu +0x03be xi +0x03bf omicron +0x03c0 pi +0x03c1 rho +0x03c2 sigma1 +0x03c3 sigma +0x03c4 tau +0x03c5 upsilon +0x03c6 phi +0x03c7 chi +0x03c8 psi +0x03c9 omega +0x03ca iotadieresis +0x03cb upsilondieresis +0x03cc omicrontonos +0x03cd upsilontonos +0x03ce omegatonos +0x03d1 theta1 +0x03d2 Upsilon1 +0x03d5 phi1 +0x03d6 omega1 +0x0401 afii10023 +0x0402 afii10051 +0x0403 afii10052 +0x0404 afii10053 +0x0405 afii10054 +0x0406 afii10055 +0x0407 afii10056 +0x0408 afii10057 +0x0409 afii10058 +0x040a afii10059 +0x040b afii10060 +0x040c afii10061 +0x040e afii10062 +0x040f afii10145 +0x0410 afii10017 +0x0411 afii10018 +0x0412 afii10019 +0x0413 afii10020 +0x0414 afii10021 +0x0415 afii10022 +0x0416 afii10024 +0x0417 afii10025 +0x0418 afii10026 +0x0419 afii10027 +0x041a afii10028 +0x041b afii10029 +0x041c afii10030 +0x041d afii10031 +0x041e afii10032 +0x041f afii10033 +0x0420 afii10034 +0x0421 afii10035 +0x0422 afii10036 +0x0423 afii10037 +0x0424 afii10038 +0x0425 afii10039 +0x0426 afii10040 +0x0427 afii10041 +0x0428 afii10042 +0x0429 afii10043 +0x042a afii10044 +0x042b afii10045 +0x042c afii10046 +0x042d afii10047 +0x042e afii10048 +0x042f afii10049 +0x0430 afii10065 +0x0431 afii10066 +0x0432 afii10067 +0x0433 afii10068 +0x0434 afii10069 +0x0435 afii10070 +0x0436 afii10072 +0x0437 afii10073 +0x0438 afii10074 +0x0439 afii10075 +0x043a afii10076 +0x043b afii10077 +0x043c afii10078 +0x043d afii10079 +0x043e afii10080 +0x043f afii10081 +0x0440 afii10082 +0x0441 afii10083 +0x0442 afii10084 +0x0443 afii10085 +0x0444 afii10086 +0x0445 afii10087 +0x0446 afii10088 +0x0447 afii10089 +0x0448 afii10090 +0x0449 afii10091 +0x044a afii10092 +0x044b afii10093 +0x044c afii10094 +0x044d afii10095 +0x044e afii10096 +0x044f afii10097 +0x0451 afii10071 +0x0452 afii10099 +0x0453 afii10100 +0x0454 afii10101 +0x0455 afii10102 +0x0456 afii10103 +0x0457 afii10104 +0x0458 afii10105 +0x0459 afii10106 +0x045a afii10107 +0x045b afii10108 +0x045c afii10109 +0x045e afii10110 +0x045f afii10193 +0x0462 afii10146 +0x0463 afii10194 +0x0472 afii10147 +0x0473 afii10195 +0x0474 afii10148 +0x0475 afii10196 +0x0490 afii10050 +0x0491 afii10098 +0x04d9 afii10846 +0x05b0 afii57799 +0x05b1 afii57801 +0x05b2 afii57800 +0x05b3 afii57802 +0x05b4 afii57793 +0x05b5 afii57794 +0x05b6 afii57795 +0x05b7 afii57798 +0x05b8 afii57797 +0x05b9 afii57806 +0x05bb afii57796 +0x05bc afii57807 +0x05bd afii57839 +0x05be afii57645 +0x05bf afii57841 +0x05c0 afii57842 +0x05c1 afii57804 +0x05c2 afii57803 +0x05c3 afii57658 +0x05d0 afii57664 +0x05d1 afii57665 +0x05d2 afii57666 +0x05d3 afii57667 +0x05d4 afii57668 +0x05d5 afii57669 +0x05d6 afii57670 +0x05d7 afii57671 +0x05d8 afii57672 +0x05d9 afii57673 +0x05da afii57674 +0x05db afii57675 +0x05dc afii57676 +0x05dd afii57677 +0x05de afii57678 +0x05df afii57679 +0x05e0 afii57680 +0x05e1 afii57681 +0x05e2 afii57682 +0x05e3 afii57683 +0x05e4 afii57684 +0x05e5 afii57685 +0x05e6 afii57686 +0x05e7 afii57687 +0x05e8 afii57688 +0x05e9 afii57689 +0x05ea afii57690 +0x05f0 afii57716 +0x05f1 afii57717 +0x05f2 afii57718 +0x060c afii57388 +0x061b afii57403 +0x061f afii57407 +0x0621 afii57409 +0x0622 afii57410 +0x0623 afii57411 +0x0624 afii57412 +0x0625 afii57413 +0x0626 afii57414 +0x0627 afii57415 +0x0628 afii57416 +0x0629 afii57417 +0x062a afii57418 +0x062b afii57419 +0x062c afii57420 +0x062d afii57421 +0x062e afii57422 +0x062f afii57423 +0x0630 afii57424 +0x0631 afii57425 +0x0632 afii57426 +0x0633 afii57427 +0x0634 afii57428 +0x0635 afii57429 +0x0636 afii57430 +0x0637 afii57431 +0x0638 afii57432 +0x0639 afii57433 +0x063a afii57434 +0x0640 afii57440 +0x0641 afii57441 +0x0642 afii57442 +0x0643 afii57443 +0x0644 afii57444 +0x0645 afii57445 +0x0646 afii57446 +0x0647 afii57470 +0x0648 afii57448 +0x0649 afii57449 +0x064a afii57450 +0x064b afii57451 +0x064c afii57452 +0x064d afii57453 +0x064e afii57454 +0x064f afii57455 +0x0650 afii57456 +0x0651 afii57457 +0x0652 afii57458 +0x0660 afii57392 +0x0661 afii57393 +0x0662 afii57394 +0x0663 afii57395 +0x0664 afii57396 +0x0665 afii57397 +0x0666 afii57398 +0x0667 afii57399 +0x0668 afii57400 +0x0669 afii57401 +0x066a afii57381 +0x066d afii63167 +0x0679 afii57511 +0x067e afii57506 +0x0686 afii57507 +0x0688 afii57512 +0x0691 afii57513 +0x0698 afii57508 +0x06a4 afii57505 +0x06af afii57509 +0x06ba afii57514 +0x06d2 afii57519 +0x06d5 afii57534 +0x1e80 Wgrave +0x1e81 wgrave +0x1e82 Wacute +0x1e83 wacute +0x1e84 Wdieresis +0x1e85 wdieresis +0x1ef2 Ygrave +0x1ef3 ygrave +0x200c afii61664 +0x200d afii301 +0x200e afii299 +0x200f afii300 +0x2012 figuredash +0x2013 endash +0x2014 emdash +0x2015 afii00208 +0x2017 underscoredbl +0x2018 quoteleft +0x2019 quoteright +0x201a quotesinglbase +0x201b quotereversed +0x201c quotedblleft +0x201d quotedblright +0x201e quotedblbase +0x2020 dagger +0x2021 daggerdbl +0x2022 bullet +0x2024 onedotenleader +0x2025 twodotenleader +0x2026 ellipsis +0x202c afii61573 +0x202d afii61574 +0x202e afii61575 +0x2030 perthousand +0x2032 minute +0x2033 second +0x2039 guilsinglleft +0x203a guilsinglright +0x203c exclamdbl +0x2044 fraction +0x2070 zerosuperior +0x2074 foursuperior +0x2075 fivesuperior +0x2076 sixsuperior +0x2077 sevensuperior +0x2078 eightsuperior +0x2079 ninesuperior +0x207d parenleftsuperior +0x207e parenrightsuperior +0x207f nsuperior +0x2080 zeroinferior +0x2081 oneinferior +0x2082 twoinferior +0x2083 threeinferior +0x2084 fourinferior +0x2085 fiveinferior +0x2086 sixinferior +0x2087 seveninferior +0x2088 eightinferior +0x2089 nineinferior +0x208d parenleftinferior +0x208e parenrightinferior +0x20a1 colonmonetary +0x20a3 franc +0x20a4 lira +0x20a7 peseta +0x20aa afii57636 +0x20ab dong +0x20ac Euro +0x2105 afii61248 +0x2111 Ifraktur +0x2113 afii61289 +0x2116 afii61352 +0x2118 weierstrass +0x211c Rfraktur +0x211e prescription +0x2122 trademark +0x2126 Omega +0x212e estimated +0x2135 aleph +0x2153 onethird +0x2154 twothirds +0x215b oneeighth +0x215c threeeighths +0x215d fiveeighths +0x215e seveneighths +0x2190 arrowleft +0x2191 arrowup +0x2192 arrowright +0x2193 arrowdown +0x2194 arrowboth +0x2195 arrowupdn +0x21a8 arrowupdnbse +0x21b5 carriagereturn +0x21d0 arrowdblleft +0x21d1 arrowdblup +0x21d2 arrowdblright +0x21d3 arrowdbldown +0x21d4 arrowdblboth +0x2200 universal +0x2202 partialdiff +0x2203 existential +0x2205 emptyset +0x2206 Delta +0x2207 gradient +0x2208 element +0x2209 notelement +0x220b suchthat +0x220f product +0x2211 summation +0x2212 minus +0x2215 fraction +0x2217 asteriskmath +0x2219 periodcentered +0x221a radical +0x221d proportional +0x221e infinity +0x221f orthogonal +0x2220 angle +0x2227 logicaland +0x2228 logicalor +0x2229 intersection +0x222a union +0x222b integral +0x2234 therefore +0x223c similar +0x2245 congruent +0x2248 approxequal +0x2260 notequal +0x2261 equivalence +0x2264 lessequal +0x2265 greaterequal +0x2282 propersubset +0x2283 propersuperset +0x2284 notsubset +0x2286 reflexsubset +0x2287 reflexsuperset +0x2295 circleplus +0x2297 circlemultiply +0x22a5 perpendicular +0x22c5 dotmath +0x2302 house +0x2310 revlogicalnot +0x2320 integraltp +0x2321 integralbt +0x2329 angleleft +0x232a angleright +0x2500 SF100000 +0x2502 SF110000 +0x250c SF010000 +0x2510 SF030000 +0x2514 SF020000 +0x2518 SF040000 +0x251c SF080000 +0x2524 SF090000 +0x252c SF060000 +0x2534 SF070000 +0x253c SF050000 +0x2550 SF430000 +0x2551 SF240000 +0x2552 SF510000 +0x2553 SF520000 +0x2554 SF390000 +0x2555 SF220000 +0x2556 SF210000 +0x2557 SF250000 +0x2558 SF500000 +0x2559 SF490000 +0x255a SF380000 +0x255b SF280000 +0x255c SF270000 +0x255d SF260000 +0x255e SF360000 +0x255f SF370000 +0x2560 SF420000 +0x2561 SF190000 +0x2562 SF200000 +0x2563 SF230000 +0x2564 SF470000 +0x2565 SF480000 +0x2566 SF410000 +0x2567 SF450000 +0x2568 SF460000 +0x2569 SF400000 +0x256a SF540000 +0x256b SF530000 +0x256c SF440000 +0x2580 upblock +0x2584 dnblock +0x2588 block +0x258c lfblock +0x2590 rtblock +0x2591 ltshade +0x2592 shade +0x2593 dkshade +0x25a0 filledbox +0x25a1 H22073 +0x25aa H18543 +0x25ab H18551 +0x25ac filledrect +0x25b2 triagup +0x25ba triagrt +0x25bc triagdn +0x25c4 triaglf +0x25ca lozenge +0x25cb circle +0x25cf H18533 +0x25d8 invbullet +0x25d9 invcircle +0x25e6 openbullet +0x263a smileface +0x263b invsmileface +0x263c sun +0x2640 female +0x2642 male +0x2660 spade +0x2663 club +0x2665 heart +0x2666 diamond +0x266a musicalnote +0x266b musicalnotedbl +0xf6be dotlessj +0xf6bf LL +0xf6c0 ll +0xf6c1 Scedilla +0xf6c2 scedilla +0xf6c3 commaaccent +0xf6c4 afii10063 +0xf6c5 afii10064 +0xf6c6 afii10192 +0xf6c7 afii10831 +0xf6c8 afii10832 +0xf6c9 Acute +0xf6ca Caron +0xf6cb Dieresis +0xf6cc DieresisAcute +0xf6cd DieresisGrave +0xf6ce Grave +0xf6cf Hungarumlaut +0xf6d0 Macron +0xf6d1 cyrBreve +0xf6d2 cyrFlex +0xf6d3 dblGrave +0xf6d4 cyrbreve +0xf6d5 cyrflex +0xf6d6 dblgrave +0xf6d7 dieresisacute +0xf6d8 dieresisgrave +0xf6d9 copyrightserif +0xf6da registerserif +0xf6db trademarkserif +0xf6dc onefitted +0xf6dd rupiah +0xf6de threequartersemdash +0xf6df centinferior +0xf6e0 centsuperior +0xf6e1 commainferior +0xf6e2 commasuperior +0xf6e3 dollarinferior +0xf6e4 dollarsuperior +0xf6e5 hypheninferior +0xf6e6 hyphensuperior +0xf6e7 periodinferior +0xf6e8 periodsuperior +0xf6e9 asuperior +0xf6ea bsuperior +0xf6eb dsuperior +0xf6ec esuperior +0xf6ed isuperior +0xf6ee lsuperior +0xf6ef msuperior +0xf6f0 osuperior +0xf6f1 rsuperior +0xf6f2 ssuperior +0xf6f3 tsuperior +0xf6f4 Brevesmall +0xf6f5 Caronsmall +0xf6f6 Circumflexsmall +0xf6f7 Dotaccentsmall +0xf6f8 Hungarumlautsmall +0xf6f9 Lslashsmall +0xf6fa OEsmall +0xf6fb Ogoneksmall +0xf6fc Ringsmall +0xf6fd Scaronsmall +0xf6fe Tildesmall +0xf6ff Zcaronsmall +0xf721 exclamsmall +0xf724 dollaroldstyle +0xf726 ampersandsmall +0xf730 zerooldstyle +0xf731 oneoldstyle +0xf732 twooldstyle +0xf733 threeoldstyle +0xf734 fouroldstyle +0xf735 fiveoldstyle +0xf736 sixoldstyle +0xf737 sevenoldstyle +0xf738 eightoldstyle +0xf739 nineoldstyle +0xf73f questionsmall +0xf760 Gravesmall +0xf761 Asmall +0xf762 Bsmall +0xf763 Csmall +0xf764 Dsmall +0xf765 Esmall +0xf766 Fsmall +0xf767 Gsmall +0xf768 Hsmall +0xf769 Ismall +0xf76a Jsmall +0xf76b Ksmall +0xf76c Lsmall +0xf76d Msmall +0xf76e Nsmall +0xf76f Osmall +0xf770 Psmall +0xf771 Qsmall +0xf772 Rsmall +0xf773 Ssmall +0xf774 Tsmall +0xf775 Usmall +0xf776 Vsmall +0xf777 Wsmall +0xf778 Xsmall +0xf779 Ysmall +0xf77a Zsmall +0xf7a1 exclamdownsmall +0xf7a2 centoldstyle +0xf7a8 Dieresissmall +0xf7af Macronsmall +0xf7b4 Acutesmall +0xf7b8 Cedillasmall +0xf7bf questiondownsmall +0xf7e0 Agravesmall +0xf7e1 Aacutesmall +0xf7e2 Acircumflexsmall +0xf7e3 Atildesmall +0xf7e4 Adieresissmall +0xf7e5 Aringsmall +0xf7e6 AEsmall +0xf7e7 Ccedillasmall +0xf7e8 Egravesmall +0xf7e9 Eacutesmall +0xf7ea Ecircumflexsmall +0xf7eb Edieresissmall +0xf7ec Igravesmall +0xf7ed Iacutesmall +0xf7ee Icircumflexsmall +0xf7ef Idieresissmall +0xf7f0 Ethsmall +0xf7f1 Ntildesmall +0xf7f2 Ogravesmall +0xf7f3 Oacutesmall +0xf7f4 Ocircumflexsmall +0xf7f5 Otildesmall +0xf7f6 Odieresissmall +0xf7f8 Oslashsmall +0xf7f9 Ugravesmall +0xf7fa Uacutesmall +0xf7fb Ucircumflexsmall +0xf7fc Udieresissmall +0xf7fd Yacutesmall +0xf7fe Thornsmall +0xf7ff Ydieresissmall +0xf8e5 radicalex +0xf8e6 arrowvertex +0xf8e7 arrowhorizex +0xf8e8 registersans +0xf8e9 copyrightsans +0xf8ea trademarksans +0xf8eb parenlefttp +0xf8ec parenleftex +0xf8ed parenleftbt +0xf8ee bracketlefttp +0xf8ef bracketleftex +0xf8f0 bracketleftbt +0xf8f1 bracelefttp +0xf8f2 braceleftmid +0xf8f3 braceleftbt +0xf8f4 braceex +0xf8f5 integralex +0xf8f6 parenrighttp +0xf8f7 parenrightex +0xf8f8 parenrightbt +0xf8f9 bracketrighttp +0xf8fa bracketrightex +0xf8fb bracketrightbt +0xf8fc bracerighttp +0xf8fd bracerightmid +0xf8fe bracerightbt +0xfb00 ff +0xfb01 fi +0xfb02 fl +0xfb03 ffi +0xfb04 ffl +0xfb1f afii57705 +0xfb2a afii57694 +0xfb2b afii57695 +0xfb35 afii57723 +0xfb4b afii57700 diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 0000000000..303cbae1ff --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,89 @@ +# +# "$Id$" +# +# Documentation makefile for the Common UNIX Printing System (CUPS). +# +# Copyright 1993-1999 by Easy Software Products. +# +# These coded instructions, statements, and computer programs are the +# property of Easy Software Products and are protected by Federal +# copyright law. Distribution and use rights are outlined in the file +# "LICENSE.txt" which should have been included with this file. If this +# file is missing or damaged please contact Easy Software Products +# at: +# +# Attn: CUPS Licensing Information +# Easy Software Products +# 44141 Airport View Drive, Suite 204 +# Hollywood, Maryland 20636-3111 USA +# +# Voice: (301) 373-9603 +# EMail: cups-info@cups.org +# WWW: http://www.cups.org +# + +include ../Makedefs + +# +# HTMLDOC generation rules... +# + +.SUFFIXES: .html .pdf .shtml +.shtml.html: + htmldoc --title images/cups-large.gif --numbered -f $@ $< +.shtml.pdf: + htmldoc --title images/cups-large.gif --duplex --compression=9 \ + --numbered --jpeg -f $@ $< + +# +# Document files... +# + +DOCUMENTS = cmp.shtml idd.shtml sam.shtml sdd.shtml ssr.shtml \ + stp.shtml sum.shtml svd.shtml +DOCIMAGES = images/navbar.gif +WEBPAGES = cups.css cupsdoc.css index.html documentation.html +WEBIMAGES = images/navbar.gif images/printer-idle.gif \ + images/printer-processing.gif \ + images/printer-stopped.gif + +# +# +# Make all documents... +# + +all: $(DOCUMENTS:.shtml=.pdf) $(DOCUMENTS:.shtml=.html) overview.pdf + +# +# Remove all generated files... +# + +clean: + $(RM) $(DOCUMENTS:.shtml=.pdf) + $(RM) $(DOCUMENTS:.shtml=.html) + $(RM) overview.pdf + +# +# Install all documentation files... +# + +install: + -$(MKDIR) $(SERVERROOT)/doc + $(CP) $(WEBPAGES) $(SERVERROOT)/doc + $(CP) overview.html overview.pdf $(SERVERROOT)/doc + $(CP) $(DOCUMENTS:.shtml=.html) $(SERVERROOT)/doc + $(CP) $(DOCUMENTS:.shtml=.pdf) $(SERVERROOT)/doc + -$(MKDIR) $(SERVERROOT)/doc/images + $(CP) $(WEBIMAGES) $(SERVERROOT)/doc/images + $(CP) $(DOCIMAGES) $(SERVERROOT)/doc/images + +# +# The overview PDF file gets special attention... +# + +overview.pdf: overview.html + htmldoc --duplex --compression=9 --jpeg --webpage -f $@ $< + +# +# End of Makefile. +# diff --git a/doc/cmp.html b/doc/cmp.html new file mode 100644 index 0000000000..b8bc993859 --- /dev/null +++ b/doc/cmp.html @@ -0,0 +1,648 @@ + + +CUPS Configuration Management Plan + + + + + +


+

CUPS Configuration Management Plan


+CUPS-CMP-1.0
+Easy Software Products
+Copyright 1997-1999, All Rights Reserved
+
+
+

Table of Contents

+
+
1 Scope + +2 References + +3 File Management + +4 Trouble Report Processing + +5 Software Releases + +A Glossary + +B Coding Requirements + +C Software Trouble Report Form
+

1 Scope

+

1.1 Identification

+ This configuration management plan document provides the guidelines +for development and maintainance of the Common UNIX Printing System +("CUPS") Version 1.0 software. +

1.2 System Overview

+ The Common UNIX Printing System provides a portable printing layer for + UNIX® operating systems. It has been developed by Easy Software + Products to promote a standard printing solution for all UNIX vendors + and users. CUPS provides the System V and Berkeley command-line +interfaces. +

CUPS uses the Internet Printing Protocol (IETF-IPP) as the basis for +managing print jobs and queues. The Line Printer Daemon (LPD, RFC1179), +Server Message Block (SMB), and AppSocket protocols are also supported +with reduced functionality.

+

CUPS adds network printer browsing and PostScript Printer +Description ("PPD")-based printing options to support real world +applications under UNIX.

+

1.3 Document Overview

+ This configuration management document is organized into the following +sections: + +

2 References

+

2.1 CUPS Documentation

+ The following CUPS documentation is referenced by this document: + +

2.2 Other Documents

+ The following non-CUPS documents are referenced by this document: + +

3 File Management

+

3.1 Directory Structure

+ Each source file shall be placed a sub-directory corresponding to the +software sub-system it belongs to ("scheduler", "libcups", etc.) To +remain compatible with older UNIX filesystems, directory names shall +not exceed 16 characters in length. +

3.2 Source Files

+ Source files shall be documented and formatted as described in +Appendix B, Coding Requirements. +

3.3 Configuration Management

+ Source files shall be placed under the control of the Concurrent +Versions System ("CVS") software. Source files shall be "checked in" +with each change so that modifications can be tracked. +

Documentation on the CVS software is included with the whitepaper, +"CVS II: Parallelizing Software Development".

+

4 Trouble Report Processing

+ A Software Trouble Report ("STR") shall be submitted every time a user +or vendor experiences a problem with the CUPS software. Trouble reports +are maintained in a database with one of the following states: +
    +
  1. STR is closed with complete resolution
  2. +
  3. STR is closed without resolution
  4. +
  5. STR is active
  6. +
  7. STR is pending (new STR or additional information available)
  8. +
+ Trouble reports shall be processed using the following steps. +

4.1 Classification

+ When a trouble report is received it must be classified at one of the +following levels: +
    +
  1. Request for enhancement
  2. +
  3. Documentation error
  4. +
  5. Unable to print a file
  6. +
  7. Unable to print to a printer
  8. +
  9. Unable to print at all
  10. +
+ The scope of the problem should also be determined as: +
    +
  1. Specific to a machine
  2. +
  3. Specific to an operating system
  4. +
  5. Applies to all machines and operating systems
  6. +
+

4.2 Identification

+ Once the level and scope of the trouble report is determined the +software sub-system(s) involved with the problem are determined. This +may involve additional communication with the user or vendor to isolate +the problem to a specific cause. +

When the sub-system(s) involved have been identified, an engineer +will then determine the change(s) needed and estimate the time required +for the change(s).

+

4.3 Correction

+ Corrections are scheduled based upon the severity and complexity of +the problem. Once all changes have been made, documented, and tested +successfully a new software release snapshot is generated. Additional +tests are added as necessary for proper testing of the changes. +

4.4 Notification

+ The user or vendor is notified when the fix is available or if the +problem was caused by user error. +

5 Software Releases

+

5.1 Version Numbering

+ CUPS uses a three-part version number separated by periods to +represent the major, minor, and patch release numbers: + + Beta-test releases are indentified by appending the letter B followed +by the build number: + + A CVS snapshot is generated for every beta and final release and uses +the version number preceded by the letter "v" and with the decimal +points replaced by underscores: + + Each change that corrects a fault in a software sub-system increments +the patch release number. If a change affects the software design of +CUPS then the minor release number will be incremented and the patch +release number reset to 0. If CUPS is completely redesigned the major +release number will be incremented and the minor and patch release +numbers reset to 0: + +

5.2 Generation

+ Software releases shall be generated for each successfully completed +software trouble report. All object and executable files shall be +deleted prior to performing a full build to ensure that source files +are recompiled. +

5.3 Testing

+ Software testing shall be conducted according to the CUPS Software +Test Plan, CUPS-STP-1.0. Failed tests cause STRs to be generated to +correct the problems found. +

5.4 Release

+ When testing has been completed successfully a new distribution image +is created from the current CVS code "snapshot". No production release +shall contain software that has not passed the appropriate software +tests. +

A Glossary

+

A.1 Terms

+
+
C
+
A computer language.
+
parallel
+
Sending or receiving data more than 1 bit at a time.
+
pipe
+
A one-way communications channel between two programs.
+
serial
+
Sending or receiving data 1 bit at a time.
+
socket
+
A two-way network communications channel.
+
+

A.2 Acronyms

+
+
ASCII
+
American Standard Code for Information Interchange
+
CUPS
+
Common UNIX Printing System
+
ESC/P
+
EPSON Standard Code for Printers
+
FTP
+
File Transfer Protocol
+
HP-GL
+
Hewlett-Packard Graphics Language
+
HP-PCL
+
Hewlett-Packard Printer Control Language
+
HP-PJL
+
Hewlett-Packard Printer Job Language
+
IETF
+
Internet Engineering Task Force
+
IPP
+
Internet Printing Protocol
+
ISO
+
International Standards Organization
+
LPD
+
Line Printer Daemon
+
MIME
+
Multimedia Internet Mail Exchange
+
PCL
+
Page Control Language
+
PPD
+
PostScript Printer Description
+
SMB
+
Server Message Block
+
TFTP
+
Trivial File Transfer Protocol
+
+

B Coding Requirements

+ These coding requirements provide detailed information on source file +formatting and documentation content. These guidelines shall be applied +to all C and C++ source files provided with CUPS. +

B.1 Source Files

+

B.1.1 Naming

+ All source files names shall be 16 characters or less in length to +ensure compatibility with older UNIX filesystems. Source files +containing functions shall have an extension of ".c" for ANSI C and +".cpp" for C++ source files. All other "include" files shall have an +extension of ".h". +

B.1.2 Documentation

+ The top of each source file shall contain a header giving the name of +the file, the purpose or nature of the source file, the copyright and +licensing notice, and the functions contained in the file. The file +name and revision information is provided by the CVS "$Id: cmp.shtml,v +1.2 1999/05/13 20:40:40 mike Exp $" tag: + + The bottom of each source file shall contain a trailer giving the name +of the file using the CVS "$Id: cmp.shtml,v 1.2 1999/05/13 20:40:40 +mike Exp $" tag. The primary purpose of this is to mark the end of a +source file; if the trailer is missing it is possible that code has +been lost near the end of the file: + +

B.2 Functions

+

B.2.1 Naming

+ Functions with a global scope shall be capitalized ("DoThis", +"DoThat", "DoSomethingElse", etc.) The only exception to this rule +shall be the CUPS interface library functions which may begin with a +prefix word in lowercase ("cupsDoThis", "cupsDoThat", etc.) +

Functions with a local scope shall be declared "static" and be +lowercase with underscores between words ("do_this", "do_that", +"do_something_else", etc.)

+

B.2.2 Documentation

+ Each function shall begin with a comment header describing what the +function does, the possible input limits (if any), and the possible +output values (if any), and any special information needed: + +

B.3 Methods

+

B.3.1 Naming

+ Methods shall be in lowercase with underscores between words +("do_this", "do_that", "do_something_else", etc.) +

B.3.2 Documentation

+ Each method shall begin with a comment header describing what the +method does, the possible input limits (if any), and the possible +output values (if any), and any special information needed: + +

B.4 Variables

+

B.4.1 Naming

+ Variables with a global scope shall be capitalized ("ThisVariable", +"ThatVariable", "ThisStateVariable", etc.) The only exception to this +rule shall be the CUPS interface library global variables which must +begin with the prefix "cups" ("cupsThisVariable", "cupsThatVariable", +etc.) Global variables shall be replaced by function arguments whenever +possible. +

Variables with a local scope shall be lowercase with underscores +between words ("this_variable", "that_variable", etc.) Any local +variables shared by functions within a source file shall be declared +"static".

+

B.4.2 Documentation

+ Each variable shall be declared on a separate line and shall be +immediately followed by a comment block describing the variable: + +

B.5 Types

+

B.5.1 Naming

+ All type names shall be lowercase with underscores between words and +"_t" appended to the end of the name ("this_type_t", "that_type_t", +etc.) +

B.5.2 Documentation

+ Each type shall have a comment block immediately before the typedef: + +

B.6 Structures

+

B.6.1 Naming

+ All structure names shall be lowercase with underscores between words +and "_str" appended to the end of the name ("this_struct_str", +"that_struct_str", etc.) +

B.6.2 Documentation

+ Each structure shall have a comment block immediately before the +struct and each member shall be documented in accordance with the +variable naming policy above: + +

B.7 Classes

+

B.7.1 Naming

+ All class names shall be lowercase with underscores between words +("this_class", "that_class", etc.) +

B.7.2 Documentation

+ Each class shall have a comment block immediately before the class and +each member shall be documented in accordance with the variable naming +policy above: + +

B.8 Constants

+

B.8.1 Naming

+ All constant names shall be uppercase with underscored between words +("THIS_CONSTANT", "THAT_CONSTANT", etc.) Constants defined for the CUPS +interface library must begin with an uppercase prefix +("CUPS_THIS_CONSTANT", "CUPS_THAT_CONSTANT", etc.) +

Typed enumerations shall be used whenever possible to allow for type +checking by the compiler.

+

B.8.2 Documentation

+ Comment blocks shall immediately follow each constant: + +

B.9 Code

+

B.9.1 Documentation

+ All source code shall utilize block comments within functions to +describe the operations being performed by a group of statements: + +

B.9.2 Style

+

B.9.2.a Indentation

+ All code blocks enclosed by brackets shall begin with the opening +brace on a new line. The code then follows starting on a new line after +the brace and is indented 2 spaces. The closing brace is then placed on +a new line following the code at the original indentation: + + Single-line statements following "do", "else", "for", "if", and +"while" shall be indented 2 spaces as well. Blocks of code in a +"switch" block shall be indented 4 spaces after each "case" and +"default" case: + +

B.9.2.b Spacing

+ A space shall follow each reserved word ("if", "while", etc.) Spaces +shall not be inserted between a function name and the arguments in +parenthesis. +

B.9.2.c Return Values

+ Parenthesis shall surround values returned from a function using +"return": + +

B.9.2.d Loops

+ Whenever convenient loops should count downward to zero to improve +program performance: + +

C Software Trouble Report Form

+
+ + + + + +
Summary of Problem: +________________________________________
Problem Severity:__1=RFE +
__2=Documentation-Error +
__3=Unable-to-Print-a-File +
__4=Unable-to-Print-to-a-Printer +
__5=Unable-to-Print-at-All
Problem Scope:__1=Machine +__2=Operating-System __3=All
Detailed Description of Problem: +________________________________________ +
________________________________________ +
________________________________________ +
________________________________________ +
________________________________________ +
________________________________________
+
+ + diff --git a/doc/cmp.pdf b/doc/cmp.pdf new file mode 100644 index 0000000000..59a6bdbfe2 --- /dev/null +++ b/doc/cmp.pdf @@ -0,0 +1,966 @@ +%PDF-1.2 +%âãÏÓ +1 0 obj<>endobj +2 0 obj<>endobj +3 0 obj<>endobj +4 0 obj<>endobj +5 0 obj<>endobj +6 0 obj<>endobj +7 0 obj<>endobj +8 0 obj<>endobj +9 0 obj<>endobj +10 0 obj<>endobj +11 0 obj<>endobj +12 0 obj<>endobj +13 0 obj<>endobj +14 0 obj<>endobj +15 0 obj<>endobj +16 0 obj<>endobj +17 0 obj<>endobj +18 0 obj<>endobj +19 0 obj<>endobj +20 0 obj<>endobj +21 0 obj<>endobj +22 0 obj<>endobj +23 0 obj<>endobj +24 0 obj<>endobj +25 0 obj<>endobj +26 0 obj<>endobj +27 0 obj<>endobj +28 0 obj<>endobj +29 0 obj<>endobj +30 0 obj<>endobj +31 0 obj<>endobj +32 0 obj<>endobj +33 0 obj<>endobj +34 0 obj<>endobj +35 0 obj<>endobj +36 0 obj<>endobj +37 0 obj<>endobj +38 0 obj<>endobj +39 0 obj<>endobj +40 0 obj<>endobj +41 0 obj<>endobj +42 0 obj<>endobj +43 0 obj<>endobj +44 0 obj<>endobj +45 0 obj<>endobj +46 0 obj<>endobj +47 0 obj<>endobj +48 0 obj<>endobj +49 0 obj<>endobj +50 0 obj<>endobj +51 0 obj<>endobj +52 0 obj<>endobj +53 0 obj<>endobj +54 0 obj<>endobj +55 0 obj<>endobj +56 0 obj<>endobj +57 0 obj<>endobj +58 0 obj<>endobj +59 0 obj<>endobj +60 0 obj<>endobj +61 0 obj<>endobj +62 0 obj<>endobj +63 0 obj<>endobj +64 0 obj<>endobj +65 0 obj<>endobj +66 0 obj<>endobj +67 0 obj<>endobj +68 0 obj<>endobj +69 0 obj<>endobj +70 0 obj<>endobj +71 0 obj<>endobj +72 0 obj<>endobj +73 0 obj<>endobj +74 0 obj<>endobj +75 0 obj<>endobj +76 0 obj<>endobj +77 0 obj<>endobj +78 0 obj<>endobj +79 0 obj<>endobj +80 0 obj<>endobj +81 0 obj<>endobj +82 0 obj<>endobj +83 0 obj<>endobj +84 0 obj<>endobj +85 0 obj<>endobj +86 0 obj<>endobj +87 0 obj<>endobj +88 0 obj<>endobj +89 0 obj<>endobj +90 0 obj<>endobj +91 0 obj<>endobj +92 0 obj<>endobj +93 0 obj<>endobj +94 0 obj<>endobj +95 0 obj<>endobj +96 0 obj<>endobj +97 0 obj<>endobj +98 0 obj<>endobj +99 0 obj<>endobj +100 0 obj<>endobj +101 0 obj<>endobj +102 0 obj<>endobj +103 0 obj<>endobj +104 0 obj<>endobj +105 0 obj<>endobj +106 0 obj[10 0 R +11 0 R +12 0 R +13 0 R +14 0 R +15 0 R +16 0 R +17 0 R +18 0 R +19 0 R +20 0 R +21 0 R +22 0 R +23 0 R +24 0 R +25 0 R +26 0 R +27 0 R +28 0 R +29 0 R +30 0 R +31 0 R +32 0 R +33 0 R +34 0 R +35 0 R +36 0 R +37 0 R +38 0 R +39 0 R +40 0 R +41 0 R +42 0 R +43 0 R +44 0 R +45 0 R +46 0 R +47 0 R +48 0 R +49 0 R +50 0 R +51 0 R +52 0 R +53 0 R +54 0 R +55 0 R +56 0 R +57 0 R +58 0 R +59 0 R +60 0 R +61 0 R +62 0 R +63 0 R +64 0 R +65 0 R +66 0 R +67 0 R +68 0 R +69 0 R +70 0 R +71 0 R +72 0 R +73 0 R +74 0 R +75 0 R +76 0 R +77 0 R +78 0 R +79 0 R +80 0 R +81 0 R +82 0 R +83 0 R +84 0 R +85 0 R +86 0 R +87 0 R +88 0 R +89 0 R +90 0 R +91 0 R +92 0 R +93 0 R +94 0 R +95 0 R +96 0 R +97 0 R +98 0 R +99 0 R +100 0 R +101 0 R +102 0 R +103 0 R +104 0 R +105 0 R +]endobj +107 0 obj<>endobj +108 0 obj<>endobj +109 0 obj<>endobj +110 0 obj<>endobj +111 0 obj<>endobj +112 0 obj<>endobj +113 0 obj<>endobj +114 0 obj<>endobj +115 0 obj<>endobj +116 0 obj<>endobj +117 0 obj<>endobj +118 0 obj<>endobj +119 0 obj<>endobj +120 0 obj<>endobj +121 0 obj<>endobj +122 0 obj<>endobj +123 0 obj<>endobj +124 0 obj<>endobj +125 0 obj<>endobj +126 0 obj<>endobj +127 0 obj<>endobj +128 0 obj<>endobj +129 0 obj<>endobj +130 0 obj<>endobj +131 0 obj<>endobj +132 0 obj<>endobj +133 0 obj<>endobj +134 0 obj[107 0 R +108 0 R +109 0 R +110 0 R +111 0 R +112 0 R +113 0 R +114 0 R +115 0 R +116 0 R +117 0 R +118 0 R +119 0 R +120 0 R +121 0 R +122 0 R +123 0 R +124 0 R +125 0 R +126 0 R +127 0 R +128 0 R +129 0 R +130 0 R +131 0 R +132 0 R +133 0 R +]endobj +135 0 obj<>endobj +136 0 obj<>endobj +137 0 obj<>endobj +138 0 obj<>endobj +139 0 obj<>endobj +140 0 obj<>endobj +141 0 obj<>endobj +142 0 obj<>endobj +143 0 obj<>endobj +144 0 obj<>endobj +145 0 obj<>endobj +146 0 obj<>endobj +147 0 obj<>endobj +148 0 obj<>endobj +149 0 obj<>endobj +150 0 obj<>endobj +151 0 obj<>endobj +152 0 obj<>endobj +153 0 obj<>endobj +154 0 obj<>endobj +155 0 obj<>endobj +156 0 obj<>endobj +157 0 obj<>endobj +158 0 obj<>endobj +159 0 obj<>endobj +160 0 obj<>endobj +161 0 obj<>endobj +162 0 obj<>endobj +163 0 obj<>endobj +164 0 obj<>endobj +165 0 obj<>endobj +166 0 obj<>endobj +167 0 obj<>endobj +168 0 obj<>endobj +169 0 obj<>endobj +170 0 obj<>endobj +171 0 obj<>endobj +172 0 obj<>endobj +173 0 obj<>endobj +174 0 obj<>endobj +175 0 obj<>endobj +176 0 obj<>endobj +177 0 obj<>endobj +178 0 obj<>endobj +179 0 obj<>endobj +180 0 obj<>endobj +181 0 obj<>endobj +182 0 obj<>endobj +183 0 obj<>endobj +184 0 obj<>endobj +185 0 obj<>endobj +186 0 obj<>endobj +187 0 obj<>endobj +188 0 obj<>endobj +189 0 obj<>endobj +190 0 obj<>endobj +191 0 obj<>endobj +192 0 obj<>>>>>endobj +193 0 obj<>stream +xÚíßoÜ8’Ç¥nõKždOún§;àâ´wfŠmí](IîápÁNfn³3·™Ìö¿¿þåný ¥ª"%Q^s€Aân~ÄⷊdQý××bµùïZ|{#Þ¾þˋ;ù"–/þ*Þ®¾»úv÷oß½»Z‰ïÞ_݈››ë«Û]­oî³ÿ|óñMúowbý¯«]y»+ïvåý®ÜïÊwåÿõæ£øúå÷ÏoþCܾ½~óïb}}ýæîÅ­øøð"šž¹ÌŠ|¸Y,gÛ²ùÃâöaì\ò~qzªrv~ù0N.ys¡F*À-nGÆ%oژËùe<.<Ôív \÷¹ø‹Øq®»Ðã•óµÃ\7\*›æΌ•Ý1³Ìu/<óòMìWváY)þ¥S\7žµ2Y;Ã%…g³\:Âe¬v‡Ì—¼ð¬ÿÕà\YèuQ¾˜ëÎë¨Lâ!¹®½ÎŠ¿ŒË²Z·±6åÕ \2ô<ÁÀI!,——½sõ‚Ń`qÀ` X 0pZ2øâãÀò¼eO\û-3Íæêk÷Áµòz/“¸>x”iç\©7HyÙ1WÃEEp_áYÚcB†vÀH4ƒ:Åè\™7hYwÅ˅œb0‡Ìñb0ÏE{"—Ëó;àpyu®Ôs¢¬-sÉÐ ®‰e®•çH™[åJ=gJl‘Ë+D91Wä9TÖÖ¸2—°Z¥Æ'¨¨F(˜¨Fiàµ˕¸†Õ2`0>G ŒPã1ÎÇ%]ÄjŒëaŒ˜a0>—ŒšaÐßp/¯¶ån{ñ¡Ûƒ^†Ë?UŸäÛ{ t?\~CÒ¿¼¿èfÀ ëá:o]*Ý - ¸VÝ UqÔÖÃzèp¸éǒ›¼fs±C Zº8“lÊåâ†ôô܌µdˆ™\Ìáb¥Ss†,`r±yn6$cÈ|Wҍ¶[²%‹+ìˏÞ,´"õ`WÃ$흓l°fp‰Þ¦?ó* se`‘Á|:Yä};W$…±r4s „E›R¹’ŒcŠ1‘K …E›Ó¸2+’ ¹0°·ðz™[-©‘!‚µHÞ2éö՜•XgŒÊÊàÃÁ’jø±}.Bb<—4ÒLKÆ7D= :¹öåÛÁÊ +e’wT×Á†Ìv2¹h“aŽåІrÈ5WÂZ¥¶†ˆ³WF6Ãf®´„S㒬͒§k@”IŽç’f¡æ:ši³$Ãõˆkå€Àµëx çJX{v8¡¢l,)\pø —díÙµö²ÆÅH_læÊ¢ á:t‘¸g¡º4٘ä®ü ô:.à8%(“šlÌh\¥×qEœñJQžh²±¤q”^Çræ—D={ࢸJ¯áJyg!F²mLˆ\¥×pE¼Íþ¶ç?-sIÆôjåÚ+½†+äÎD˜‡$ÙXR¹öJ¯æÊ˜§ Æ1io#§rí•^Íz30‹¤Ê\czµsí”^Í%˜™;㘁Et®uGúuå‚aˆm·.q±•˱•‚k×{¡âÚÛ½d„ÑM DQ±úÑÅEñË\§NT¹Ä^“ÝWˆ€XYe®eñÑT¹@Ãõ8P„Óì6̬ȅس™jLb^TÔI…+Óp%žŒnˆ B€ ‡sILë©îÖ¹V}Z‰ö´%.Á‘ÒѰ,ø¢W¤ä’ǬȆ(v„èPkA`YåJ•\ɱrB}:øèp¢÷ýÛWÚ\5³æ§ª\«£ÆHz¾UˆçÊ8^ùôþY^W”¹ +¿Qc_Ñ >:œc|ɬΕ(¸Š©(ÙWíðr¸ÆhS\çÊ\E½Iɋ0Às­X²Q³‰i^ç:Øj‰+,NXò"L>4——`ÉFuboï)ÖÅE®rFÔªƒŒF §ŠUÊ•‡Sìc¹¢’a'¤þZµ‹¿Ó{M^åJ.Yã +K–—uª è¨Wo'ÙîŧþyWH©\ SË~²ºÇÕÍûù¨ +`e~2J.Á‹¢œç +yQ”ë\ÒDæÊ åÐU®”:Ε<59wàoÚ¨íU—›Zéâ’õTp%u•”[ž`¹¦šðe©â +8\‚+¬?FË\{ƒÕåÎUº8ápMê\¢áŸ…G»”[Ð\K5—¯âª^çCqÕîå|ëOîÃÙà¸f\»?Ý ¯ÔƒYÙ±Ä*®¹Ò•ãQD£¢“yW½Q¤t°€ £‚ÜDÃcÎm¹‹õë|®z#¡tD(®Š+Uû¯TG)®ó!¸ê´\©%®HoܟJë×ù\õF¡Ò¡¸æ.éÕ¹q¢¸Î‡áª5Òr%ü0ªÐ‡ÃW4.ÑëJÅu> W­Q±úéQ\ëÜpý5Wv±vÃUk¤å~•«F³«ZëâA´i\ÕF\9š+Pýԏ5]¬^çCqUi¹"‹\kõ(Æê.V¯ó¡¸ª´\+~x˜« N³½_ëbõ:Š«Ú(¬¤©¹„5.?ÖpBÕR+×ùp\•F|® ’Ë_~zðˇm¹º‹•ë|8®J#QPìWh‡«XŒ7öہº‹•ë|8®J£Z•`¹‚·NÉU\…÷C)º¸m*W¹ÑªE.¯[®´‰«|É¥¸Xìâ +Ë53âÊtñü1¨D®r£¤:UÂ=—ì˜Kjnq(®ó!¹ÊÒŠdKË57âʹ€ÃUj$+¡yâWÆá*7 +ËL¸Ús—r•®óa¹Ê"E2þ†+–+âp•%§SåÓ&ïà\)‡«ÔH{™㠓e¥.Éá*7§ó¯;ÀwÉU¼Î‡æ*7Jjç•.p%®r£J$(v\&ËeWØÌ•q¸ÊÊ+ã`åWá:ž«Ò¨4`qÔ#×ZßňÃUnTN#‚Wëö†oÈ%¼âíLðS¹*>‹I?\Ç7hº(9\ÕFw…­ \î”û]þá7§÷Ï·r%Vï Bû6Ûèr{÷\â™ë™k \Ó'ÊŒ“+|æzæzæzæzæÂq͞¹ž¹ºçò̹6+ô½RJÝa¹îvï0ó/1Ý¥Ô˜ë¢z}­ü²¡ÂæuÕ§ê“*OqQJÛ;c.QKß(ç鏧êu\ëòfhG\ê+šò˼²ÓaÇ̍ªV®eùvÃ%'Jå&Ç-~‰ºyÔÊ5ïƒ TKkQœ`•ôJ]×,/MÍn¸BÕQçAXJ“©ÖepeKé„+{º®äxP(¯ ZÀSv…².Ÿ+í’+*œX¯NÞ¥à²NÉ皺ªm~õ§–w’.¹DA äiV4°ðBfM]—<>ÝLâIg\aqNT”þdööU2˲+Ör5Õ¥pmLp’öO;á*»WhÝìÔÕ¥pm$ÃO÷ŽÑ+Æí¶p5Õ¥pmG:ñŽ/ªëŒkR²-¿‘KW—Âû˰~—ɽQúgѨóMu)\ÉþfÍĜkÙ¼üš×!S-WS] +Wzrêq%Åñ\U>¦ÒÙ¦º®ì´hä2¹‡¸oëߞµ–Z®¦º-ñ|ém[²|*hÀ5o=‡=Bê‹Mu)\…÷ÂvÇ5¬Õª\ uI\Çet/;k¨Zåj¨ËàŠÍ¹f¸t›jè_‹UôuI\Qí'pez…©qeÜý¨2ŸJ#—Ñû7Ê{1/óF.}]—îý¬v¹ +½Ì[¸´uI\éѧ7smdo½ÑE¨=(1©kT ßÛs(”¯×ëç«ø ß³äl1|/Ö3Wÿ\í¯['Wôˏ’«}ƒc=J.“ó3Wÿ\F ËQsÍFÉ%ÿa¹‚Qrµ/À¦O”k2N®ð ¾†ßÇñÌ5×ê ¾¸ïñYŽ’ ž(WòDÃï5ª´½ìunø=tC•¶./qßè\ •Øár.j“ºØð{9‡*Š+]ÀÑJ`¿÷Öµ€C´Ùò{Š]Ûi Ûôù½Ò®Š ÆpÈV‹ü~sÇŽÇ5ºï£OZ‡0іsŽZ§ `ÌÕ9Ǽj•9ÀȋsL´º%À¸çXØ: +€âẃµ‡}€²WÇXÖ®€ÒÇV–i»zÊ8æÀ’öÎê8æÀ¢vã”Á:¶[µG}€Š#s`¢]ä'œn =¢¯€stN }†°-À¬SBŸ"´p +ã”Ð"H\U§„>BtCë’Ð „ir*ºчíîë‘KŽHè%Fº!Ç +ýl4r¸,p‰ñb‚™1€ ¹Ä£pc…Þ‹úE®t<‚ˆ2,ÈÑBïH„˜¡">ÈÑBŒDgE.„Ð;"€²+ÈÑBïˆp¬P:hõtE8BÄê«À•Œ$’j‚ýQäx¡F!“2Bè'£ Ì…غñG!³ +—‡p„8üƒp"âÈ‡xÃuB8R¤—B „#Bör‚ :°™ÝªÓ*BðÌØí +È)‚8sz-k\Ñ&ú.(öCéÑw­!' ÇÐ ýŽÈIÂ1ðkôS—p~‚áï€d¼CO°z¢@NŽa'>r’sx‚¥ø¥bå'áôH*:pˆH8‡œ(N0Ê!ÐÆyÐ5å ˆ ‡Ü䈝¢Ž¹ÉAÙjâÄPé3Ê$âH¨ô¤i 6Né¥k@UÒÁvÛ$IӀ:53D„-Mµ\+w ‘¶ý9}‚Í5Ãb,d—>!&4Cò +g C\ў7ЭxC”ÄÐÈKœa 1!>nÈl€Q§äœ ¸h†¥•pLÿ‹•„ú°!çL°ÞW͂ªf³&XÏI–)Ùû@Κ`=»°ˆ<7€5ä=+‡¤÷XS´gå`D­ÀYn÷súÌÎöHÏ1GÊ0 àMÒ^¥~ŘðÀ|<=J½äR°0qí{±;ÂçT®„4`6µƒ¢Y™KzÉÐ|€#· &……Kæ`1 "Íë9ƒ‹ö ›òMÏRØꀅ݅‚U˜«âµëU‹`4,}<Vö +îdÝ'–^ªÀV”v{Փ6ƒEm2U2VÃm4°çùOÖÁ³Å,¤~PÀæÊCXõ›ÎQå†þ1k>WÂâòü[ê`1,¾)hãb˜çÇVóÚ¨•+ò¸ÿ¥ó÷‚5s.éñË9ʳ Þo_q Øvž]¶™ã=“ªeùÐÎe2`{´ýï¾ Ù¿wnÈE]†) òò¡6nò~š<®Ü”+ó씳óÅbñêaSî‹‹Ðð·Í¹l ˜õҖÿˆá’rÍ-p™Iâ ÅãroÀ–V¸œ°ö­/—Ûp!¹§6}Ć’+]âZÛãJÇ5\h.ÖNGGÛäʜášç6¹œÑzÜñžK†cÑxw gÑ q9!Øó^ +—Ò¸°DôÑ!‰kpKÄgи²‘X!•kàø—p€MäÔ)¹/T®!½3åø‰Ê5``OJš#s 6Åhi/t®¦1±ŒÁ5Ì#ží2¸™bÔ,%=pÍ`sõ®ôT9WÏÚÁÈdrIᮚpõ)ЬÔa.W`¼L26#í§ÇeÌÕÓbŒyãÀ€«ÿìs/R˜puoŠü,M#®®Á ’O͸ºUE“daC®.´Q´)Ww`fÉøÆ\äêŽ&ö¹ºX¶¦«Ûá²/‹æ÷&¬påÒ®-^š÷Èׯí Ùd»Ã•Ë wË&—¥!;_ç®qåòÆX_Ùê‹M.~jõêÒ^Oìr¤W#R·‡äâ’٥ꂋCvþÊvºà"æÅû‹ÞsÑ ×¦<à²ãýóÛN>¾3®Ý¨µäÙâ¡«Ïî’k7l7‹3õ8]>tù¹]sín{Ãaqq¶-ç‹ÅåÃCçÙ ×â/’wòś?¾×ï…üA¼ûîê[q»ººòûºÏ!÷¿þòÃO?þþåÓן~ýEüéÓ/Ÿ~üü—Ï¿|ðó§_þYþϦñ­¸¾Þ6¾~ûîê­x}ýöêæ±ùëû?Áëë«Õ¶âëëÛ«kñúæÝþ·ÇŸ~û»È~ýáëÿ}úòYÀ—_¿ÿýÏ_ÛU¼}{õ®ð{~ýß¿ùéÇÿþºéãûo_oþ÷þ_ćŸéö‡¿‰ôóoŸ¿üíó÷Û¦±Üý?ÚiñÜendstream +endobj +194 0 obj +6320 +endobj +195 0 obj<>>>>>endobj +196 0 obj<>stream +xÚ+ä2T0BCc3JÎår +ár á +äHÉHendstream +endobj +197 0 obj +31 +endobj +198 0 obj<>>>>>endobj +199 0 obj<>stream +xڕUMoâ0½ó+F=µRɾÙ[²Bjw³$­öÀÅ$pkâÔv@ì¯ß± E-BH$ž™÷Þ¼ñðQó¡AzMhu!^׆QíÛdþ¢”Nº½6DÉ­a,s¼‹ÞÊӎ×/Ï띾WFx>LÌ OyÌ —YÜ߯B›Ý24Zq ±ÌR¾,” …5ËØה¹`$2.Ê'%7F“ú4ÈWV†/˜æå¹±³ñN¼É…“ +d։œ'ËËÁc†ÖÇùíS0¾‡Ùdäû½ÁüîB:F­i¬a(düNaáóОZ„‡<é%º wT ™l`BËH]ävÈ´-7+PH>ÑCZd±5‚ nvgûÒDµe+Õ{©8-”Üj+Ù²¤6a¬xnŽšP»Ü » ‚1݈:µ ? tçvVÎs%’LáŠXž‹j#h(²Ëá½|ŸZ0Þo€ÿ¸Q—ÖÉa“PTK–ñ¿¤„tH7 ©BnÝ`£k§þ^ÅP³OÊXóf·_™Ðn¬ގñ‘á¾+粨(Ì0E…´­ôU©-JpÚ Ï™Wå·)?R²°«e†Î/º/ÄÂÎÅU•:Vú~ƒÌèӘ\§å*ü’î‰Ú]•8¤Ä‘L¬s3ü(¸r}¨ÀûUT½r¯Ù8ùk÷ÞÊ·öù1ªý®ýÙf%Ãendstream +endobj +200 0 obj +779 +endobj +201 0 obj<>>>>>endobj +202 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS041׳P072PIÑp VpÎÏKËL/-J,ÉÌÏSðMÌKLOÍMÍ+QÈIÌÓ Éâ҅èхj2‰™˜˜é™)€ù† +ÁÉù© Q×®@.Nu!^endstream +endobj +203 0 obj +117 +endobj +204 0 obj<>>>>>endobj +205 0 obj<>stream +xÚ­•OÚ0Åï|Š9²Ò&K 7 +l…T´) {ââÆp•ØÔ6Úòíkc•V%]å@Æ¿7ö¼?ZtÌÀ „nòªõ)k=½ÄĐæMЃŒ¶CX`yŽê!ûîJžýÈyϑïÊüÆË$…‰ÈwrM4Ü-èAËþ+Ï6…(KñÎøÚ-¤— )µ.…o{ÐóU]3tàü#?<³Wa×Êm«àç‰ø¡Ó ^°õN:½9ád– IIø5ß4tÄßà³Éäžî•Æ +f\£,HŽ0AÅÖÜÞrɶ糹G"Í­„ÿ³…~'aD+ƙÒf/B*»—)ð¯·PÓ?¤õd~ H±–¤ª¬ w.n¡SÌw’é½±ïVH݀›%·¸ª¦I—˜ßRáÿŒímrûf¨ÖÛ¿Mîœ`ÏE§×)áUoPžb¬þ1Â\pï*Æ +l ™áÙt:…  üÞc° ç›Ý ¡×¶ŸU›JRèÕÃ]ç9K’§ÃÌG”2K$%¼nOèdxÆ^‚fì)ϵ=N!“„«» zbͪmyøÕ²ú¼c›qæ‚byh(Ŋ˜#ÌÕ] ÅËØ<âGøÂ8º1X¬ŒM̵ÈÅÑÛÑqÑÑ{aßúŸéE?6²æU×~žf­¯­_Ð&Ùûendstream +endobj +206 0 obj +522 +endobj +207 0 obj<>>>>>endobj +208 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS041׳P072PIÑp VpÎÏKËL/-J,ÉÌÏSðMÌKLOÍMÍ+QÈIÌÓ Éâ҅èхj2‰™ê™)€ùF +A©i©E©yɩŠ)×®@.Z#bendstream +endobj +209 0 obj +122 +endobj +210 0 obj<>>>>>endobj +211 0 obj<>stream +xڍ“Mo›@†ïþ#N‰äÐ`üÙ['’­ÚB­rY/l»ì’ý¨“þúÎ.’›T•9xÅ;ûÎ<ïð4Iàš~ ¬f.7“›|òî~Éò’Þ,Wsȋ‹î…DøÈ«°Aå.óï½n¯{åÕb÷Ú8­0ȝ6/9ã¹óûŠ9$É Ÿ-{ýã5Xí G(ƒ‹­™”p@h%ãXëWş+¹6m«U!TNƒ«©H—îÈ vZûb6 Ý"µª,©‚?¹&i< ®‘å5^¢‰¦Iqྵô/!×`°aB‘_Ó2'ÔÚQ¸´,ÐÀ·O»‡®ßÞÌNaìP±í0‡ÒîÌŸ9ÒX ñ®™aÜ¡±@>Uåêø´éæ„vYO*äaßdš8íȳÐ܇ðSU@©MÃ\w²P åFè@|h[$ºÏp3…[ÝaþŠOžæ åöß-¦T¢JQyCдúkiþ»Ý!~¯î1×Ê-A—Ý‘l¸§UPö„¼,d}ò”îí>‹(ÆÓ^ĸ³,Î,#Z þ£ƒõacØNÊIUaÇȗ9hI)x7žÎT(u”$UƃÁi´íÀ¼gAO×ù>V„ð¹ôÙv–Aq¬…Öµhh7ƒ|·{Ÿi[¤D)~…D²á‚³‰¶ø“v¾ žÑÔz$ž®N_ék_ô|}oHFïá|—O¾L~•BN‰endstream +endobj +212 0 obj +542 +endobj +213 0 obj<>>>>>endobj +214 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS041׳P072PIÑp VpÎÏKËL/-J,ÉÌÏSðMÌKLOÍMÍ+QÈIÌÓ Éâ҅èхj2‰[éY*€ùÆ +n™9©HAò®!\\»Þ% +endstream +endobj +215 0 obj +118 +endobj +216 0 obj<>>>>>endobj +217 0 obj<>stream +xڅVMsÛ8 ½ûW`zrfmý‘÷–¦»3=µ›¸³_h ŠØ¡H•¤ìæßï%Û±R¥“ÄÑð<<€þ9™ÑüÌèfN‹kÊëɧõä¯V4[Ѻěë›%­‹)>¼k·†éç#}ó.ç´}ºXÿ€Ç’f³Îãr~%Ÿ;zteÜ+ÏCçÍôÝãúáÝæ‚B¥Œ¡-Sh·µŽ‘ âûgŠºfRÔöä<íØøÇ¿öš-Bãeã@kIag‹l.a÷:V+¦ûïß)ô)dÇ|ÊþÈ«VÚFü!¬¶@,TT[˜ˆ³L®LX¥3ÆíQ-…¨"‡t~u*v–‘<š¢.ҁrã@LîêÆp”ÈÁ™6jg)ÏG]ÇÝçn*zÇ›å¹M¥ŠÍÔòžä!XUE¡^°P:_+¹#µSÚ(P¶¹ˆË—åÉ<ö±étô[Ç+ò¸ Y§hì*»í5³Xu¸ËlF÷FAX¥ÎÕ¡æßÊ뿊¥eñ,©ÑsÎ -T·!JZy‰§*þ¾±Â3ã}àŸ-¬ÚJAƒ5Û8ÒÉÏ.oåuÇ${ïüHó¾[¡˜¢u#**µëâЪ»ä!þÕ>~yÝPpr×‰é‡ u­k&8!²€}&F½1 çÒÁ.ÁZå<ÆDÿÒÖRð`MÄò ¹Ô#´Ý5ÑØâåõ!0¶x†‚K•Ÿ$7§/zõgÉ}EÓ9I+)Ög¯µø‚.18l#Yw—]r›iÀÔvçÌî°1`:(ûÐ ñ=ab©UR«çÀËYÆÞ©[Û×t®T¨±_°ÔޛڍÊ0²ÞôlSc¥U +ùmfº§›‹÷Òr¶O¨Yí5ZèXc‚Ì1nOÜÁÁ°àb§té뾌îøðYíYfv€óöZнóØ#oªádÒ&!¯¸h âÉ‚ظž9Òt|N‚éNƒ_r{>i%y‰š»±•q5ÝÅ3ˆ*Ð]‘ÐW}àJ…£ZØE º”‚Ì]_Y_GÏõí‰ÂÕBHÿã׊åí‡l{XÞÈýßëÉ¿“ÿóÇÞendstream +endobj +218 0 obj +873 +endobj +219 0 obj<>>>>>endobj +220 0 obj<>stream +xÚuÁNÃ0DïþŠ9–CLŒ“^©à*Â|€Û­Qbƒ“¶ð÷¬®È+YÚy³;ûÅjzwªT?²ÍnŸ¶÷¼ƒö¤©¶å +Ún$—xIsð¡7sHñF*!Ä +V"‚@}r8O.#e\\´ô… q±:‹ëÉEÌÄøð]s1a0‡Á>øEú̉#®fBoh˜ÅágêrN™¯Ë»¿åB¶Wu%³ÝìÞ÷oØ¥èÃñœ—¨x6ÑÝèâŒý`–èÕjªÚ¦.¦®ô¤¼Aýßµš½²_¿Yçendstream +endobj +221 0 obj +216 +endobj +222 0 obj<>>>>>endobj +223 0 obj<>stream +xڝVMSÛ0½çWìpjgˆ'’Þ€N/”¤\Y^'flɕd(ÿ¾»’çchÃ!±õôöí7¿1Œè/†«1L¦ ËÁÍjðå~ñVL¯.`•~º„¥ÎÜ«0X °h?¯žò2šìðrtÃ#›k?ê2A“«uÀ_@7èñ4 o-–P#pƒ8¬„qðÒ(Oé­p˜Bò1êԂÓ`°2hQ9º‹PŠgmΡÌ •B%œÜʋf d9žDc¶¨í× ms~q ¶öFÌž=òä‘çÝ9£Q4ÚõrÈT­Ÿ7èÄСu­r˜â™«”ÔçY\U…*¥xy +tŽœ¿L…~ >Hê¼H›Øü¿þÄÓì{‘Ä'ü¸†ÛÇ%X%*»Ñr kTr“iH™{ƒ„¼õ Èr%ŠÖeÿÆçšè¥˜)1ÝúØKVг—3Oòš»'IQæ%Y¨t®œåz(„ $5…ÖX©©@>£—øiôÔ ÷òDLî™ÜµF%QòÆqMg¢.(LŠ~Ú¶‰l í›uXҁ4X"kgwv굉Lß3ºø{aYæíðÝ-}Š6_+Ðøæ¢3ڃSß#§H¥«BÁãï©9Ø=ÀÝç¸G^¦7H5!uYQʰx#DЃi×£ÿ ¢g6ø°×Ú ‘}§çÃ9ojèsŸjP_¼=¯ß!nj\¢Ô$â4 #­ŒNké¸àáã=”B° ԋ=ÒcWâ.zh¦Ö.ô4{ÿÊø` :ngâ.ôû¸£ÝrñÍ6™·ëe ßÂÈ¡»G÷Êvcmǭ݈Pe½ÅÍkk)ÑÚ¬.¨bÛâM»–rF×IÁd•6.‚kbÒÉ3õ×b¯FñÊÚ ÆgyñÞrЁ·¢f¸Ji•‘†’>ŠšQ~´Ó*[›fžX]Ù²§X$=¦ÑM܅j+Z9§öï6N.;±\à” nEI-l%í›Ø·ùö&›€E!Ô¹?.W‹!× Ü Vè™m/FRЀåêÁ¯ñ¤Ðs3?Ã2š"YZJMôÆÝYçÈtü“r1EsÂbÎÏw«ÁÏÁ_øe¼?endstream +endobj +224 0 obj +845 +endobj +225 0 obj<>>>>>endobj +226 0 obj<>stream +xÚmP½R„0îyŠ+- ǶÞh§sz¨õ^XŽ8`6̍oï,,œ¤Úý~÷+QÉS°-ã×crß$·w vi M'»²ªÒšöz—ðJ!ÓMó)¨”Z1›¼”¥`>z²ˆƒ±gè‘áD2Ðnœ +ÔÏZs7Ã7 Xº@k8xsšƒq̈gà=a$tލz={O6Àþý(zíAŒÕ6Í£ñ[œ¸wá*…g“wí¬I¿Fîq„j ìºpAO¢aIj]€ ™Å4úá$“7’âXšqº¶¯Û«¢’SÕKŠýÛá{g;sž=.öOh¥Ò£´‘»Y)›*Ï"IeqXäuº…ìŸC?4ÉKòc„endstream +endobj +227 0 obj +287 +endobj +228 0 obj<>>>>>endobj +229 0 obj<>stream +xڝTÛn£0}ç+æqû-)Íå1‹’4RÕe•öÕ5êÆÖv6Êßï8´RoXÚs8sŽç˜ßIWtä0›Àõ¸J¾7ÉåzùšU¦³šöÛ6Ò8Çìé¢y7Ù|€¤7óle94h•0SÈó€ Þt2 åP*¾(-Õ,m}rU„sU——Õ8骪Ü!þÜ­‹0¯›ïZH„Æ2ív،7ÜÈÛm•nîÆùnñ(Ñû´b|„n,ëŸwp÷²)‡Oç¯ÔaÐŜ&üé/QÌ + +ÃU(äyx±j’ŸÉ_Ç68Pendstream +endobj +230 0 obj +425 +endobj +231 0 obj<>>>>>endobj +232 0 obj<>stream +xڝ“MSƒ0†ïüŠ=ê,•R<öÆv`‡ø"M16$ÒúñëMPÛéXrÚwöÙÝw—/„ùB¸Ží«oн«,†0¼±¡8‰‚ðúâùh–_â'£GGÝÆAÔéô•S­}Dª-Qk@Š M̤ÐJrȉ¨w¤¦_„Ÿ +þ ”Xþ£ÄR>œƒ_¤8ë‡/,JP ©¨™ Ô°kÀ¤ÝB&Uåä"t¶kÖ2‘’ZV’»ˆåê7"ÑL +¡ÔD¬-¬TMûè;Gó~vn&?Ø:'´q¢ŠE‘ö³Š׬¡kFà`BA‡ô­z4ÛrYê¼4dÖü—³B®‰‘luY)ö¬sÓ¶ ¸},‹i?µ¤joHm[Ûì”Ëjë`á ;N+¶gfÕã°"¢Ýöé%ßyã‘ù[GÉMÛÌÙ=*­SVïTwfÂtÔPaæå¤Ð£±ÉòÇÁM +‡6…I0‚.0 †0©”ïMk¥{wÞ'K­&sendstream +endobj +233 0 obj +381 +endobj +234 0 obj<>>>>>endobj +235 0 obj<>stream +xڝV[sÚ:~çWì0}H[s <•2‡™6Ós Iò"luj[®$Cø÷]I†0I§‰g­½~»ûI¿j´ñ߃Aü>IífQkÝ ÁÂb…;ýAáÕ LDÈÓ5üÇ~å\²„¥Z}\ü²]ð<'Ûìô‰•^DL1œ†,i@&ņ‡ B¦)Y<] ™PÍE +ø(‘Ë€Á +÷Àmhcƒ¦!„"ȍ'ˆTã 11 gÏ'WÏë}Äϼ´>½Â§¿óybäÔ&À-Sä™.ºÈTpŠ"ïjOÅÁ8MŒiJÕ'h¥·ëü]Š0´jX±âêܔD’¾ïôÀª¶ÂJËܾ +ûÚ¬ë 3ý9r„©áZÒDÆsnж§“ÈBuøÖ¢ù€¢š!õ˜Ž87vÇph\êۘn Í1R¾Ì-ÒÆTŽI80¬U‘kÃÔá¹ÅRCýël2½ŸO‰~ÑuØFÜLg$ò8t¬°dÌ4°% GÞUébW»™€ÙêõÕ4{•.œÒ&tF²˜Qåš ÷ÜÜ%´ôèÝJš¿±ÖéȞ0ðõ0ܳ׬֪vZ-ÛízÝŒ9òÔðÈÙn%ß wÌs®ÎM·ZñÇ»­a¾Q¹‹MÕ:í¾ßoúŠ>ÌÇ”á£À¼Fð|å·½çàüæ°ßö/$ö ï8æy¦š†ˆ¾˜r]-ðôô4‚HëlÔjm·[rAþT}RÌøûEÚ«÷|…Ñ7Ã#—å;ò7äý +yÿT¾u|f5 –O­¥ÐZ$tpiin^ož\8£û­럜q¸£(“<Á¦z=‹Iį/¸õÓúeØs¸E]Þ×¥³ºW\¨.ÝH»ƒ.^ÔÚFƳÍ6]Ôþ­ý_AJendstream +endobj +236 0 obj +1067 +endobj +237 0 obj<>>>>>endobj +238 0 obj<>stream +xÚÕVQoÛ6~÷¯8¶,ZާëKSÈC» õÞ 4u²¸Q¤FR±½aÿ}GI¶c5]Öíi¶`ðHÞÇï¾»£ü[AL_É,<¢è½_öÆwS` –­Ì®§Ñ5,Ó g*+2©ð-È |Žà-'ӂtPHç¤Þ€ôÁ* YkE;rîA˜!çֈ”q4r[C NÁ4húf°ü…ΏaMâ4bI§a)&“c|yfÂ%,¤þ«ûô†)#—ûB ‘;›Ïçãøj̘Ä7Óðå_»^õ£ظ¡1v¢Ï`ˆ$óhÖßà]¥…—F»ãΤaL(ÓëèªÝ1øÄ ¦ÙvÒu4™5`G ØJŸ‡2k®À S"¸œ+Eºà¥ô\Éß1…ÕEÿƒYæÒõ‡P¸oFŸM>§ÓÊ!M¡ÑjK×hµ?Ùê‰;e8¼¡PÚl¥žrrûóÃgÚ£Í8e_ɵåvىt.EߓÇFêC¥ÅLî`klJ•Ù¢ÜaˆDT¥;Es°êˆú­ó7õRF|-WŠBqKZõç^Š>p*Z8]»W:EK¾Cuúm(Ð@Úu(ÑÔ|ñ-Ëz؈NCwPý >•ý™ÂH&ÑìPø`DU üŒþf},8é{Ðûà©…) +äÈ)ŠÜ +ס·¡ùêÎ:¸§ݰž:v¨Ôeå)±…ô_M}Îõ~5Öòù™ÊÇG®*Ò®»•†àJ’R#uflQGI})¦ÿ¡Ë_·iX]¬¯a·¦ {xÍün5è¶sä“ñèn@ÏvþÑ>3šJ‚L’5|Ɨð#Q¸×TCA*­F!ÄQ ?¼#ZôÃhÜ>FÑ ç€vOh'Rµ…Ùµ0´­ôÇ9ÿ(êdÑWV¥æíÙҟ/Üq |¤²6éßßpÉË7\ sjN©ÿqÂ÷4^÷~{¹ “ïkâŽä_6aëü?iÁñÝu+cŒêc6ï2Z¬ß·FgrSÙñ#×|ƒuüŠ×ŽØô yÞLâàĦa2¡ÿ čôì9éËÞO½¿ž‹iendstream +endobj +239 0 obj +833 +endobj +240 0 obj<>>>>>endobj +241 0 obj<>stream +xڕUMsÛ6½ëWìèËQ¢>,Ûi‰wrhêNԞ4ãÁ¥„”­dúß»DY¤•J3¢,ÞîÛ}»üÜKaLߘ^/{o—½Ñí®’ , ¿wq¹€e~6:,ÿîa˜¦~ çð‚Kfíõu®ïÝFØÕÙjð†p£Ëªv;x qÿq5H:—»XµC{ J+욎ZëÖ¢š9xþÃïɵEc*ý€¶LÖøÆÉ~yMÑÑOJÿ;ø]NÑ1ð ôî Vg{´Ç=™uð¾¶Ù$I‡žAWEH»ÕàUëè_¿Ý^A:O.}-†TŒáô*™ùÓ·ôø‹Á2‰ö`9U#ŒÙe2ßÛ%)|d¥Pëh6Œ&ìÂm€ÁZêŒI°\Wvä„ ³J8&ÅÌ)àþ’ÔÜì¿Z3×^ ûÉ1‡G›èx²4r¬œÐ +œÚSË£Þüy÷ „rh +Æ¤È 3»&â퓍à(këèæZ¨H:Î+ƒ…x„>¯+Û÷´üŸ.µ¸×¢™À¯]¿‡` V’"Ì!ÛAQ+îyu|3³®KTÎG‹ +I­¤Uk52ùf‰¤æÏ+$½89#Í«ZåÔ\º–¡{@¤4h“[ÏÓç÷~{ Ô Ž™;:nø¾Q»½ëeÓæ£¤¤3°º6T§B2Gê3§oI ‚÷“žN’‹FÂx§yÈkòxRÉiì„?BŠÒ%‰G!0•?вÄ\Щ±ÐÒç3cÀuéÝCFìÿé$+GˍȨłDÿ×1Ìãaz¸Òju’3´Êñ*1ß¼6Æûõ‰¢6)b_t¦L8*Ø÷h¢E€ïŒš»ê£eþãÑò†òê+»ã§•êËÓ¿w}`U…d•Çـ@‹È&bwJÒÜû¦ÛÔÃ!?‡åÓ ú¦êæÿOueä·a[ìJ¦%­ ¢b÷×r,~Z+ÏßÃ~XEïô$Ü8" MƒÉ€óԞ|©Žn/÷\Ò4%Л> ïúp£U!Öµ Ôá7¦Ø;ÉB*†élA·†‹É8&lz*a³ÅŒŒ‚E:÷?zÿ…†•endstream +endobj +242 0 obj +855 +endobj +243 0 obj<>>>>>endobj +244 0 obj<>stream +xÚÍUMoÚ@½ó+žr"¨Ö|7§†¦·V©âÞ"¡e½€[Ûëz× Tõ¿gv×|*I.­@È3Ì{3oö­ü»ÁÐ¥Coh¿"kÜFÎ—.&AˆhasÃñQÜ4ÛBÆr$7U¡gf•Ðegææ:úI¨ Ø [X›píÞ$è[äm0ă)+aªRê}iÏwè¢Ýƒº0`øÆ³$_ú²>«‹Â¡gû”¦Ð;6ä<“zÅ);—HÕF–‚k‰MbV¨òX–Z(jKÿš”96ªŒ5xãjF¸ˆææý÷Ò ašr­/\ŸÑ뮏°Tï¾:»àXöæßE¯ðýèm¾÷Ó¾Ýó÷’åq0ù™ûÿåý¨ïµ»GÜîâÿÜèãú°cä÷aÈ÷’qÚ§*_$˪tÞÀWžó¥tÇ}Ÿrç•6ëÕ…] bC›ìûA]o±Ás»‹ßOë×vendstream +endobj +245 0 obj +575 +endobj +246 0 obj<>>>>>endobj +247 0 obj<>stream +xÚµUMoÚ@½ó+¦9 á£i„¤j¤6MWUU¢hmñ6¶×Ý]—Òªÿ½³þ @ J§};óæÍ<ó½fC‡~6 »Ð€×ΜZûõìckN@wƒáЀã×Ï(2‰Ò,Ѫá|+p=«[àZý‘u\â,®X̓yëƒm— îÀêÐ$ŠÀ+“AÂbT BFA!KS”S ®CÈ¥ò„DŸnõ1…¾‚YýÀysys7}uãL®œƒ#Sª¬|s=qÖ®µgÍm€O(q $èaúéúx¢QÌCˆ¸+™\Bœ)MÅç<)8±äåVÍTRʟ†›Éu·Eªè.^e¦J#g™3L²%Ӝ8¯i¤èjb‚?PB*”ân„ @,Š~è=x!z÷4 p—yƒžˆS¡´vL°×]Mšbç£ʉÎK?:È©ˆ ÜHx÷AN1Ÿ3Ñ’˜ä„yájâ/‹tµiõVúUrÚæ`šßüÞ8™ 'Y–µõnSüƒÙçYÃ)tN€Ã+:(RE³zžœL݆*²qóµs;kÌæÕááÊcÕ>~K‰É‹ÎÅÝåùۋ“ÇyüÛëgÆun·¢U/dÉÕ³šóÅÞÿ_½ð*$Iðb]ƒhW"»ß£N™‘¨žî%¹NnG!!¦³ºMÌ7íH_<úv=¿BiãQé9Û¶É̓ãQþ3_|úCø<+ ïXÂæ¹ à:b¹a[vHoZÃngçaاP~gMà©}¨ýû‡Žendstream +endobj +248 0 obj +749 +endobj +249 0 obj<>>>>>endobj +250 0 obj<>stream +xڕV]OÛ0}ﯸÊ0š6´ +Û$`LBb[»í&ä&7­‡kw¶Ó&þû®í”,ác¬­’ؾ¾_çø¤¿: ôé›À`×ýÒEçxÒé}A2ˆw`’ÓÚî~ⳍãxDc{+psò3X%Á¦;Å»61ƒ3™¡´Ìr%ƒí°¶Ýٍ‡ÎöHHU†0*½1€2Ê`Ó[˜j–Þ 5`æŒÌ¦8ãJnç`çj‰’Ë™·¢‘K\b 2ðnÉRB®„P¥qIPèPU¶a,ÓÖyhì–[Ô>BðÌdÜ÷ÅPb;`–4oª ”mÙù€KA£¬é¸=ää¶Úu®Ì†Â4§B™¨Búþ„öa!˜<­'nð»1òaBo ΕZºp+¦a«×0kîémµ|lÁ…VT±¡Fª)m_1Q ´Z–VÁh4Šã¸½í¥ äJÃÕ‡wÐ?o!é÷ýӛ7W›-ÛvQ™º¶snÈÁÕæáÓ«Ì>¹zßß7‰Ùu}]SsLÝØõ¤ ®X\jà¢LEÛ¡0èîT‘»ñœ®Ž4Q9ç£ö>¦0% +·¸q΂Ê/¸£Qdˆùé< +å §Ã§žÀÈÒ9D)£ÜB6æ¬67÷j>…¨„ӚÝ^ò-pÚÐ8ç0žMN¯Ï>œŸÂÁ#pþÞËð¹ÏT#»i/Tå=P* +)gÿãó¾)p n‰›Â˜ZNnŸ—·JW N€F£A½"ÜJ¥3êoàMřm@›ÆW›Þ?®jˆÓN‡øm‰èȑ2]Ëì_<’lôËÉ +Ó³"0˜ø´dšçh¸‰éx³È¾ -´„oþÔ?[êEí²Ê×Z«‚ÂWz¡½JÜ G5^B£°½š›ÁžzWó­÷EÔ2/…ÏòWt„R%WôŽ¡ª@¸T–*DFóMeª”%#ìHÿîP+w狥V+ºÎ4[À5©Â‚Éôõ'®FÃïPåÕÑ#2ôš3—}:ŒÐ…Ä©æûJG»ÝGê¹>¹ä±nTÕ¦ýªü$Iâýú-òõb 'Jæ|Vhÿ‚OL²™—@¸Ì3­› ÷hWwo§ï6%ûnr8Ð\ÿ‰ÿ +§“Îçι¸j2endstream +endobj +251 0 obj +856 +endobj +252 0 obj<>>>>>endobj +253 0 obj<>stream +xÚí“MOƒ@†ïüŠ9êa‘ᣀ µåf¬Ïd¥‹b +‹Ó­¦ÿÞ]¨6Æ»lB6»ï3oÞxµ½B¼”u[i C^†±0 }È×g7ÉJ½s“Ü=n¬D'IA*©9Ï_4¢YØ.0ÏwížÍvMÃi²‚%I6—àtŒ“c´Å/Ÿ‘cG õ[9¸@&ÞÕj?²ëÅ7LVé̽£yoà‹ÂMæ²Ü5¢U\Õ²e "IS™—<´\[1%ْêV1ÎÒZ÷f¢ô'J½áÃVœ¨L++vµÙŒ;Ì]ÊNŒB÷ʯз¼|®[&é]'H§lŸX¶ß*›\S+ ";>zͅâ:éæb[Rݙ6}3áþӄ§=ùçŽ_~ô9=]c†C‘ŸS?ôíh˜Ææ`‘[÷Ö.Ë3ýendstream +endobj +254 0 obj +333 +endobj +255 0 obj<>>>>>endobj +256 0 obj<>stream +xÚ-ŒA D÷œb–ºhªÒµÝ™Tû=*45”Ðx}%53«É{ófüjŸ{wì@lÓÖd!¶ª¬¡$=V͵ëÑoÇaŽ:Á㤽Œ3>¡›´_ӓ‹Sü%ÉóXIUî°¼ 6}t4 æÛdp1¯Ú]†ÄÎì ý‚*;endstream +endobj +257 0 obj +135 +endobj +258 0 obj<>>>/Annots 106 0 R>>endobj +259 0 obj<>stream +xÚݛKsÛ8 €ïù:îVŸmºé졏m¼½»ŽÒz'¶ZÙn'ÿ~I”ÄLøy9°>šóýJ•ÿE- e‹ÍîêÕêêō+„+V÷…°ª”…­_Ýý¶Z~h‹î¾¸îöÇv<ü¾ú÷êÏÕUUVžÞDxûø&4 +«ÿØ®ïðù¡¸ ü'_ï¿/nL!Dè1<æ 7QÌâGä®P¦lr>H‘r»é¾µ4R*ìUߝÿJ¹ø—˜Õ„²AÓÒø÷]adi°A¨Z£ª½½­´QÓ%¡ë tçŸAÛÓ.PAÝùY±½ßnÖÇm·ÿµÖM]ÖKÒ;§Û8â¤ÛؘÕmШþQ§’Ó)’›º´9ÅHº}<Ûá ãóÞ@J ?:¹ȑöþGÛÿض?m-J·ã0V1®ñƒB«@ƒ²Šq®Ä™®«$²¨‚Wdh”#êu·9íütŸçM¨u©s`úÓH?£žÙ4‚ ø¦–CÀ‡Ïg|S+Ւø o‚º2>H‘ò±½oûv¿i3ztˊ?¿x)fò{ áç…{cã¸%îSMY Îõ?n “ÏúÉoª`´) ä@J¾D¤ kŸ×hœM´Ó4Ȁ¤-„cɦ‰Dn*»22Š‘ôþøµí sŒ‡,Q…X4…¡aÉ ó>$áCŠHÂùab@ŠŸÏ H2hÇN1 ñ²ñ%ãGi¢Ülý¢y4yxW¸h–) Ä õv½_iƒafÖV®\äšÖ0ÎSYˆìqBÇÆ™­ª!è+>¤a®*žöb$½ÞöíæØõó¼ "¸RXÏf@”#ðö؟6ÇS?³ Qauöü&c,¤S4¨ð¦øÜ· ‘(ã¢8rn»S¿!|hòtX¸Åg,”Þ8Մ[–ïp6©Ý˜r AÚÄGø¬Â­Yˆzè'3KB]wûûí—Só6±žp<µ áŒê¿0BÙ gŸ)È2Ùh£†dŸÏJ6ÚhˆíšN6 ¯¿CËø EʪïNŸ©|3yÞÿVíƒOC1Ò>¶ßºžØáLž‘PûH˜ÿ4#íCßùUùa»ÿ2³ªXF(,kÆït5f+hœ—­´4›­RB¨¡ÇÌêúaí5JŸ¸ØjQ«N½²ž¤šØ Úl@¥lªA.ae`”7—z„ÅiÔO¢1QÄ©Q¡KÔ)›(ìÜS2ŠuÊ}XUÍ*4n;¶nå”ZUã 4H¥VyB,d”ŠdQ™O§h”#ê]ÇNT¹}ÚðjȪj=œ Áç³r¨J +CçЄ7ê)¤H¹íî?×=‘D'?ù¥O™ Å&H=´ëÃÜ¢Ó¯ÿ›nÙ=û•c†Æy9PY0›S~K,òP9ŸÚþ@.='‡#ؐG3Ê#ìÝi÷¹í©åÉ¢>g]±TXR~½×€A¸ü™ÈáÐZçh”#êM»oûõe{N«JÁ¤V•mØ šÈ~‹ú„Œb$­ÚÃqvf*µÈmN©RÄ} 46H¥J ÛÃfÐDn¬÷،Œb™¶712_REEæOé°L[ùCã¬*]œd/©ZÖ@ÜÁ²"ã8RÞÊkÂÚg~hœ—ýdƒUؗdþ±~«¡Ã4‡AŒ¤UÛïf–r™K ^½‹»q –+îJ‹õӗdaÁ?ÂYS†FyBmúnÿ8§XvF‹R¬ +³RCéT„Õ4΋ ‹ª¯ÈÈ †üªàI(FÎuwç³q:UO`áðã åC©÷ûiÛ·D¡Êšr9‡º‚©!J‰uÝ0½ qfXQqˆ¯˜ ¢†═¬‡=nŸSÊ ?}záYäq{¹¤wÂ:µ CP;8 1kÚ§G¥ToÊ.¡V9å{·Þ«À%ìOX5V2†`Wlj¬Dä FÉ©ÙÂZ¿ÀËà(WùÝò¾Ási“ ¢bqtYhPéQ8,¿bÒ£È.ìt32ˆé洏‡y‡åÞTzªSMÏJQcu8LhP³RÔXÜõ:e;±Á¹38ÊvÎÍ©ÑB ÆeÉ2qP£M“uíD×ÎÐ(×ËwlÍ8¶vi[¡°A:¶©R†Qœc#مMCFq"½m_»»¹“J»À‹sìŒô¿zH7Ð gd¼Ž:åÙèØS8Êö?pl 5^—$«ÛAR§œ£x×F6ºöŽr„]¶s ¬G‡dÕ88·)Ãhι‘콈ŒŒb$}Z÷Ûð‡Ùƒ½4÷†ž–®Ӎ«™lã0XjÖ± ~=å‚ôRVâŒò5îgÅlg]êãÁàÏS2Hu~Åt™ÞÌܽª«tB¥à3å˵H9Å0®ŒØ&xì BĬ¿Íù°4 ½ÛÎÍESé%~¦æ¢iRr1¬+#\yJ)’.ߙµ÷/Z3ÛmRn1¬3#œyJ)’.ڙ•Ý”`î)Ԝe\¡.ܧ›BA˜ß ¾ }´ ?õÅMƒ‡&üC•mšáßAò¡ãUÎâÃÃ:N ·Ô2l‹Jüûê?®²¸ãendstream +endobj +260 0 obj +1984 +endobj +261 0 obj<>>>/Annots 134 0 R>>endobj +262 0 obj<>stream +xÚ՘Ár›0†ï<…ŽíÁ +HB׸uOí¤1}š`;Æ´O§oߕ´ +à©=ÙN2Ìì,|kýÚ_kò+a$…_F2iþžšä¾LîVš0MÊ a2£œH%àZ>¿+«ïûš´²l}}èïËÉÇ2Ii +saæòø‰(NS"³žkˆ.¨Ä`OÖ¦ÂÙݖܭr˜©© `¦]Á{*)#³UFà†°,©‰e0°/U³;l l ¥X>˨à.zÁ&#‚rW/¨ f52réEä1‘̤¤ùy‹úÐ>Øøªßµ‡·•À…” ¨—I£c´€5Šœf̪^ŒÃV?5¯Þ֐B“1¤å¾:ëãL 2Ø¥‹·à÷¤°ý=é‚PO +­)v¥ŠZÛ³µ'pÌ#ìö­- +Æó2Ú (ca|Š2ÆÌíÙÎÜ8ævÓö #÷övAÈÞBe~Æ{{²V°ö ÓH‚©xì+‹¯¥ËùÕœ©HW += »R¦¨hÜÚHFkÑ.ïP7`옄¹°³Á­ÊA sé§N76²ÑØc8ævÝÆVcgÜNg6 }Fnjd¥ŒXc2¦‘´lŸë·UãŠ\ßÐþ—¾dz4plìKžú£ãæF6öåîòv«}éLåðz゠‚©òGǝlÆÍ·Â ó[÷ö3½ ²_Ko²bv¹\iwŽ¥°×.¼( +|Q„犿XÏË9bÂ"@»I—öœu»éW]87ì¼Ù– Î¥=®ìړycžßë`F!ÑÂïµÍ{Ücý³íúÀRGÀ‰âüÓÁ mÕvÍÌ¡&.Ö6L›t·*pÆ*Ü¿Á/¿=¬Íÿ6»í©³gù\ªmmÎò°¯ì²`¹‚%.·«ØíP°¯É_*Ïk%endstream +endobj +263 0 obj +710 +endobj +264 0 obj<>endobj +265 0 obj<>endobj +266 0 obj<>endobj +267 0 obj<>endobj +268 0 obj<>endobj +269 0 obj<>endobj +270 0 obj<>endobj +271 0 obj<>endobj +272 0 obj<>endobj +273 0 obj<>endobj +274 0 obj<>endobj +275 0 obj<>endobj +276 0 obj<>endobj +277 0 obj<>endobj +278 0 obj<>endobj +279 0 obj<>endobj +280 0 obj<>endobj +281 0 obj<>endobj +282 0 obj<>endobj +283 0 obj<>endobj +284 0 obj<>endobj +285 0 obj<>endobj +286 0 obj<>endobj +287 0 obj<>endobj +288 0 obj<>endobj +289 0 obj<>endobj +290 0 obj<>endobj +291 0 obj<>endobj +292 0 obj<>endobj +293 0 obj<>endobj +294 0 obj<>endobj +295 0 obj<>endobj +296 0 obj<>endobj +297 0 obj<>endobj +298 0 obj<>endobj +299 0 obj<>endobj +300 0 obj<>endobj +301 0 obj<>endobj +302 0 obj<>endobj +303 0 obj<>endobj +304 0 obj<>endobj +305 0 obj<>endobj +306 0 obj<>endobj +307 0 obj<>endobj +308 0 obj<>endobj +309 0 obj<>endobj +310 0 obj<>endobj +311 0 obj<>endobj +312 0 obj<>endobj +313 0 obj<>endobj +314 0 obj<>endobj +315 0 obj<>endobj +316 0 obj<>endobj +317 0 obj<>endobj +318 0 obj<>endobj +319 0 obj<>/Outlines 264 0 R/PageMode/UseOutlines/OpenAction[198 0 R/XYZ null null null]>>endobj +xref +0 320 +0000000000 65535 f +0000000015 00000 n +0000000218 00000 n +0000000279 00000 n +0000000353 00000 n +0000000431 00000 n +0000000508 00000 n +0000000587 00000 n +0000000663 00000 n +0000000744 00000 n +0000000802 00000 n +0000000905 00000 n +0000001009 00000 n +0000001114 00000 n +0000001219 00000 n +0000001324 00000 n +0000001429 00000 n +0000001534 00000 n +0000001639 00000 n +0000001744 00000 n +0000001849 00000 n +0000001952 00000 n +0000002056 00000 n +0000002161 00000 n +0000002266 00000 n +0000002371 00000 n +0000002476 00000 n +0000002581 00000 n +0000002686 00000 n +0000002789 00000 n +0000002893 00000 n +0000002998 00000 n +0000003103 00000 n +0000003208 00000 n +0000003313 00000 n +0000003418 00000 n +0000003523 00000 n +0000003628 00000 n +0000003733 00000 n +0000003838 00000 n +0000003943 00000 n +0000004046 00000 n +0000004150 00000 n +0000004255 00000 n +0000004360 00000 n +0000004465 00000 n +0000004570 00000 n +0000004675 00000 n +0000004780 00000 n +0000004885 00000 n +0000004990 00000 n +0000005095 00000 n +0000005200 00000 n +0000005303 00000 n +0000005407 00000 n +0000005512 00000 n +0000005617 00000 n +0000005722 00000 n +0000005827 00000 n +0000005932 00000 n +0000006037 00000 n +0000006142 00000 n +0000006247 00000 n +0000006352 00000 n +0000006457 00000 n +0000006560 00000 n +0000006664 00000 n +0000006769 00000 n +0000006874 00000 n +0000006979 00000 n +0000007084 00000 n +0000007187 00000 n +0000007291 00000 n +0000007396 00000 n +0000007501 00000 n +0000007606 00000 n +0000007711 00000 n +0000007816 00000 n +0000007921 00000 n +0000008026 00000 n +0000008131 00000 n +0000008236 00000 n +0000008341 00000 n +0000008446 00000 n +0000008551 00000 n +0000008656 00000 n +0000008761 00000 n +0000008866 00000 n +0000008971 00000 n +0000009076 00000 n +0000009181 00000 n +0000009286 00000 n +0000009391 00000 n +0000009496 00000 n +0000009601 00000 n +0000009706 00000 n +0000009811 00000 n +0000009916 00000 n +0000010021 00000 n +0000010126 00000 n +0000010231 00000 n +0000010336 00000 n +0000010441 00000 n +0000010545 00000 n +0000010649 00000 n +0000010753 00000 n +0000010857 00000 n +0000011553 00000 n +0000011659 00000 n +0000011765 00000 n +0000011871 00000 n +0000011977 00000 n +0000012081 00000 n +0000012186 00000 n +0000012292 00000 n +0000012398 00000 n +0000012504 00000 n +0000012610 00000 n +0000012714 00000 n +0000012819 00000 n +0000012925 00000 n +0000013031 00000 n +0000013137 00000 n +0000013243 00000 n +0000013347 00000 n +0000013452 00000 n +0000013558 00000 n +0000013664 00000 n +0000013770 00000 n +0000013876 00000 n +0000013980 00000 n +0000014084 00000 n +0000014189 00000 n +0000014295 00000 n +0000014401 00000 n +0000014635 00000 n +0000014669 00000 n +0000014703 00000 n +0000015402 00000 n +0000015451 00000 n +0000015500 00000 n +0000015549 00000 n +0000015598 00000 n +0000015647 00000 n +0000015696 00000 n +0000015745 00000 n +0000015794 00000 n +0000015843 00000 n +0000015892 00000 n +0000015941 00000 n +0000015990 00000 n +0000016039 00000 n +0000016088 00000 n +0000016137 00000 n +0000016186 00000 n +0000016235 00000 n +0000016284 00000 n +0000016333 00000 n +0000016382 00000 n +0000016431 00000 n +0000016480 00000 n +0000016529 00000 n +0000016578 00000 n +0000016627 00000 n +0000016676 00000 n +0000016725 00000 n +0000016774 00000 n +0000016823 00000 n +0000016872 00000 n +0000016921 00000 n +0000016970 00000 n +0000017019 00000 n +0000017068 00000 n +0000017117 00000 n +0000017166 00000 n +0000017215 00000 n +0000017264 00000 n +0000017313 00000 n +0000017362 00000 n +0000017411 00000 n +0000017460 00000 n +0000017509 00000 n +0000017558 00000 n +0000017607 00000 n +0000017656 00000 n +0000017705 00000 n +0000017754 00000 n +0000017803 00000 n +0000017852 00000 n +0000017901 00000 n +0000017950 00000 n +0000017999 00000 n +0000018260 00000 n +0000018412 00000 n +0000024803 00000 n +0000024825 00000 n +0000024938 00000 n +0000025040 00000 n +0000025060 00000 n +0000025200 00000 n +0000026050 00000 n +0000026071 00000 n +0000026184 00000 n +0000026372 00000 n +0000026393 00000 n +0000026533 00000 n +0000027126 00000 n +0000027147 00000 n +0000027260 00000 n +0000027453 00000 n +0000027474 00000 n +0000027605 00000 n +0000028218 00000 n +0000028239 00000 n +0000028352 00000 n +0000028541 00000 n +0000028562 00000 n +0000028693 00000 n +0000029637 00000 n +0000029658 00000 n +0000029789 00000 n +0000030076 00000 n +0000030097 00000 n +0000030237 00000 n +0000031153 00000 n +0000031174 00000 n +0000031305 00000 n +0000031663 00000 n +0000031684 00000 n +0000031824 00000 n +0000032320 00000 n +0000032341 00000 n +0000032472 00000 n +0000032924 00000 n +0000032945 00000 n +0000033085 00000 n +0000034223 00000 n +0000034245 00000 n +0000034385 00000 n +0000035289 00000 n +0000035310 00000 n +0000035450 00000 n +0000036376 00000 n +0000036397 00000 n +0000036537 00000 n +0000037183 00000 n +0000037204 00000 n +0000037344 00000 n +0000038164 00000 n +0000038185 00000 n +0000038325 00000 n +0000039252 00000 n +0000039273 00000 n +0000039413 00000 n +0000039817 00000 n +0000039838 00000 n +0000039951 00000 n +0000040157 00000 n +0000040178 00000 n +0000040333 00000 n +0000042388 00000 n +0000042410 00000 n +0000042565 00000 n +0000043346 00000 n +0000043367 00000 n +0000043422 00000 n +0000043527 00000 n +0000043671 00000 n +0000043777 00000 n +0000043897 00000 n +0000044006 00000 n +0000044155 00000 n +0000044265 00000 n +0000044372 00000 n +0000044526 00000 n +0000044637 00000 n +0000044754 00000 n +0000044870 00000 n +0000045034 00000 n +0000045140 00000 n +0000045259 00000 n +0000045374 00000 n +0000045478 00000 n +0000045634 00000 n +0000045743 00000 n +0000045858 00000 n +0000045970 00000 n +0000046069 00000 n +0000046216 00000 n +0000046313 00000 n +0000046413 00000 n +0000046571 00000 n +0000046711 00000 n +0000046811 00000 n +0000046918 00000 n +0000047068 00000 n +0000047168 00000 n +0000047275 00000 n +0000047423 00000 n +0000047523 00000 n +0000047630 00000 n +0000047780 00000 n +0000047880 00000 n +0000047987 00000 n +0000048133 00000 n +0000048233 00000 n +0000048340 00000 n +0000048491 00000 n +0000048591 00000 n +0000048698 00000 n +0000048846 00000 n +0000048946 00000 n +0000049053 00000 n +0000049203 00000 n +0000049303 00000 n +0000049410 00000 n +0000049542 00000 n +0000049649 00000 n +0000049748 00000 n +0000049866 00000 n +trailer +<> +startxref +50052 +%%EOF diff --git a/doc/cmp.shtml b/doc/cmp.shtml new file mode 100644 index 0000000000..05ea5ce94b --- /dev/null +++ b/doc/cmp.shtml @@ -0,0 +1,713 @@ + + + + + + CUPS Configuration Management Plan + + + +

Scope

+ +

Identification

+ +This configuration management plan document provides the guidelines for +development and maintainance of the Common UNIX Printing System ("CUPS") +Version 1.0 software. + +

System Overview

+ +The Common UNIX Printing System provides a portable printing layer for +UNIX® operating systems. It has been developed by Easy Software +Products to promote a standard printing solution for all UNIX vendors +and users. CUPS provides the System V and Berkeley command-line interfaces. + +

CUPS uses the Internet Printing Protocol (IETF-IPP) as the basis +for managing print jobs and queues. The Line Printer Daemon (LPD, +RFC1179), Server Message Block (SMB), and AppSocket protocols are also +supported with reduced functionality. + +

CUPS adds network printer browsing and PostScript Printer +Description ("PPD")-based printing options to support real +world applications under UNIX. + +

Document Overview

+ +This configuration management document is organized into the following +sections: + +
    +
  • 1 - Scope
  • +
  • 2 - References
  • +
  • 3 - File Management
  • +
  • 4 - Trouble Report Processing
  • +
  • 5 - Software Releases
  • +
  • A - Glossary
  • +
  • B - Coding Requirements
  • +
+ +

References

+ +

CUPS Documentation

+ +The following CUPS documentation is referenced by this document: + +
    +
  • CUPS-CMP-1.0: CUPS Configuration Management Plan +
  • CUPS-IDD-1.0: CUPS System Interface Design Description +
  • CUPS-SAM-1.0.x: CUPS Software Administrators Manual +
  • CUPS-SDD-1.0: CUPS Software Design Description +
  • CUPS-SPM-1.0: CUPS Software Programming Manual +
  • CUPS-SSR-1.0: CUPS Software Security Report +
  • CUPS-STP-1.0: CUPS Software Test Plan +
  • CUPS-SUM-1.0.x: CUPS Software Users Manual +
  • CUPS-SVD-1.0.x: CUPS Software Version Description +
+ +

Other Documents

+ +The following non-CUPS documents are referenced by this document: + +
    +
  • IEEE 1387.4, System Administration: Printing (draft) +
  • IPP/1.0: Additional Optional Operations - Set 1 +
  • IPP/1.0: Encoding and Transport +
  • IPP/1.0: Implementers Guide +
  • IPP/1.0: Model and Semantics +
  • RFC 1179, Line Printer Daemon Protocol +
+ +

File Management

+ +

Directory Structure

+ +Each source file shall be placed a sub-directory corresponding to the software +sub-system it belongs to ("scheduler", "libcups", etc.) To remain compatible +with older UNIX filesystems, directory names shall not exceed 16 characters +in length. + +

Source Files

+ +Source files shall be documented and formatted as described in Appendix +B, Coding Requirements. + +

Configuration Management

+ +Source files shall be placed under the control of the Concurrent Versions +System ("CVS") software. Source files shall be "checked in" with each change +so that modifications can be tracked. + +

Documentation on the CVS software is included with the whitepaper, "CVS +II: Parallelizing Software Development". + +

Trouble Report Processing

+ +A Software Trouble Report ("STR") shall be submitted every time a user +or vendor experiences a problem with the CUPS software. Trouble reports +are maintained in a database with one of the following states: + +
    +
  1. STR is closed with complete resolution
  2. +
  3. STR is closed without resolution
  4. +
  5. STR is active
  6. +
  7. STR is pending (new STR or additional information available)
  8. +
+ +Trouble reports shall be processed using the following steps. + +

Classification

+ +When a trouble report is received it must be classified at one of the following +levels: + +
    +
  1. Request for enhancement
  2. +
  3. Documentation error
  4. +
  5. Unable to print a file
  6. +
  7. Unable to print to a printer
  8. +
  9. Unable to print at all
  10. +
+ +The scope of the problem should also be determined as: + +
    +
  1. Specific to a machine
  2. +
  3. Specific to an operating system
  4. +
  5. Applies to all machines and operating systems
  6. +
+ +

Identification

+ +Once the level and scope of the trouble report is determined the software +sub-system(s) involved with the problem are determined. This may involve +additional communication with the user or vendor to isolate the problem +to a specific cause. + +

When the sub-system(s) involved have been identified, an engineer will +then determine the change(s) needed and estimate the time required for +the change(s). + +

Correction

+ +Corrections are scheduled based upon the severity and complexity of the +problem. Once all changes have been made, documented, and tested successfully +a new software release snapshot is generated. Additional tests are added +as necessary for proper testing of the changes. + +

Notification

+ +The user or vendor is notified when the fix is available or if the problem +was caused by user error. + +

Software Releases

+ +

Version Numbering

+ +CUPS uses a three-part version number separated by periods to represent +the major, minor, and patch release numbers: + +
    +
    +major.minor.patch
    +1.0.0
    +
    +
+ +Beta-test releases are indentified by appending the letter B followed by +the build number: + +
    +
    +major.minor.patchbbuild
    +1.0.0b1
    +
    +
+ +A CVS snapshot is generated for every beta and final release and uses +the version number preceded by the letter "v" and with the decimal +points replaced by underscores: + +
    +
    +v1_0_0b1
    +v1_0_0
    +
    +
+ +Each change that corrects a fault in a software sub-system increments the +patch release number. If a change affects the software design of CUPS then +the minor release number will be incremented and the patch release number +reset to 0. If CUPS is completely redesigned the major release number will +be incremented and the minor and patch release numbers reset to 0: + +
    +
    +1.0.0b1    First beta release
    +1.0.0b2    Second beta release
    +1.0.0      First production release
    +1.0.1b1    First beta of 1.0.1
    +1.0.1      Production release of 1.0.1
    +1.1.0b1    First beta of 1.1.0
    +1.1.0      Production release of 1.1.0
    +2.0.0b1    First beta of 2.0.0
    +2.0.0      Production release of 2.0.0
    +
    +
+ +

Generation

+ +Software releases shall be generated for each successfully completed software +trouble report. All object and executable files shall be deleted prior +to performing a full build to ensure that source files are recompiled. + +

Testing

+ +Software testing shall be conducted according to the CUPS Software Test +Plan, CUPS-STP-1.0. Failed tests cause STRs to be generated to correct +the problems found. + +

Release

+ +When testing has been completed successfully a new distribution image is +created from the current CVS code "snapshot". No production release shall +contain software that has not passed the appropriate software tests. + +

Glossary

+ +

Terms

+ +
+ +
C +
A computer language. + +
parallel +
Sending or receiving data more than 1 bit at a time. + +
pipe +
A one-way communications channel between two programs. + +
serial +
Sending or receiving data 1 bit at a time. + +
socket +
A two-way network communications channel. + +
+ +

Acronyms

+ +
+ +
ASCII +
American Standard Code for Information Interchange + +
CUPS +
Common UNIX Printing System + +
ESC/P +
EPSON Standard Code for Printers + +
FTP +
File Transfer Protocol + +
HP-GL +
Hewlett-Packard Graphics Language + +
HP-PCL +
Hewlett-Packard Printer Control Language + +
HP-PJL +
Hewlett-Packard Printer Job Language + +
IETF +
Internet Engineering Task Force + +
IPP +
Internet Printing Protocol + +
ISO +
International Standards Organization + +
LPD +
Line Printer Daemon + +
MIME +
Multimedia Internet Mail Exchange + +
PCL +
Page Control Language + +
PPD +
PostScript Printer Description + +
SMB +
Server Message Block + +
TFTP +
Trivial File Transfer Protocol + +
+ +

Coding Requirements

+ +These coding requirements provide detailed information on source file +formatting and documentation content. These guidelines shall be applied +to all C and C++ source files provided with CUPS. + +

Source Files

+ +

Naming

+ +All source files names shall be 16 characters or less in length to +ensure compatibility with older UNIX filesystems. Source files +containing functions shall have an extension of ".c" for ANSI C and +".cpp" for C++ source files. All other "include" files shall have an +extension of ".h". + +

Documentation

+ +The top of each source file shall contain a header giving the name of the +file, the purpose or nature of the source file, the copyright and licensing +notice, and the functions contained in the file. The file name and revision +information is provided by the CVS "$Id: cmp.shtml 322 1999-05-13 20:40:46Z mike $" tag: + +
    +
    +/*
    + * "$Id: cmp.shtml 322 1999-05-13 20:40:46Z mike $"
    + *
    + *   Description of file contents.
    + *
    + *   Copyright 1997-1999 by Easy Software Products, all rights
    + *   reserved.
    + *
    + *   These coded instructions, statements, and computer programs are
    + *   the property of Easy Software Products and are protected by
    + *   Federal copyright law.  Distribution and use rights are outlined
    + *   in the file "LICENSE.txt" which should have been included with
    + *   this file.  If this file is missing or damaged please contact
    + *   Easy Software Products at:
    + *
    + *       Attn: CUPS Licensing Information
    + *       Easy Software Products
    + *       44145 Airport View Drive, Suite 204
    + *       Hollywood, Maryland 20636-3111 USA
    + *
    + *       Voice: (301) 373-9603
    + *       EMail: cups-info@cups.org
    + *         WWW: http://www.cups.org
    + *
    + * Contents:
    + *
    + *   function1() - Description 1.
    + *   function2() - Description 2.
    + *   function3() - Description 3.
    + */
    +
    +
+ +The bottom of each source file shall contain a trailer giving the name +of the file using the CVS "$Id: cmp.shtml 322 1999-05-13 20:40:46Z mike $" tag. The primary purpose of this is to +mark the end of a source file; if the trailer is missing it is possible +that code has been lost near the end of the file: + +
    +
    +/*
    + * End of "$Id: cmp.shtml 322 1999-05-13 20:40:46Z mike $".
    + */
    +
    +
+ +

Functions

+ +

Naming

+ +Functions with a global scope shall be capitalized ("DoThis", "DoThat", +"DoSomethingElse", etc.) The only exception to this rule shall be the +CUPS interface library functions which may begin with a prefix word in +lowercase ("cupsDoThis", "cupsDoThat", etc.) + +

Functions with a local scope shall be declared "static" and be lowercase +with underscores between words ("do_this", "do_that", "do_something_else", +etc.) + +

Documentation

+ +Each function shall begin with a comment header describing what the function +does, the possible input limits (if any), and the possible output values +(if any), and any special information needed: + +
    +
    +/*
    + * 'do_this()' - Compute y = this(x).
    + *
    + * Notes: none.
    + */
    +
    +static float     /* O - Inverse power value, 0.0 <= y <= 1.0 */
    +do_this(float x) /* I - Power value (0.0 <= x <= 1.0) */
    +{
    + ...
    + return (y);
    +}
    +
    +
+ +

Methods

+ +

Naming

+ +Methods shall be in lowercase with underscores between words ("do_this", +"do_that", "do_something_else", etc.) + +

Documentation

+ +Each method shall begin with a comment header describing what the method +does, the possible input limits (if any), and the possible output values +(if any), and any special information needed: + +
    +
    +/*
    + * 'class::do_this()' - Compute y = this(x).
    + *
    + * Notes: none.
    + */
    +
    +float                   /* O - Inverse power value, 0.0 <= y <= 1.0 */
    +class::do_this(float x) /* I - Power value (0.0 <= x <= 1.0) */
    +{
    + ...
    + return (y);
    +}
    +
    +
+ +

Variables

+ +

Naming

+ +Variables with a global scope shall be capitalized ("ThisVariable", +"ThatVariable", "ThisStateVariable", etc.) The only exception to this +rule shall be the CUPS interface library global variables which must +begin with the prefix "cups" ("cupsThisVariable", "cupsThatVariable", +etc.) Global variables shall be replaced by function arguments whenever +possible. + +

Variables with a local scope shall be lowercase with underscores between +words ("this_variable", "that_variable", etc.) Any local variables shared +by functions within a source file shall be declared "static". + +

Documentation

+ +Each variable shall be declared on a separate line and shall be immediately +followed by a comment block describing the variable: + +
    +int this_variable;   /* The current state of this */
    +int that_variable;   /* The current state of that */
    +
+ +

Types

+ +

Naming

+ +All type names shall be lowercase with underscores between words and +"_t" appended to the end of the name ("this_type_t", "that_type_t", +etc.) + +

Documentation

+ +Each type shall have a comment block immediately before the typedef: + +
    +
    +/*
    + * This type is for CUPS foobar options.
    + */
    +typedef int cups_this_type_t;
    +
    +
+ +

Structures

+ +

Naming

+ +All structure names shall be lowercase with underscores between words and +"_str" appended to the end of the name ("this_struct_str", "that_struct_str", +etc.) + +

Documentation

+ +Each structure shall have a comment block immediately before the struct +and each member shall be documented in accordance with the variable naming +policy above: + +
    +
    +/*
    + * This structure is for CUPS foobar options.
    + */
    +struct cups_this_struct_str
    +{
    +  int this_member;   /* Current state for this */
    +  int that_member;   /* Current state for that */
    +};
    +
    +
+ +

Classes

+ +

Naming

+ +All class names shall be lowercase with underscores between words +("this_class", "that_class", etc.) + +

Documentation

+ +Each class shall have a comment block immediately before the class +and each member shall be documented in accordance with the variable naming +policy above: + +
    +
    +/*
    + * This class is for CUPS foobar options.
    + */
    +class cups_this_class
    +{
    +  int this_member;   /* Current state for this */
    +  int that_member;   /* Current state for that */
    +};
    +
    +
+ +

Constants

+ +

Naming

+ +All constant names shall be uppercase with underscored between words +("THIS_CONSTANT", "THAT_CONSTANT", etc.) Constants defined for the CUPS +interface library must begin with an uppercase prefix +("CUPS_THIS_CONSTANT", "CUPS_THAT_CONSTANT", etc.) + +

Typed enumerations shall be used whenever possible to allow for type +checking by the compiler. + +

Documentation

+ +Comment blocks shall immediately follow each constant: + +
    +
    +enum
    +{
    +  CUPS_THIS_TRAY,   /* This tray */
    +  CUPS_THAT_TRAY    /* That tray */
    +};
    +
    +
+ +

Code

+ +

Documentation

+ +All source code shall utilize block comments within functions to describe +the operations being performed by a group of statements: + +
    +
    +/*
    + * Clear the state array before we begin...
    + */
    +
    +for (i = 0; i < (sizeof(array) / sizeof(sizeof(array[0])); i ++)
    +  array[i] = STATE_IDLE;
    +
    +/*
    + * Wait for state changes...
    + */
    +
    +do
    +{
    +  for (i = 0; i < (sizeof(array) / sizeof(sizeof(array[0])); i ++)
    +    if (array[i] != STATE_IDLE)
    +      break;
    +
    +  if (i == (sizeof(array) / sizeof(array[0])))
    +    sleep(1);
    +} while (i == (sizeof(array) / sizeof(array[0])));
    +
    +
+ +

Style

+ +

Indentation

+ +All code blocks enclosed by brackets shall begin with the opening brace +on a new line. The code then follows starting on a new line after the brace +and is indented 2 spaces. The closing brace is then placed on a new line +following the code at the original indentation: + +
    +
    +{
    +  int i; /* Looping var */
    +
    + /*
    +  * Process foobar values from 0 to 999...
    +  */
    +
    +  for (i = 0; i < 1000; i ++)
    +  {
    +    do_this(i);
    +    do_that(i);
    +  }
    +}
    +
    +
+ +Single-line statements following "do", "else", "for", "if", and "while" +shall be indented 2 spaces as well. Blocks of code in a "switch" block +shall be indented 4 spaces after each "case" and "default" case: + +
    +
    +switch (array[i])
    +{
    +  case STATE_IDLE :
    +      do_this(i);
    +      do_that(i);
    +      break;
    +  default :
    +      do_nothing(i);
    +      break;
    +}
    +
    +
+ +

Spacing

+ +A space shall follow each reserved word ("if", "while", etc.) Spaces shall +not be inserted between a function name and the arguments in parenthesis. + +

Return Values

+ +Parenthesis shall surround values returned from a function using "return": + +
    +
    +return (STATE_IDLE);
    +
    +
+ +

Loops

+ +Whenever convenient loops should count downward to zero to improve program +performance: + +
    +
    +for (i = sizeof(array) / sizeof(array[0]) - 1; i >= 0; i --)
    +  array[i] = STATE_IDLE;
    +
    +
+ +

Software Trouble Report Form

+ +
+ + + + + + + + + + + + + + + + + + + +
Summary of Problem:________________________________________
Problem Severity:__1=RFE +
__2=Documentation-Error +
__3=Unable-to-Print-a-File +
__4=Unable-to-Print-to-a-Printer +
__5=Unable-to-Print-at-All
Problem Scope:__1=Machine __2=Operating-System __3=All
Detailed Description of Problem:________________________________________ +
________________________________________ +
________________________________________ +
________________________________________ +
________________________________________ +
________________________________________
+ + + diff --git a/doc/cups.css b/doc/cups.css new file mode 100644 index 0000000000..0553f766ee --- /dev/null +++ b/doc/cups.css @@ -0,0 +1,3 @@ +BODY { background-color: #cccc99 } +H1 { font-family: sans-serif; margin-left: 5% } +TH { background-color: #999966 } diff --git a/doc/documentation.html b/doc/documentation.html new file mode 100644 index 0000000000..43d2bb2060 --- /dev/null +++ b/doc/documentation.html @@ -0,0 +1,109 @@ + + + Documentation - Common UNIX Printing System + + + Current Printer Status + Current Printer Classes Status + Current Jobs Status + Read CUPS Documentation On-Line + Download the Current CUPS Software + + + + +

+ +Easy Software Products Home Page + + +

Documentation

+ +The following documentation is available (or will be shortly) for CUPS: + +
    + +
  • Online man pages (for users and administrators) + +
  • Whitepaper - An Overview of the Common UNIX Printing System ( + HTML | + PDF ) + +
  • Software Users Manual (Not Yet Available) + +
  • Software Administrators Manual (Not Yet Available) + +
  • Configuration Management Plan ( + HTML | + PDF ) + +
  • Interface Design Description ( + HTML | + PDF ) + +
  • Software Design Description ( + HTML | + PDF ) + +
  • Software Version Description ( + HTML | + PDF ) + +
  • Software Security Report ( + HTML | + PDF ) + +
  • Software Test Plan (Not Yet Available) + +
+ +The source code is documented and formatted according to the Configuration +Management Plan, CUPS-CMP-1.0. The design documents should provide the +programmer more than enough information to understand (and maintain, if +necessary) the code. + +

RFCs

+ +The following RFCs are applicable to CUPS: + + + +
+ +

The Common UNIX Printing System, CUPS, and the CUPS logo are the +trademark property of Easy Software +Products. CUPS is copyright 1997-1999 by Easy Software Products, +All Rights Reserved. + + + diff --git a/doc/figures.sc b/doc/figures.sc new file mode 100644 index 0000000000000000000000000000000000000000..44c439ffd7b83476896c3dc0e42cbf2b7802b222 GIT binary patch literal 51020 zc-qZ<3z$^Zm2MSX4K(;c(~Z2Or9?mkB%mb2H4>`2S_DPH*r@ox?$cGLn}X^(m8w$+ z2^lNK#AMXK5JN;0?O`0_CnmmnyoMP=RbvR(5OG2rdyHcsDnke=Gf2j0k9GI+)Y|8{ ztE&6n>F=xF=j_MYYwz{1{aE{PS|iJ@tqBxA_4#}ge7?X)#IFqLb1RTe>t${fxnMy3$%UCHjv=Udfmm z3*!8Ne|=KDoz{&Qe_Xs<^kn`GCLXzeqp7Uie|%CybtYzj{m;d6iXxtL(SL%jZB&z3 zilrLD{u86wbXrBR<46#}WVX9QO=JH_N;VePg3&}gCD55n>yyeXQ}UmpCZkF!lf~Y# z;ObWHe;%h#SS`_?YNEm8H*HeWnK-KdjGm4syA1#HNqVvJu>Z6U1=UzeizjtMl-NJm zsi90unBx8y#FLv4J6bx30HAejz*58h(-ZMcDndj|)qsGV|TaoTY z6;u<{ z{~vjoP(i)iT`d0h=E3>_UM5yhFGI!4qzZWXT(S7+D}(g|yiBe@MnlERlnQvs4iR?G zt3XCW#mm$R>gBJ7h?k}c>Sd^SIln^eJ~3E7z{|7>b$Tdx30Bx2y+2q#z{>>{_D4g( z%k;|dG9+4yBhc$rs0y(}LhUM{JiUWSU7`L?{U-~Xe(AZY(bEmsqp zR6QP5?B9b-mbjWmMYL=>uBI<())FzE-o`J;#;>@{BU!l5^ju5l)np!B%jRlmu3ej9 z<8VCh9__2EU4!jRnC7q;nSa-FUWfr|oPG$D3;P`{z1FVd_={}y`C1x6KEvIP+?nkp z6CNj2dJdS=@%N=U`jCH5`5Au>fAUT(ekL?&TtAN+ZaXARpZGWYTv*zB9ey|BHswSaAv%VP{DO==vMDF!B$YaV%E@Ku zZ{AMmQg`A}Dl3#vz-TEcP5c*GWL4fmuhoyoXSAW8nU5s`ALDa1#2v%<7(a-7j2HN5 zK)+Xk+^-P$Xl$oxkaiP3(ED)42e#UAx<0YF9tQj^JUH@IU-B#Z{YYN?HhHTR1hM!EV~TiZ|N%HKWvMHUbCEqT6sg;-}a@JMdRM*yd#;wei6~}zX|AUtdPz~L+`%x zoyCaGdV|jE#bV3C1(e?WRSl8)t6nhZ_(eL+oZ2-cegJw97Lwp;a~ zZ;?m4j%bzqhCN7S9C!f8_-3Kcnamh)CPo|hHKHtaz{g5~kC~?O%p62MW|sUyE5`nozKtMz2=I6V?Gf$8H_92hw{_(~6oF4uevIBk; zccLG!Cm~+H)z7BQyjH*x#{ieXLi@UhZ6=Qg+swl8&Q2ab44w_%;dmT`<8+|SOnJ`Md1Aq78oyU{m-Kb+Z-k&t(W$uH&DAeD)pigK|(7Qt)d|TDyMmi6b?1Lj( zvNPVr`&~4;Fm=MXeIjjCNj9{-Od55J^PJ1(k=&i%?%fx&_)s=Z{VS&lW#iOuBiWp= z_Qn1m0NH2;56dWB!+p`(zJ^451RJ{^K-jJQyg+A>FJMcj+OaF8Z63SAvBl*AAD14b zX+D#qe4uv+tgWkRyvOn=W9}7Qug0nR}$mlnqJPQRrE@m>C#bk7`ql|8?T1KY_F%5n?vwww zr5n*NVNOTl&K2AB0tzdz@DNHDV(B=~qCM$wPnhKk)73XzyVBIo*x5B{`Ia4lc1=7t z$b%;FCfHX*(42$2WKJcH(}sb%YXEjAOy>rn&p~=m=rrY)6FScAz%AAGIXDl9F~6?| zV=Q2gu?%bn&h^nG!)Ou*SmK!2vb=1?$}59&>cUYpSuAa2_=(h(@_B<_=$GKM(Jo*olPrxTub7zgM>J|g>HI{py!OL+Xt>x zl3iJ)%aT-!X1ftD*J&C^$SV8FbXrSW>YDgks`@Itkq~+;*E0GlrCVL8X&bYt3=CS) zol3-`aotqb&R82_zive`mDO8I0@$E+keaz#>kz11qpGPe-Un&xX%d!>UQxxbR5E%= zm^?5M&**AWP2&jc5y&Q?MM=fuQ1)n&GpdZ0>L%3ySU1TGv3xChShFRi3Vg3p)!21v zLQ`U*?`9p9aE0iZ?dHfbc{2o=e9cvayo>^w{drMLwg1JeE>?dkO*X5N@~o!MB05`< za;fQXtUI1Gfs2M<5ZDHYm}3%Z#T!qdaA*Qzyd@YDtKKAL>~(#HwlCvB>tVHp(suL4 zl1-&}0=2hBI~>{VJWq~nwJtTjH0G%L*jyaPndUn+YlZfEKC?CB@#JpnnA&l!Hox7n zcGAbzP6!|DnbS0{`!vIK7WRz#x^Ibj@iAM?a=`yar z{Mw-NT=656Zkh|7l04R0`>6fnbIxOj$V^Ji9`Ube1*-W~eWo2weL zu{`AaQ`T*i-th>o< zcU#KT$iN1Ohm}%M%{J@PZv^?BX7W4DaCAEFZ9ib~W%P;Dl+>q}9Q0{3;QzOfkLJS^ z7uanXog;H%Nqy=E`t%7(SK~rQm^)bXX|absZMW#t3Bbp{3iWy)l?Sn7VLtA2)Tf)O z)u-nEa`cG|HOki}K0<-IgwY%qI&*|wEgjdl7=Ec#+lGv;=(yV>uAm_?HDeyiWl_&& z^3vnFWjKhBLx{?W&o`k=w9d|qDrh@mT1(lCXi{k{3cPGo&|UxD5afLq(?8@AdEX_e ze|JghAEPO!f2({B`qu;ae-HA3*Uq?$^D>PK-1P4x(7!V%U7ZUZsDGC6#r|dPIJeq~ zh5-w8%^!vGU^@|Z1Ni{q!+CzVwp#ted6d(i(Fs!dD!5+PQwZVMf%=63n^wP+MY?45 z&ZH3TRnz#B9DEX}auwB5DxHBrMd{e0n9WA zC}=#Twxvo9OcYJA+7f7vN6MC9lRfkB*P^GV1YF?pCUXfcB*vXQzO0_gk2_agVWX#Z zc9wv>ouvl$Klcgk${E&YondR^&g*Jseg12q+>3nmPINrSryI)FXF#Rq9y@)GoDESv zob~y}s>i2iLuK@*M!!+MLc=cSf6f?{`YRjNwr(w^CT#j=Db>eqP|CjR$9kO7x1?|g zcC5`4PGp`Rr&8vIC8lnQN7Xi=ruaAoxu%xE+%DYf*e=xj2ESdXcb|{?#CBn`eg8e| zNx=Vig?aIekdM1~?p{X!y&cdQ-f~&-&n|S}8iJ+&?%V1s$3B3^&*0ox&EMGBcUxw* z2gqJDXMMk65Y`mS=)X&bwDJ|6^l~vf<0^L5OvcWZ12Mb9(T1{h2y7@@%dw%X>b1x0 zSg^)Z^SH1U(3Io$b!xAvcU<$veH~n8{XX1t5qT}|H_X*aW+Uoah@UlTOigYv#l&7_3yf7CcM5VF z)$Zdik=rNaZJMK`_3^Yr9|Grq4+(noU8=*> zJjOZ?3iVQ8^-^HD@+L37md$o()b*>+dw^2Lc}(*t+amR`u>RWUMy~DO&x@XKspk)SB#6p!z>)f>*I9$t#QL3 zJP*>LdfD#2f2`(*LfIao<3HlEcdtE4Jf2ymc4uQaZL>`6&fFm04_SE^ulJY!YlIJUpn+mHMH<5ZpZuk}Y%xMeq1mPi&j>J7_k|zoevv3@*!0Gl|}GUw^lTV@cWA#`t8Tw@p)%X=`FPa9n{fPGO`|T3 zfNZAqpk0Uk?%xXa_2|++yVSeu{;$4W9`*BR$Zc(Rx4_2^)&}iha@!G->tA++9uxRj#?mZf z@>}MU!|^hoJdT(7WO4kC701T9&gl|Y0o|}q?LqWgbIiS?$j=hVjp+klGUz-}JciO; z>q4g_ldq6_%fz|ytvSD=y>*W`2W58PcECqkC=Z^SWB1nFIKszkj_ay_S(P1_D49i-s2<bE&7j6s#s}PdSu%K*42xB+pp+NQ| zgl<&Tl!Et{p>X`%rtlqT6HHbsY>~##Jj}*SJ)yMbqb6dRTh@u*!8vs?MOTFU)nrt| zH}K(EI0`e~VI7fxH0pEXNmEERqsD}cJF=afd`)?R^ISfV5pZ^h;S9M1XNM%#bN7_y zr=Ip;MpI7r|1v1KPBh$Roe1|)BSAUOH~7VSBrfXl5x0r0*P?d^eOg_WJ{=a%%6jY5 zCMA(o=XWc5bp0kdZJNZ~$)!aMoR~^}vapU1&PxQQ3H5>RAz&`4kJ*lLuNBhGE)6Gm zI==IsyqE4EFzEAlB;UJuz1q(W0zo0K3xhuH657c1#3qYx!DheMKN@S8G_HtE7M=s? z5bt?YUJc@0FECx;;arBd(F||rI^yk%RpV`R`FO(y%7j`e;83 zhT@8>Q{#MU9C5X(T3q2g%EcAEJGW9?vDDtUx=6rPfZ{6hKGU_pAmS?EimTaBHjz(h zn~GhskLlBp6s~YQSzNKW61cieP#=X{BXJ*Nm?{h+ zrV6f@S|IT8Jd?}w3{%fbV(R%aF!j7Nrk?g_qb?PAc!=?SH`~YgkRzt9sTxyvmyanl zE2|VyG^snDE)(kFhdIjUojF<;KXkxTe+78@p(~yi34H8eGC?lkV}~T3c1Yrh(Uio~ zDfji5z~#bNY5^Kc?LxeKo6Uus@17IqKr`E2*OK;!FI-IQUN2hjlPh#y^X&c^hp)xY zOMBLh3aj7z8IOzku&g^ZJaoX2%}nh$iMz`hH>_Qgi-f*Yz|Z@}{Nv~H@BYKpv`$)A zyRXLtJ};E5k)5f=E_?U91AxVoSzqI{<<{3)@AcsQ3V{bds%=8QyU`S>9P(3EtNPJb3?tz{6g~`(DQTUP<2fmcjd8Y2HINeF|vt z0%Hst_5j;|huvw^4(77|?&_-6E?6FAtX&Xms9b+?u4$PK@Ac8)Syf7m>_iRDAzLdl z*4;s!rCZ62G}Nz+Y+AQFtYyp9Foy}$?FL&#jh zhs++r0f#+=HvJT*Dc4V}*=mDPFb)nh2s}(=7)5hY-1g&l2aK+$8l!=-G0GuQK2$|i zX3|mnfLKO2i51l{y7`oa4i8h=uOSB-L7k3nnapsB#}~Wk{e9AFZ(g{Z?260rf@~WZ zE^&Xm%i7;M;<8Z^m%HryTL)aeV1vuWfcFWI2YhyxxOkqr%k?bn@@jF(=d|UtodiE} zs63CkQ;aEIHpL-j_+f%2FOo;M(iM-=BS=|x>CzOpwsE3Sf1ec3Mm{P2iInX%s@INZ zqRU{2QC`)3Y;(e?2}jE516MxB-t-|+{_(nfl+ zU)eZyI>oZ1XNs{=lT3#_b>Tc9$FY$^`B9{f@1*Uq<6c@DUD!X~dEK4RJmhM_ohsm| z!0=RHe8}t>9dOt)>ZA*Hdq!<_;raz0^V!b{Je*~FBe6R`*E~J<7Y>xpff@S?pZ({C z!kV>Ll6fU^!vnK_ZR{C5E6zI$AUp)pk@FW9^@#fmQFxez<9G#5cfcAq48rpu9jcT2 zJ?18V0rv^EjLK79&gr4~oYNzSW%bLwvpwLeIwj!T}?0shl7jrbE2H>LJg? zf?V)E(O%{bxbBUtHK&8T7skF{Q@HF8-yrph+;IEb#E!se3-ScvVUUi*HSMFs;b9hz z;}tmF0h_oWya3YGH{7tuL!L_oxr_@M_l1+XcRm9n%Cp`lFVA|Pq&#m(dB`&)jM>iZ zA@xYy0eW|;j689CL7pSNez0))^_P-*MQ%7ZWe1lLi(8T>2oHmFB<^&voH#tp!g0I; zr#oO17lao;I#egW@sMY;U<266YzI4;?O>;*?Oe{S7BCfvog*1T8D5AGBRyacfwX{CFpo6q=y5%%sd23l6t z7>MN|KL!FP+3|3oNqWQBRG;}6JRjyvHEn+~VuIaNa3j@JW6y$cY1&k2O?}Ka7jR!z>)9>*I8{TjPd7_&$&h)!ow`ZP(pGpW<()y!hGqR0(@Ck0;Z1aoUn? zm)F|I6Gr>F8}IqNqeyUt-QCnS>ACj7(h2hX=E?smw2ab7y{ZQR@@J(rGMDc+Cd z@^4NU z^OAQSejoilAZ_IL-&u!#w;8&+z%&n7K6)Jb)tl2rZ06~C6rN|{VU#Y+(s7=Jwio3a zX8FQ&^$j;qHPs0|zYzpQJ6Grv*&PXFooK7&9v`>!8wbId{Esb{70)=)@wBNv=RPL4 zxz_`HIVA9Zg!1rvJ(_Y}_j+7e?U)?rAwMQ3cV?B$jWVP0DJ+@g5Jt)52QKE~u@zlU z$2+n*UBtm}8Ry`H;+8m?O+!m2DT0DW`X~TBh^9t!yYaFhm;X_BiQK$a%*!~l2k)Gp zAn;Mg?!T#H_ts37)|0ORJ^2GlH`0lYNl(hZ|7Nm9Pg(#UcM9d1$n<0sx&OxRvbNb$ zwVsS>FH=t#s@wGW3cWbvVriY3ZJuEABS>_1Ihz~Q`2i;A$+M+b!p-(MpXK?wP?!9B zeU0r@rj3%=Zj{Eh-*zq09^3ajU>kl1Yoah$JjLwSr^tO8ez=d@gl+SB`B#PV)bwyV zBgtMt=RNX~YB7cLs1#Flxn*!6g)-1m@Pb1CB6nz6+Kaye?Zxqyz`p-*l8w+_EHlpb zl-i389(w7%$NmlhBcC#ie9G=zk=SF;<4a-uZlC=gdwYz(>VWa10ORKie1JP3kUkB= z`|MpX4$h(lwg_~N8FWTsy~OVh7;ml`;|F{dW4zS34LZ(E2S3}QT1=IJx*6wRhW%pX z?WOc{~3;4KKC=b4u6T9d41PC9_M!?hs*)H3`yJ!_XQgU znB9Gjo8A3BK_=jv3PdI{cUkT(<1Wi#<=k<5%W{Xl;GckwTp;i<=BRP+9ll@3V=NEP z@;)X@$5aoZJz;Vw4o~OfXLnChddB;1@g0?y+aHI4{tBG13;amPYvNIU*I05XdVMMNIcIC!;cH~(#SB3-IH?r|9E_+qP8P!t%hGYfFpdW>>}T(O~zbX+l9Ia)q(IhVl4JUJmEamDXY>>i`86rS&q+;?@% zh%15T+ty3iyJrb}EN1*;_l$V|pADYD{fmL`2y|3NXNj+#&~d(h@$*&Vc?sD=Rso(9 zrIF=KX++N`4NRl-i>Tb!ym_xgeTEChx5?JOE5vUFT+9Hl$wjdXB+ z*y0oChwvShH{mfq{5v79I>w{FJwRyJInEC+uiD1pZ?DkC(V=MxRY_JjyauV==7*08 z^%7v;nZWKz=d~k?jUymA?qD>1Qs10uv%4qPZjUU*y7imi-vU@K+1`8Eo#f2LcWAiS zyb+E9AA$Nh1nH2yBfaDvj!}e;v#t4mRkgOm@{q?-Dixy^<_n~e6XatOw*9)z__zfR ziE0Tg-A2E01pPND>A2F7P}}eq4>K@CiAM1Uv{6Vjt*Xh4NG+*rNwrN&CbpRJk7c4t z%E$tjC5ngoB>zlGDdleNTT=LbMUe$;$yU3wiPCqMIZftCLo#Uj^S}YsYor06`=th{kWi)`#FPbCq3L*;`LKU&44U|v}<0;s8H63cz z6v`7NwPZH#ltv8XNd%{d=x>tmU#|pV5x)dic2Gn%_-Jerayo_LuIZ zwQcV_?u_`A&<^9hV*HzFm=Bq~Vr6_QjnkAId)eHJZP{n~C!_y7!0z_#W$pnwpYhyh zdcbk={!Ilh38p#7^Mrdbew0QPEfvKmM=_)>f}lHz0|cvS&X~J zcY!;{U(0)*spRpb_EPUM;!5nLZa?9{yIeF0Fz&qijuV8=(c-6s4tjSOFD|ZjyomECZ@ftR zBHRO9C_QML?z4Ox1bcNRG)1qwJszVM4wSq~mk>a|PF?ir&~((-Zeea_O($7I3hb;sCpZ59G@9S2&(jf3?hr zE74ym?GCmAFz>0Y75Hc`p5Sg|t#4Rl$I=fa_kX@2(Aie}khlstM>`C^JLtn-R6T!E zN`7+sz(!FRV$-A*;(V?UbO^bS>V)ANU9X|Zli8QXz0@`?@O844{XteXPWBfPAH_55 zFD#v5Z^7^FMUE#Qr(d$aC@*=~%H9<6`X-Y*atUqZO5q>HlfplvDTn_KpTnLxz)|f8 zVchjZ@eFs#cN31>;fDVdsE79jI{&=%L*o88M8Cg)-W~A&xvK0?ERQnrPw+<-pnO9x znmndA(v#maL_||STTH`sy1H3+2qQBYI`f&~G_4aY%I1FH1Eb!5UObEBb;L=2o_iH{ zJNE;GCZgri51ba{e~`%^xrC2{OFi{~$Cug{$7o9G!4(dA0KS)7TPN`G<{f9ai}PwZ z=aG+H^Z?lB0&hV&Eu-)Fn9zBPe%l1UJLth@tJVW{52w5yaHLhJ2dEqAOvIzQNf$P% zTS}iNH+*AiXE{oO*~`Z9DtH`vWz;BTxsE;YKss(B-?HUih82Nin}K9_13=bvgiw1O z`yJ4+4-gjq=!6ZEj#u7eD4M;RCrcI)>xP>KKbFqhk)=QLh2` zsU2Eapc`u)|%J|6<7Co5fF%?0)PdONoA`#NSXj)k zfZdaF^A8?hdLNba{G-F+JMF_>1v+t#VB;A#?PKoZyAE1{zjNz%z-!*H8Je{EH6Bu6?Nvp&x>wJ8c?Has7uM4yfr1R=oZu9DQg?bGB?oUqg z5bDAH``RO1>kZLz!S!*0kMov(%w56%y01hMD@(= zwcKfFe|Jx>^?suKPk(uN;jz?DiS6;R)ZXUrO<8T+-DA3+r~tx4ARUQoy8jS|hgmpI z*T?DhTH}U6cpjvyZ-}mOw*%LX70PxGs*APE#qW>j7$tx$x^LCrKJKudZ;``6{Nu5o~=zVuC z`zIdPytWYfN&2(l-(S&0_(AUehG#!9>e>{y`KhPA-uLXU|DMGC+s(7WkKTL@t?O8e zhuwOdFb=GvcP0~;y?ffNSv-r~`Z%y#A1~RhSzOU>eH_@Wk8`_qEN6ogU@NX|gtl|S z^B(ry+5uPIhnv$u-uqtO{)gso>kkutM+V>Nd*NsA@pX|%#3)hQEL{e2|VUtKM3i!Nqk-r=-98;{bqWH#1GR9%+`Y1o?O ZRG+qdi|#pj6tCS(qj7$L#tX&M{})W2yc7Tc literal 0 Hc-jL100001 diff --git a/doc/idd.html b/doc/idd.html new file mode 100644 index 0000000000..47e9a3725f --- /dev/null +++ b/doc/idd.html @@ -0,0 +1,278 @@ + + +DRAFT - CUPS Interface Design Description + + + + + +


+

DRAFT - CUPS Interface Design Description


+CUPS-IDD-1.0
+Easy Software Products
+Copyright 1997-1999, All Rights Reserved
+
+
+

Table of Contents

+
+
1 Scope + +2 References + +3 Internal Interfaces + +4 External Interfaces + +5 Command-Line Interfaces + +A Glossary + +
+

1 Scope

+

1.1 Identification

+ This interface design description document provides detailed file +formats, message formats, and program conventions for the Common UNIX +Printing System ("CUPS") Version 1.0. +

1.2 System Overview

+ The Common UNIX Printing System provides a portable printing layer for + UNIX® operating systems. It has been developed by Easy Software + Products to promote a standard printing solution for all UNIX vendors + and users. CUPS provides the System V and Berkeley command-line +interfaces. +

CUPS uses the Internet Printing Protocol (IETF-IPP) as the basis for +managing print jobs and queues. The Line Printer Daemon (LPD, RFC1179), +Server Message Block (SMB), and AppSocket protocols are also supported +with reduced functionality.

+

CUPS adds network printer browsing and PostScript Printer +Description ("PPD")-based printing options to support real world +applications under UNIX.

+

1.3 Document Overview

+ This interface design description document is organized into the +following sections: +
    +
  • 1 - Scope
  • +
  • 2 - References
  • +
  • 3 - Internal Interfaces
  • +
  • 4 - External Interfaces
  • +
  • 5 - Command-Line Interfaces
  • +
  • A - Glossary
  • +
+

2 References

+

2.1 CUPS Documentation

+ The following CUPS documentation is referenced by this document: +
    +
  • CUPS-CMP-1.0: CUPS Configuration Management Plan
  • +
  • CUPS-IDD-1.0: CUPS System Interface Design Description
  • +
  • CUPS-SAM-1.0.x: CUPS Software Administrators Manual
  • +
  • CUPS-SDD-1.0: CUPS Software Design Description
  • +
  • CUPS-SPM-1.0: CUPS Software Programming Manual
  • +
  • CUPS-SSR-1.0: CUPS Software Security Report
  • +
  • CUPS-STP-1.0: CUPS Software Test Plan
  • +
  • CUPS-SUM-1.0.x: CUPS Software Users Manual
  • +
  • CUPS-SVD-1.0.x: CUPS Software Version Description
  • +
+

2.2 Other Documents

+ The following non-CUPS documents are referenced by this document: +
    +
  • IEEE 1387.4, System Administration: Printing (draft)
  • +
  • IPP/1.0: Additional Optional Operations - Set 1
  • +
  • IPP/1.0: Encoding and Transport
  • +
  • IPP/1.0: Implementers Guide
  • +
  • IPP/1.0: Model and Semantics
  • +
  • RFC 1179, Line Printer Daemon Protocol
  • +
+

3 Internal Interfaces

+

3.1 Character Set Files

+

3.2 Language Files

+

3.3 MIME Files

+

3.3.1 mime.types

+

3.3.2 mime.convs

+

3.4 PPD Files

+

3.5 Scheduler Configuration Files

+

3.5.1 cupsd.conf

+

3.5.2 printers.conf

+

3.5.3 classes.conf

+

4 External Interfaces

+

4.1 Application Socket Protocol

+

4.2 CUPS Browsing Protocol

+

4.3 CUPS PostScript File

+ CUPS PostScript files are device-dependent Adobe PostScript program +files. The PostScript language is described in the PostScript Language +Reference Manual, Third Edition. +

4.4 CUPS Raster File

+ CUPS raster files are device-dependent raster image files that contain +a PostScript page device dictionary and device-dependent raster imagery +for each page in the document. These files are used to transfer raster +data from the PostScript and image file RIPs to device-dependent +filters that convert the raster data to a printable format. +

A raster file begins with a four byte synchronization word: +0x52615374 ("RaSt") for big-endian architectures and 0x74536152 +("tSaR") for little-endian architectures. The writer of the raster +file will use the native word order, and the reader is responsible for +detecting a reversed word order file and swapping bytes as needed. The +CUPS Interface Library raster functions perform this function +automatically.

+

Following the synchronization word are a series of raster pages. + Each page starts with a page device dictionary header and is followed +immediately by the raster data for that page. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BytesDescriptionValues
0-63MediaClassNul-terminated ASCII string
64-127MediaColorNul-terminated ASCII string
128-191MediaTypeNul-terminated ASCII string
192-255OutputTypeNul-terminated ASCII string
256-259AdvanceDistance0 to 232 - 1 +pixels
260-263AdvanceMedia0 = Never advance roll +
1 = Advance roll after file +
2 = Advance roll after job +
3 = Advance roll after set +
4 = Advance roll after page
264-267Collate0 = do not collate copies +
1 = collate copies
268-271CutMedia0 = Never cut media +
1 = Cut roll after file +
2 = Cut roll after job +
3 = Cut roll after set +
4 = Cut roll after page
272-275Duplex0 = Print single-sided +
1 = Print double-sided
276-283HWResolutionHorizontal and vertical +resolution in dots-per-inch.
284-299ImagingBoundingBoxFour integers giving +the left, bottom, right, and top positions of the page bounding box in +pixels
300-303InsertSheet0 = Do not insert separator +sheets +
1 = Insert separator sheets
304-307Jog0 = Do no jog pages +
1 = Jog pages after file +
2 = Jog pages after job +
3 = Jog pages after set
308-311LeadingEdge0 = Top edge is first +
1 = Right edge is first +
2 = Bottom edge is first +
3 = Left edge is first
312-319MarginsLeft and bottom origin of image +in pixels
320-323ManualFeed0 = Do not manually feed +media +
1 = Manually feed media
324-327MediaPositionInput slot position from +0 to N
328-331MediaWeightMedia weight in grams per +meter squared
332-335MirrorPrint0 = Do not mirror prints +
1 = Mirror prints
336-339NegativePrint
+
+

+

4.5 Internet Printing Protocol

+

4.6 Line Printer Daemon Protocol

+

4.7 Parallel Device

+

4.8 Serial Device

+

4.9 Server Message Block Protocol

+

4.10 Trivial File Transfer Protocol

+

5 Command-Line Interfaces

+

5.1 Backend Interfaces

+

5.2 Filter Interfaces

+

A Glossary

+

A.1 Terms

+
+
C
+
A computer language.
+
parallel
+
Sending or receiving data more than 1 bit at a time.
+
pipe
+
A one-way communications channel between two programs.
+
serial
+
Sending or receiving data 1 bit at a time.
+
socket
+
A two-way network communications channel.
+
+

A.2 Acronyms

+
+
ASCII
+
American Standard Code for Information Interchange
+
CUPS
+
Common UNIX Printing System
+
ESC/P
+
EPSON Standard Code for Printers
+
FTP
+
File Transfer Protocol
+
HP-GL
+
Hewlett-Packard Graphics Language
+
HP-PCL
+
Hewlett-Packard Printer Control Language
+
HP-PJL
+
Hewlett-Packard Printer Job Language
+
IETF
+
Internet Engineering Task Force
+
IPP
+
Internet Printing Protocol
+
ISO
+
International Standards Organization
+
LPD
+
Line Printer Daemon
+
MIME
+
Multimedia Internet Mail Exchange
+
PCL
+
Page Control Language
+
PPD
+
PostScript Printer Description
+
SMB
+
Server Message Block
+
TFTP
+
Trivial File Transfer Protocol
+
+ + diff --git a/doc/idd.pdf b/doc/idd.pdf new file mode 100644 index 0000000000..13b5a0f85c --- /dev/null +++ b/doc/idd.pdf @@ -0,0 +1,758 @@ +%PDF-1.2 +%âãÏÓ +1 0 obj<>endobj +2 0 obj<>endobj +3 0 obj<>endobj +4 0 obj<>endobj +5 0 obj<>endobj +6 0 obj<>endobj +7 0 obj<>endobj +8 0 obj<>endobj +9 0 obj<>endobj +10 0 obj<>endobj +11 0 obj<>endobj +12 0 obj<>endobj +13 0 obj<>endobj +14 0 obj<>endobj +15 0 obj<>endobj +16 0 obj<>endobj +17 0 obj<>endobj +18 0 obj<>endobj +19 0 obj<>endobj +20 0 obj<>endobj +21 0 obj<>endobj +22 0 obj<>endobj +23 0 obj<>endobj +24 0 obj<>endobj +25 0 obj<>endobj +26 0 obj<>endobj +27 0 obj<>endobj +28 0 obj<>endobj +29 0 obj<>endobj +30 0 obj<>endobj +31 0 obj<>endobj +32 0 obj<>endobj +33 0 obj<>endobj +34 0 obj<>endobj +35 0 obj<>endobj +36 0 obj<>endobj +37 0 obj<>endobj +38 0 obj<>endobj +39 0 obj<>endobj +40 0 obj<>endobj +41 0 obj<>endobj +42 0 obj<>endobj +43 0 obj<>endobj +44 0 obj<>endobj +45 0 obj<>endobj +46 0 obj<>endobj +47 0 obj<>endobj +48 0 obj<>endobj +49 0 obj<>endobj +50 0 obj<>endobj +51 0 obj<>endobj +52 0 obj<>endobj +53 0 obj<>endobj +54 0 obj<>endobj +55 0 obj<>endobj +56 0 obj<>endobj +57 0 obj<>endobj +58 0 obj<>endobj +59 0 obj<>endobj +60 0 obj<>endobj +61 0 obj<>endobj +62 0 obj<>endobj +63 0 obj<>endobj +64 0 obj<>endobj +65 0 obj<>endobj +66 0 obj<>endobj +67 0 obj<>endobj +68 0 obj<>endobj +69 0 obj<>endobj +70 0 obj<>endobj +71 0 obj<>endobj +72 0 obj<>endobj +73 0 obj<>endobj +74 0 obj<>endobj +75 0 obj<>endobj +76 0 obj<>endobj +77 0 obj<>endobj +78 0 obj<>endobj +79 0 obj<>endobj +80 0 obj<>endobj +81 0 obj<>endobj +82 0 obj<>endobj +83 0 obj<>endobj +84 0 obj<>endobj +85 0 obj<>endobj +86 0 obj<>endobj +87 0 obj<>endobj +88 0 obj<>endobj +89 0 obj<>endobj +90 0 obj<>endobj +91 0 obj<>endobj +92 0 obj<>endobj +93 0 obj<>endobj +94 0 obj<>endobj +95 0 obj<>endobj +96 0 obj<>endobj +97 0 obj<>endobj +98 0 obj<>endobj +99 0 obj<>endobj +100 0 obj<>endobj +101 0 obj<>endobj +102 0 obj<>endobj +103 0 obj<>endobj +104 0 obj<>endobj +105 0 obj<>endobj +106 0 obj<>endobj +107 0 obj<>endobj +108 0 obj<>endobj +109 0 obj<>endobj +110 0 obj<>endobj +111 0 obj<>endobj +112 0 obj<>endobj +113 0 obj<>endobj +114 0 obj<>endobj +115 0 obj<>endobj +116 0 obj[9 0 R +10 0 R +11 0 R +12 0 R +13 0 R +14 0 R +15 0 R +16 0 R +17 0 R +18 0 R +19 0 R +20 0 R +21 0 R +22 0 R +23 0 R +24 0 R +25 0 R +26 0 R +27 0 R +28 0 R +29 0 R +30 0 R +31 0 R +32 0 R +33 0 R +34 0 R +35 0 R +36 0 R +37 0 R +38 0 R +39 0 R +40 0 R +41 0 R +42 0 R +43 0 R +44 0 R +45 0 R +46 0 R +47 0 R +48 0 R +49 0 R +50 0 R +51 0 R +52 0 R +53 0 R +54 0 R +55 0 R +56 0 R +57 0 R +58 0 R +59 0 R +60 0 R +61 0 R +62 0 R +63 0 R +64 0 R +65 0 R +66 0 R +67 0 R +68 0 R +69 0 R +70 0 R +71 0 R +72 0 R +73 0 R +74 0 R +75 0 R +76 0 R +77 0 R +78 0 R +79 0 R +80 0 R +81 0 R +82 0 R +83 0 R +84 0 R +85 0 R +86 0 R +87 0 R +88 0 R +89 0 R +90 0 R +91 0 R +92 0 R +93 0 R +94 0 R +95 0 R +96 0 R +97 0 R +98 0 R +99 0 R +100 0 R +101 0 R +102 0 R +103 0 R +104 0 R +105 0 R +106 0 R +107 0 R +108 0 R +109 0 R +110 0 R +111 0 R +112 0 R +113 0 R +114 0 R +115 0 R +]endobj +117 0 obj<>endobj +118 0 obj<>endobj +119 0 obj<>endobj +120 0 obj<>endobj +121 0 obj<>endobj +122 0 obj<>endobj +123 0 obj<>endobj +124 0 obj<>endobj +125 0 obj<>endobj +126 0 obj<>endobj +127 0 obj<>endobj +128 0 obj<>endobj +129 0 obj<>endobj +130 0 obj<>endobj +131 0 obj<>endobj +132 0 obj<>endobj +133 0 obj<>endobj +134 0 obj<>endobj +135 0 obj<>endobj +136 0 obj<>endobj +137 0 obj<>endobj +138 0 obj<>endobj +139 0 obj<>endobj +140 0 obj<>endobj +141 0 obj<>endobj +142 0 obj<>endobj +143 0 obj<>endobj +144 0 obj<>endobj +145 0 obj<>endobj +146 0 obj<>endobj +147 0 obj<>endobj +148 0 obj<>endobj +149 0 obj<>endobj +150 0 obj<>endobj +151 0 obj<>endobj +152 0 obj<>endobj +153 0 obj<>endobj +154 0 obj<>endobj +155 0 obj<>endobj +156 0 obj<>>>>>endobj +157 0 obj<>stream +xÚíßoä8rÇ¥nõË<ÉÞéwº= $@ÆÓö¸go€ h“y+Iòäa±;{Ùà²{73—àþûô/wë)U)‰ò™ ì®mªÅXüV‘,ªÿòêZ¬6ÿ\‹ïoÄûâ§ÿyu/_ÅòÕ_ÄûÕ®¾ßýñý‡W+ñ‡W7âææúêvWëÓ»‡ì?Þ}z—þë½XÿójWÞïʇ]ù¸+»òîü˾û$¾}ùëçwÿ.nß_¿û7±¾¾~wâV|z|•?Ï/\fE>Þ,‹‹³mÙüÏâöqì\òaqzªrv~ù8N.ys¡F*À-nGÆ%oژžÊùe<.<Ôív \¹ø‹Øq®ûÐã•óµÃ\7\*›æÎô•Ý>³Ìõ <óò]ìWváY)þ¥S\7žµ2Y;Ã%…g³\:Âe¬v»Ì—¼ð¬ÿÍà\YèuQ¾˜ëÞë¨Lâ!¹®½ÎŠ¿ŒË²Z·±6åÍ \2ô<ÁÀI!,—×½sõ‚Ń`qÀ` X 0pZ2øâãÀò¼eO\û-3Íæêk÷Áµòz/“¸î¼Ê´s®Ô¤¼î˜+ ‡á"ˆ"¸¯ð,í€1H!C;`$šAbt®Ì´¬»â +‡åB1Cæx1‡ç"‹=‘Kåùp ¸¼À:Wê9Q֖¹dè×Ä2×Ês¤Ì­r¥ž3%¶È劢œ+ò*kk\™KX­Òã TÔ# LÔ£Š4ðZåJ\Ãjé0ŸÆ£: F¨ñçŒã’.b5Æõ0FGŒ0ŸKF0读Î΋7Ûr¿=øÐm‡A/Ý埿©òí9ˆÎ: ºï.¿!é_>\tÓaÐuw·N•î Ж\«nºªØk ëa=tØ]„ôcÉÍ ^³¹Ø¡-]œI6årqC zznƚ2ÄL.fw±Ò©9]0¹X<7’Ñe>+éFÛ-vْÅöeƒGoZ‘z°¿ªa’öÎI6X3¸DoC‹Ÿyй²°È`>‹,ò¾#’ÂX9š¹Â"‚M©\ÉFÈ1ŘÈ%†Â"‚Íi\™É \؛x½Î­–ÔÈÁZ$o‹tújNáJ,„3Feeps°¤~lŸ‹Ð‚Ï%̓4Ӓñ Qσ®}¹c"X™¡LòŽŠà"ؐÙNm0̱\ÑP™'Ê,Á §y‡Eð ÌͰ;+¤hâǵr + - p\h!M:|W:°Gf(ØÅWà ï¼à$l†á +Ý ŠÖO\)?0®Ãâv®ÈÑ tز+tDãIí Z¹R·º Ùa“V®È±îBú°¸+t¬»OzÞ•9ã’iM +Z¸çº %NZ¸„c£ -eq#—t°»pc~Ùȕ:Ø]¸e¤ ‘ ©ò~¯X(+š4r…E†Dåhâª|ÏX¨á±nàBª|Ð7WN²!àªüºw.„!N¸X[câDϕº(òhA‹µ\à¢È£ÐRË%U œ)Ít\ÒUÕÀ ý©Ž+¥…†eOvú©bìO¿‡Ã3MJªœbýü +ß0`Qs×\Ë%K7jJh%ºÖXÃ%h±F#×TËu¸MQç0ŽCâp†W€ãòô\PP¯ n +´%gx-‘\K-WVx>€5CÌ( Ô\@t^Í\–ko{“S'L,)ýDÍ%ˆÎ«™k¢ç:i…¤ÌzÐÏÁáËõd\ +®“¶§x3Ä(}¬âʨ1T ×\ËuÁˆ²V’`:Ðç^žkªçŠžQH™|gXAò\»Ê·pyz®ôðYÅ %Pq…D3låZj¹ö÷ší…_²k¶©‚KRͰ•+Ðs­ö@¢¾‡j´Üæ+¸Rª¶rùz®ý͉Ӄ)ˆ@öÊ1–kz¬­äÚÇuå!Õ+Or,×,|’'%WA¤(³T³' ÊÆÏ==5W𥶆ˆ³WF6Ãf®´„S㒬Œ§k@”IŽç’Of¡æ:ši±$õˆså€Àµkx çJXkv8¡¢l,)\p¸†K²ÖìZ[Yãb¤/6seQÐpšH\³‹PMšlLr +W~Pzp6œ”IM6f4®ƒÒë¸"N¥(O4ÙXÒ¸J¯ã +9ãK¢ž=p7Q\¥×p¥¼=Œ#Ù@Š6&D®ƒÒk¸"ÞbÛ󟖹$cxµrí•^Ãò6g"ÌÃ’l,©\{¥WseÌ]Œ㘁´¶‘S¹öJ¯æ½˜ERe®ˆ1¼Ú¹vJ¯æÌ̉qÌ@‰¢:×κ#ý¼rÁ0Ä6[—¸X›ÊåØJÁµk½Pqíí^2Bh&P¢¨Xýè⢁øe®S#ª\b¯É‚nˆ+DÀ¬,‚2ײøhª\ ázê(Ân +vfVäB¬ÙL5&1/*ê¤Â•i¸’OF7Ä!@Ã¹Æ$¦õªëŸu®ÕÓC@ïV¢=m‰Kpd£´5, ¾¨À)¹ä±+²!J„]!:ԚDPXV¹R%Wr¬œÐc_„>:œè}ÿö•6×Eͬù©*×ê¨1’žoâ¹2ŽW>ÝÂ?+Ã+âŠ2Wá9öí"à£Ã9ƗÌê\‰‚«˜Š‘ qÕ>`/‡kŒ6Åu®LÁUԛ”< <׊%5›˜æu®ƒ­–¸Ââ€%OÂäcs)p –lTæñôžb^\ä*gD­:ÈhzªX¥Ü©<œb£È• ;é õÐr¨üÞkò&WrÉWX²¼¬ƒTM@G½z;Év/>õÏ{8BJåJ˜røTöƒÕ=®öhÞÏGU+ó“Qr ^å;™ßs¥ÏNæ±\£ùâ$pnÙýh^î¿­ä|]àŠØ2_¬s¾VýÖ;»,-ûV{kÇù”ÑvÛEšEÀ¹å%‚ë´nSœ±’kÎᚫ¹Š#éõ‘K°Ý—_£:•&N9\S%W¦Þ_ÙîK  1ãJ=—§äê}þ¢Ú^u¹©•&.9\KWRW9@¹å –kª _–*®€Ã(¸Âúc´Ìµ7X]î\¥‰פÎõ$þYx´{@¹å͵Tsù*®êq>Wí àQηþä!<˜ ŽkÖȵû¿á•Z0+;–XÅ5Wº¢r<Џ¨èdž6ÛnÌÛ¹/ŸÖvî¼Òñ€b§®ÚEiÉn¨Eì%‚«–RîâSnOµ‰‡«vQyÓéÇ¨0já:¥)²ägÊ&.9\ՋD90ßѐÏ6sI W¤ç +8\Ջ*#eg–@…Q9†ëôƒ"û_Íås¸*UžJ<—ß—â8_;—⢴ê`›r ˜ðpbÎU× Åq¾v.ÝÀ@5_öìpI ×J­óŠã|®úE‘ÒÁ&Œ +r= 9·å&֏ó!¸ê ¥#BqÍP\©Ú¥š8JqœÁU¿H˕Z⊔ñÆÃ) ©4±~œÁU¿(T:"×Ã%½š"7ÎSÇù0\µ‹´\ ?Œ*´áðKô¼RqœÃU»¨XýtG×:7œ͕M¬çÃpÕ.Òr?ŒÊÕ£YU­5ñ Ú4®êE\9š+Pý֏5M¬çCqU/ÒrE¹Öê^ŒÕM¬çCqU/Òr­øáa®68Íò~­‰Õã|(®êEa%MõÈ%¬qù±†«ª–šX9·ãª\Äçš ¹üeá·¿|Xö˜«›X9·ãª\$ +Š]â +ípò‹ñÆ~Ù#P7±rœÇU¹¨G%X® ÇÍSrWáýPŠ&îD›ÊU¾hUˆ¢—×-WÚÄU>·äRœ,6q…åšqeºxþT +"Wù¢¤:TÂ=—ì˜KjNq(Žó!¹Ê¥ɖ–knĕ7r‡«t‘¬„æ‰\‡«|QX`âÀ՞{¸ì«tœËU¾(R$ão¸Òa¹"Wé¢ä´«|Zäœ+åp•.’ÅV¦ÇxÃdZiKr¸Ê‰Óþ×½GàŠ»ä*çCs•/Jjû•.p%®òE•HPì¸L¦Ë(®°™+ãp•/*όƒ•\…ã|x®ÊE¥‹£¹Öú&F®òEå4"Øqµ.oø†\Â+.ÑÎÔ?•«rÑ]q²˜ôÃu|€¦‰’ÃU½è¾°aËò°Ë?üîôþùV®±äÀÊâ™Ah_f]nïžK¼p½pkúL¹‚qr…/\/\/\/\/\8®Ù × W÷\ž9×fæƒ>WJ©;,×ýîfþ%¦¹”ºs]T¯•_6TxÜ¢®z7@½Så)Ji[gÌ%jéå<ýâöT½.ƒk]^ íˆë®>£)¿Ì+;mvÜaNTµr-Ë´.©ØQ*¿Ð09.ñKÔÉ£V®y\ šZ‹â«¤oTê2¸fyihvê¶Ê 8ÂRšLµ.ƒ+([J'\ÙÓÆÓY±nñÕµ§Ýze]פtën¸’ãF¡¼.Ü´ §ì +e]>WÚ%WTر^¼KÁe’Ï5uUËü껖·w’.¹DA äiT4°ðBfM]—Ü>Ý âIg\aqNT”þdº™WKúáñÏÙÙ¦Ì bÎHé뒸¶ç¿ŽiÞ)×D÷‡-O!©¸i©Ï%ƒt;„—q…ºtœÃžrV€ Rwð\«Ãçm?yÝ×>\kâÆIii뒸¢ƒ m-=îŒë°×y¾VX»LŠ'9×Ö%qÁ)ûÕÏ;ã:†èµÖî¿ø!,øb}]%W=±sG‘ÆëÖ}uÇUÈ©´6zò6G_¬¯KáJ°Ú~°WÓ¾^±^é½ÄI=‹V[—•~ܺeC®¦}ØHyŽ£49Ž[ëR¸¤w|!ú¬™ËhYj3KE-«E_—À•óî·ÝqU²hý¸Ö“¢.…kï˜wn¹K®Â‹¶Êª/™ÓÕ¥písºóñ]r=„­åR©’Mëâ¸öŽ9ÝÕ7ãjÍûºU£F(Šº.Þ/ïÜ`¼ý·ßÂe#Ÿíá¢>©I4“U]W²³À[îžëÔÚi%”Z£ê¸öŽyç–ûàz…‰vÐ4Õ%píóÎ-raß-š6‹AS]—|òb³¾¸N‰×í\•º®½cދd#—I>ööU2˲+Ör5Õ¥pmLp’ÖO;á*»Wh]ìÔÕ¥pm$ÃO÷ŽÑ+Æ­¶p5Õ¥pm{:ñŽ/ªëŒkR²-¿‘KW—Âûð~—ɹQú³hÔù¦º®d²fbεlž~͋󐩖«©.…+=9õθ’b®*·©4¶©.…+;͹LÎ!î¯õoO›ZK-WSݖx¾ô¶-YÞ4àš·îÞ6!õ“Ŧº®Â{a»ãŠæjU®†º$.ã2:—5T­r5ÔepÅæ\3\ºM5ô¯Å*úº$®¨ö›¸2½ÂÔ¸2îzT™ŽO¥‘Ëèý嵘×y#—¾.‰K÷~V»\…Æ^æ-\Úº$®ôèӛ¹Œ²·Þè"Ôn”˜Ô5*†ïí9Ê×ëõóU|†ïYr¶¾녫®ö×-“+ú»åŠGÉÕ¾À±%—É„ù…«.£‰å¨¹f£ä’·\Á(¹Ú'`ÓgÊ5'Wø _Ãïãxá€kõ _Ü÷ø,GÉϔ+y†¢á÷š UÚ^ö:7üº¡J[“—¸ï t.Jìp9HµI]lø½œC•ÅŽ.àh %°ß{ëZÀ!Úì ù=Å®­´…mz€ü^i×Åc 8d«¿E~¿¹cGŠãÝ÷Ñ'­Ý˜hË9Ç ­Ã0æêœc^µÊ`äÅ9&ZÝ`܁s,lí@ñ»æÀÚÃ>@Ù«c,kW@é‹c3Ë´]½ås`I{cõs`Q»qÊ`›­Ú£>@őŽ90Ñ.r€N·„ÑVÀ9:§„>CØàzÖ)¡OZ8…qJ褮ªSB!š +È®uIè´9]ŠèÃv÷õÄ%G$ô#ݐc…~69\¸Äx1ÁŒ@†\ b„Q8ȱBïEý"W:ADäh¡w$BÌPäh¡F"‡³"Bè@Ùäh¡wD8V(´zº"!böUàJFIµ +Á~+r¼Ð£I™ !ô“QÈFPæB,Ýø£Y…KŒC8Bœ +þA8qHäüá:!)ÒËá +„#B¶r‚ :°˜ÝªÓ*BðÌØå +È)‚8sx-k\Ñú,(ÖCéÑg­!' ÇÐ ýŽÈIÂ1ðkôS—p~€áï€d¼C°z @NŽa>r’sx€¥ø©båa÷H*:pˆH؇œ(0Ê&ÐúyÐ9eˆ¹ÈDr‘ƒ²Ôā9 Òg”AĞPéI+Ò@½t8¥”¦UI[m“$MêÐ̶4Õr­Ü5DÚò äô6wÔ ‹±]ú@†˜Ð È3œ qE{Þ@·âA QCW Oq†1Ąø¸!g °bDAsX࢖fÀy0ýOVêÆœ3ÀzŸ5 ªšAÎ`='Y¦dï9k€õìÂ"òØV—÷¬’Þ"` ў•ƒµgºÝwÌ!è#8Ë#=Ç)À€7H{•úcÀóñô(õ’ó˜û9ý‰Çñw˜ö×a¬á\Yí­Ãp­™!¸JßS‡…¬g üê§Ã˜aðGj?òÂ:`;Â~:,a:SàKP/ArHä8®léFwM‘\©#&Cn¹‘!V¾ji˜PC5˅ÜÌ;8K¾Õ@nfˆj=öéÎÑ\xCìP:R›ÜÔýx`WŠ˜ l—–xçñÍPË%½¡-13’.ȍ ±#MF>ŒmGÞm…ê•10µÝxçÌÐZÀØ×w2Ädh([`ã‰ÙŸ±¬L)X¸ö½Ø=áÆ9•+!u˜Mí hV@æ’Þ@`24`ÇÈm‚Iaá¦`É,T¤q=gpÑî°)ßõ,… ¡XX](X…¹*^Û1°1_µFÃÒÇ`e}¡àNÖ}bé¥ +lEiG°7=)aóf0XÔ&Sõ c5œF{žÿd<[ÌBê6WrÀªßtŽ*7ôÛ¬ù\ ‹Ëóo©Å°ø¦8 ‹ÙažwwÜYÍs£V®Èãü—Î?Ö0ÎM¸¤Ç/ç(kÌ.xŸ¾4â2è°í8»l3Ç&UËô¡Ë¤ÃöhúϾ ٟ;7ä¢NÔyùXë7ù°MWnʕyvÊÙùb±xó¸)‹ÅEhøisc.f½´å?b¸¤ƒ\s \f’8Hwá¸Üë°¥.ç:¬}é Ç%ÇÖ]H.®M± ‡äÊC—¸Öö¸Òquš‹µÒёÆÇ6¹2g¸æ¹M.g´·½ç’áX4žÆÅ]Â@4h\NHv¿—Â%Gc…4.,½uHâÜñY4®l$VHå8þ%l`¹µDJî •kHïLÙ~¢r ؓ’æÈ\ƒ 1ZÚ k !FL,cp 3Ĉ{» ®A†5ˀÃEIB3Ø\½k=UŽÇÕ³v02™\R¸+…&\}Š"+u˜ËÕ/“ŒÍÅHûéÅqsõ4cž80àêÃ?û܃&\ݛ"?Kӈ«k0ƒäS3®nUÑ$Yؐ«Km”mÊÕ˜Y2¾19‡º£‰‰}®.¦-†éêv¸ìË¢ù¹ +\¹´k‹—æ-²Ãµ±E{]6YçîpåòβÉe©ËÎ×¹k\¹¼1–Á7¶Úb“‹ŸZ} º´×»\éՈÔí!¹¸dv©ºà␝¿±Ý†.¸ˆyñþ¢ƒ÷\tõ)¸ìxÿü¶“ÛwƵ뵃<[ùåǟ>‹ÇÏ_ýãoÛÿüôå×?ûõ÷ßþQþ÷æ3nÅõõö3®?Ü^½o¯ß_Ýl?e{õÛOo¯¯Vۊo¯×WÅۛû›Ä?~ý›È~ÿåÛÿýøå³€/¿ÿüן¾}ÝU¼}¿iÌés~ÿóß¾üúÇÿú¶iêÇïßnþõñŸÄݟþ$Òí/¿Šôó×Ï_þ÷óÏÛKc¹ûÇó;endstream +endobj +158 0 obj +6325 +endobj +159 0 obj<>>>>>endobj +160 0 obj<>stream +xÚ+ä2T0BCc3JÎår +ár á +äHÉHendstream +endobj +161 0 obj +31 +endobj +162 0 obj<>>>>>endobj +163 0 obj<>stream +xÚ¥UKOÛ@¾çWŒ8D\œ„!ôZÐîB’7†³Æ§ë„˜eéö:0KOCˆYâÙìÑG/ƒ¾7/ûÏB˜¦Xžñ„. ŸÜ0¬S[]Ÿ:[q ¼0¨2– ¤¨ù²°_‰â¥­„T&UN½ TrÍ)BQøÀ2ú ™T93úrԚ-°"µEKÅr‹O¨a;hYÔDkKOÚ¦ƒY!ŒdžÜý×éˆQâÅâ­6˜ÃüôdtÅ'ó3x@¥-­0¸^± =ØYÐÚ[£ZsܼáÁÛè/”R¶ Õå.G°-*'ÂÖÎ[—] á(æ‚Ú5ÐL ¬˜>rah­^£ Š[˜0½…XffÙV‰Ñ`¤åKƒDAò•©tOAKQ¹QYL¯‚ N¥Òv +G¸•&°ŽîµÙÔzÜ䆨žPಆ4/p¿*:¨»î\tí¨µo5µy𽙤ÆÈD +æt2»nN£ˆÆÉ|ú‚iîW ØÒæ;yð(N>>>>>endobj +166 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS046V072PIÑp rt QÐUp VðÌ+I-JKLNUpI-ÎLÏQÉE™%™ùyš!Y\º ºPF 3=30ßP!89¿ $êÂȐV!õendstream +endobj +167 0 obj +120 +endobj +168 0 obj<>>>>>endobj +169 0 obj<>stream +xÚ­•OÚ0Åï|Š9²Ò&K 7 +l…T´) {ââÆp•ØÔ6Úòíkc•V%]å@Æ¿7ö¼?ZtÌÀ „nòªõ)k=½ÄĐæMЃŒ¶CX`yŽê!ûîJžýÈyϑïÊüÆË$…‰ÈwrM4Ü-èAËþ+Ï6…(KñÎøÚ-¤— )µ.…o{ÐóU]3tàü#?<³Wa×Êm«àç‰ø¡Ó ^°õN:½9ád– IIø5ß4tÄßà³Éäžî•Æ +f\£,HŽ0AÅÖÜÞrɶ糹G"Í­„ÿ³…~'aD+ƙÒf/B*»—)ð¯·PÓ?¤õd~ H±–¤ª¬ w.n¡SÌw’é½±ïVH݀›%·¸ª¦I—˜ßRáÿŒímrûf¨ÖÛ¿Mîœ`ÏE§×)áUoPžb¬þ1Â\pï*Æ +l ™áÙt:…  üÞc° ç›Ý ¡×¶ŸU›JRèÕÃ]ç9K’§ÃÌG”2K$%¼nOèdxÆ^‚fì)ϵ=N!“„«» zbͪmyøÕ²ú¼c›qæ‚byh(Ŋ˜#ÌÕ] ÅËØ<âGøÂ8º1X¬ŒM̵ÈÅÑÛÑqÑÑ{aßúŸéE?6²æU×~žf­¯­_Ð&Ùûendstream +endobj +170 0 obj +522 +endobj +171 0 obj<>>>>>endobj +172 0 obj<>stream +xÚ-‹Á +Â0DïûsÔC´›”êµZ Þ´® q#ŒšöÿшÌÀ03¼71ª¯®)öÚ-û5˜!ìV¶‚\gÝÐöƒíùpÂ>MšÃÅ+:ã-•ð9¾¦øLs¹“) ù“uYjˋ¿n1hЬÉëX®Ð‘>H.#ùendstream +endobj +173 0 obj +123 +endobj +174 0 obj<>>>>>endobj +175 0 obj<>stream +xڍ‘QOà …ßù÷Qd£”¾:×d‰KfÆ ”v˜–ÖҚøï½•ÆiLÍ ä|‡s.¼k\ ¶ 𠘆<*²Ê3`¨•Í6UÜq8øÁö^×qSjcýz¬ 2ÒBÒÈS»‹îµAÎv€ÜÕÑñ‹JàYûjԕ]8ÇýUüʛ|1/•TÌ &6®±tøè¾ïù)'Q6­ÿ¿y +§ÓÓBgs±ÅXãT»Ö—®{=¸ÖßÐP`C3v¡˜:” +´t½›^7,L­C°W`•K`lÎb<›Ù¥ïJåšfˆ"#¦ó^‘ò Àt‰ìendstream +endobj +176 0 obj +243 +endobj +177 0 obj<>>>>>endobj +178 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS046V072PIÑp rt QÐUp VðÌ+I-JKLNUpI-ÎLÏQÉE™%™ùyš!Y\º ºPf c K= 0ߢ=/1aN1HkW «'jendstream +endobj +179 0 obj +122 +endobj +180 0 obj<>>>>>endobj +181 0 obj<>stream +xÚµWMoÛ8½ûW zjZ+êÓ^`Nšú‘µ½{ꅖh›»2©’T÷×wHÊ®­¨¶/A€@gÞ{3ÊßBü#GgPl7óÁ÷c c˜/q%˘—o¸{6L ZÁƒÀ‡%-˜~7ÿÏcÓ`äÑÃtx|@`R×/¨áRÀLÿ3JYÈÊî>>>>>endobj +184 0 obj<>stream +xڕ˜Qs›8€ßý+öñn¦ø„„1<ÜCÓ4×tšL.ñMŸ‰‘‰:Q!çzýõ·BÂX:ÉØ|r´ŸW»›|_„@ð+›ïí~qµYüqAÂf,¤'á2Mþ…?á}þšU[J–%d;Í|“Ï¿o¾-![R2?Øp=#?Xg7äÇ͂, îïøðøDɒ@¥KÜ# ñ5^ˆAqxòÀá:}C“ š‘Ë4jY…³•Ý9£€Æk³KÜÄk0‚Ls{Øk#Ì%TRÃÖÞÆçZðf`"DîÆøh0†ûàh2A;^Ú ]2ÄI@×a_ÀAßñ\dgîù+~¬Ûƒ†}w;.}›;QòEÏ)æ Ö  éŒ[Eì(|m^Ž +ïh2A[á~Ú +_ÑÄ _S¾ê ¿>Ô%ÿq¦ûA‰JC#ª¢äA#rž{Œ[(—‡ç·ÐˆÜj<;ã:z^Æùi+ JWx¡4a=Ÿ¾>òF–-dÕÓðI*ñSV:ÃO¸ÊÓO‹mV<¨ãbÕà^.uÔ\¢Ú¾,ÇÝDñ)9¢xªu4™ ­?íÜD]r$XŽÒ´çævŸ˜WòPåís?QnäAaԚ\5PˆWd@¿ ]ÉwúÖÆF=Ó¨—vF)µµgX4Ú¯w™ÂÚØôl¶™Êf‹`AkÙ@‚ÀºÊçÖ.Šõe~×ìèy]ÓOÛèÃ$u“bõ¢l}uÈÊn[¾¯xí[¢üvülx¸4Âݽ]sô.» Wë_èš=¯hùiç&ê2ƒbÑ¢ý¢Õ°®“õôÜV5M‰zºN;…‰B2´„û‰Èé¯dEGÏË +?í"'ǬÀ*ÃÂóÈ¿rS+zq·×áßö†IûBeûp2:ˋ¶Â~?djj–Lɱ¡O‡ïàyÑ{aüÚÖW†Õ€õÇè;¡”Tí@|ñ@´Ԇñu­»áý‘AúÔafÌѧ–1cŒöÁnRìÚ ‹1ü~1¼çE¦Å+? +™3Nc5¦ÇnjÓÜ0»)÷ÿ‹HÜÿ"BÆ`Míß=ïo6À‡žp`¼Ûe[×¼Eež¶JÔÝÌÂÀ­LÌ–„ËÔÆ¡¦ö]³Æ¤ï›6PÁߋÿ́endstream +endobj +185 0 obj +1105 +endobj +186 0 obj<>>>>>endobj +187 0 obj<>stream +xڕ”QOƒ0€ßù÷¨°ëèhytNŒ‰&s«? Án©²¢…ì÷{µÄ,q[ „ƒÒïî¾\¾H1‡¼€ú,Uò ̐¾ÿ…Í#p™!%£ÈòÝÞÀö ËDyãu8Ç p´|‚ŏ³G !&X ð8‹qð`S,pŠŽ·(ò <ÎâLgtV•À™µ£ó[ fsPï7<[À“ëw¦‡µ·®·nO/mßÖms«>„t!3áž­34VÚZw°Ö^7i`e޶6ÿ [ã­¾¸_†ý#µz1]§÷–M[^îÈ”·ÇP±²¡…vݎòO3f•ÆÂ$XžgŒÚPöjsW)Háþm½CÙéڐYg÷.>>>>>endobj +190 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS046V072PIÑp rt QÐUp VðÌ+I-JKLNUpI-ÎLÏQÉE™%™ùyš!Y\º ºP† !c C=K°€‰ž Ę Äb 9 +n™9© %®!\\‰¨%üendstream +endobj +191 0 obj +129 +endobj +192 0 obj<>>>>>endobj +193 0 obj<>stream +xÚ+ä2T0BCs#c3…ä\.§.}7KCK…4 Œ™¹‰BHІ©‚s~nnb^Š®Of^ª‚g^IjQZbrj±fHD½©žD‡®©…Dž¡‚Sbrvj^ +šEF +n™9@Y C- aFššÕr‡‰¹ Ð u†† ×®@.» =Cendstream +endobj +194 0 obj +140 +endobj +195 0 obj<>>>>>endobj +196 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS046V072PIÑp rt QÐUp VðÌ+I-JKLNUpI-ÎLÏQÉE™%™ùyš!Y\º ºP†F !c =S°€©‚s~nnb^Š®Of^*°b:×®@.l·(Èendstream +endobj +197 0 obj +131 +endobj +198 0 obj<>>>>>endobj +199 0 obj<>stream +xڝTÛn£0}ç+æqû- Íå1‹’4RÕe•öÕ5êÆj;ò÷;­´—biW ÌáÌ9žc^“nèÈa>é ¸J¾6Éõf ùš=UfóšöË +¶Ò8Çìùªy·Ùb€¤·‹le94h•03Èó€ Þt2 åP*>)­€Õ=ZLwGÖaö;Qú+¼g–I‰rœ°FÝ +݁±`‘£x -ó ”±þ™i2þ$<0:Á o(zŒ©7Ó;ê¨g^í€SžÐŸ5ø“ÞšÎ2åbíZÁþËÝ?xr†ÐÇ\‘Ü‹+Mò=Œ¸ËþLEJyJ§Ë\L`Å­ÑçX4Vu¹ÛE¤(ZN#«=Ó-³-”¦Eؓÿ¦«º(¢{ +PPÕaÄwùXÕã­JòHT»PY¡}XÚúì<ªçº.¯«qÒuU{øDü¥ZaÞ4ލeÚí1°o¸‘¶»*ÝޏóÝáI¢÷iÅø!ÝZÖ? îàþ}SŸ.>¨Ã ‹Mø¯¿D1/( 7¡OËu“|O~ÇJ8Rendstream +endobj +200 0 obj +426 +endobj +201 0 obj<>>>>>endobj +202 0 obj<>stream +xڝ’ÝRƒ0…ïyŠ½Ô °´ñ²?0¶c”ø1M1 iýyzªíԙÆêÀ՞ÙosÎî‹BÏ|! bûÓÆcï"‹! /m)N¢ ¼8»F>šäçøÉèÑ^÷ûqu:{­™Ö>"tEԐâB3)´’5äDTkR±-á{‚€0#æÿ1—§àg)ΎÃg%˜†TT\0fØ`Ò® “Š:¹€ík™HI-©¬]Äòæ7"Ñ\ +RC©‰X˜0Z¸Qü£ìM³sã|따Ɖ*fEzœU¬kͶàv!„א¾ÑG³-W¤ÎKCfÍ9+ärŒd«Kªø³ÞûfmWpçXããԒ©!¬mícǵ¤+ gØqBXñ 7«ÎxÍ+"Ú¥ažQòÕ‡0L®‚ØöMïF&÷¨Ü®`I(³öx%~ºôÃÁüË~Ïv†‘-Ea ¡+Œ‚>Œ¨’â½i­”bïÖûšÚ' endstream +endobj +203 0 obj +376 +endobj +204 0 obj<>>>/Annots 116 0 R>>endobj +205 0 obj<>stream +xÚ՛Ír9€ï~Š>î¢4ÿºÉcbÇ©T%5ÞXó¹íh¢OKölÞ~ T“vÔî!굫d1 ?J €hæ¯ QÕþWT­¬TS-7ïço¯]%\5¿¯D£f²jZã_çwÿ˜/þXwÕÜmÝö°ÿçüϋó‹zV{ +¼xùúU£¬¶©à߯«[à¿èÞ?To¯M%ÌÃÎ&ªQü€ÜTÊÌlÎG)Qn—»Ç@¥¦Y¥ñÓù.³ÉÿˆQM¨4-ÝTFÎ 5UkRµ·w#› é£ëºñ#h;‚äôéߊÕýj¹8¬v۟kÝ´³vJz/é6|ã¨ÛÐÕ-hTHß#èT–tJdÛʜLb"Ýþغ ³†ñÞ@J?tÜ('ÚoÏ]ÿ¼êþþ¹q´˜¹I§`ã¬ÿRdlpV1ÎÍh¥«‚U"YÔ°+24É uµ[>mürç¥Ôz¦s`ì@Ăi¤_Qg6`¾iåÑáãû“¾iºjÉ;üˆ7 ®ŒR¢|íÛ.»ýˆÝ´üÏO~Tañ{ Ý=6Ns÷¦ ß[Ý}œÁ‚ÓÈf@1r.¿¹eL6Œõ‹ßÔ`´”„r$ŽĄ¦9¯ÑJ6ÑfØ`’nÐËb˜ˆd[{ߕ‘IL¤ßߺž1Ç0¢D ¾(…‘œ`Ñ ã{HNb)Þ! ç¿&9¤ðþ4‡$A;þË©‚C"¼×†ÉùA)Ÿ|®ÜoëqXØT®yICq†»_Œû·éy7SØ;uƒŽ=¬çÐ8џÕ-ú|Uöh4‡¿u>‰‰tùmÑ/–n'%Hˆ5¸±è쀻í¸ü  {þf¤Ø`׫õ˜Ñýâ˜Â†,Z;5.lpNR;܅E¹!·Ê¸$œÏ‹íÃÓâ¡c-ÛaBÖǏ|´ììø©cø½ë&³K&iÝ·°ÁšÄ‡ ‹F)%ґl¡x‘QI_>}ùÀøÙa4ää  e¡<²x£4ÓrŒã–ñ¹­·LӄsƒƒŒQË´^M‹§oÎ&88“´/á$'Øfµéf‡Ýt’ŠaÕRƒU£Ñûg¬ßIp˜ÝÊNr‚5.wÛç5š3+±ä$t=hl°NB‹–uÉI¹5¾kF&1‘nn®ÆIÉàhç”DbQ¢pÿ?˝´l“¬i$yoS2 qlðŒKb,M-¿uwOk6[›POnsÉîr·½_=<õáÈäM Å3}93v°å¬Éþrƒ—ü•P!Öá: Ö_…MZvûĆRT›ÃIN°åÓãþÖýˆÛ‡3ʙwJIu„ÏÐ`õX‹>MÙï[ø½Ðæp’ì±_ÁimϨÒè3¬ÁÿBÊ¶CüħGemŒŸ†K¬GHÎ28É ¶\/öûŽUãd#(œ"T#°ž6“ôþ¤B„jBÈÒ|" Ôî3:JãÿKEˆdxpûuÎ"±<©¡§–kûŸ–¤*¤ÂH±qZBi‹NS‹qNôÙ$$'Ô»ÇÇ5=Dã/ (À©3cƽÝ-¿³åˆ„àyí«Ï;ï¦ßvËÝúçkÀ+UŸc ”̬ôðà\¾¤”AO®‹EˆHuíŒLb"P5(!­÷¡‹äÄzßïþÞ¯¶ŒQä_00ÆD,õlµÅ’Y}f Ö¬Rb`ÑÅ2F$£âS2‰‰tŠY Õ÷6g‘œX7»ýávÙ¯ÙÝ:@ð ïrdì@LHƒG*#¨Ïë­KÖ­ípþÄkݚî~èâù3’Qÿ)™ÄD:ź„>­nrɉõu±gëË)à¸XR\ìà†í¨e§Qˆ,ØWºäþ +68ûJG.¹tˆ\ë^rIÜ Ïg¸È˜Œ§ X2ÉɁú”¿à’¸d퍔áb‡Sò9O®`U›ÜœÁkU+cՔìJäPÙÉÈ$&ÒçÕ¶+”"Jø &rÉeÌvÂQŽKÇ8äW¼Ø€W‹næw:ãÙWß5v“MÇJ ¤I.ñ`ƒ] ‹¹X[Z DöçG—“IL¤›E¿X¯;æT”â#¡ŒGòx'¨{^-ÇnNéDÉ2Æ é6X˘&¦S¶d"Ûô–’IL¤Û®_q§Õd<„\¸Ò’ÑHN´‚]Ԕ«%Óh9äBØ`M£U̅\É4D¶ú8MfšHò¦yfošèäc + 崌fõÀúÒí÷ì#Ùt<ÜôKZì@À÷kÊep Àãœx©Ä؁p§j~yô-­IWÃì±Á®USå¢f‡MÀ²Ñ llÄÌûÕ3»i“Á°i¡lš¡PŽ0Èj¹yo—e(ê?Øb»¿gƒ·Éxª9Ï$¼b¨ýåÇdǖe-1ÂÒïO*?ÊZaX3|òˆÅÇ Êån³YlïÞðY™M‰B™WȌY¬D6g®®‡[³…Ë̺!Úbã´Ò£pt'ÌKqOƲ9PIïËïÝöŽÙÃìÓú™3ÊÝ©—ÕÄ‚oÑ>mr? œSÅÊi°J©fÉ­5¶/o¥IÞ²gd<„\(ùd4’­h9‘۝œeÀ¯Ás#<¼ÁšÓޝÙŽ œ9ÖÙ¹ãܑ,/ó P9×;ŸÇô?F‚›à½‚—š.Üo†Û‰á¬y$6NôQŠ®½c}ԀõqD'Œ»ÅDšwýfì‰~;ÿ¿¨WâM"ü¢R\BÒÅ¢w¬‹`°G`­fh’GÔ²ßmlÆé©i)UúöÚÆµ·Œ£çW_ß]Ï«7U(Ü^uÕíW[øÊëô¿ ”sÀ›V†/¸"…þëâ?Ü`ˆÐendstream +endobj +206 0 obj +2162 +endobj +207 0 obj<>>>>>endobj +208 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS046V072PIÑp rt QÐUp VðÌ+I-JKLNUpI-ÎLÏQÉE™%™ùyš!Y\º ºP™™ !×®@.'endstream +endobj +209 0 obj +104 +endobj +210 0 obj<>endobj +211 0 obj<>endobj +212 0 obj<>endobj +213 0 obj<>endobj +214 0 obj<>endobj +215 0 obj<>endobj +216 0 obj<>endobj +217 0 obj<>endobj +218 0 obj<>endobj +219 0 obj<>endobj +220 0 obj<>endobj +221 0 obj<>endobj +222 0 obj<>endobj +223 0 obj<>endobj +224 0 obj<>endobj +225 0 obj<>endobj +226 0 obj<>endobj +227 0 obj<>endobj +228 0 obj<>endobj +229 0 obj<>endobj +230 0 obj<>endobj +231 0 obj<>endobj +232 0 obj<>endobj +233 0 obj<>endobj +234 0 obj<>endobj +235 0 obj<>endobj +236 0 obj<>endobj +237 0 obj<>endobj +238 0 obj<>endobj +239 0 obj<>endobj +240 0 obj<>endobj +241 0 obj<>endobj +242 0 obj<>endobj +243 0 obj<>endobj +244 0 obj<>endobj +245 0 obj<>endobj +246 0 obj<>endobj +247 0 obj<>/Outlines 210 0 R/PageMode/UseOutlines/OpenAction[162 0 R/XYZ null null null]>>endobj +xref +0 248 +0000000000 65535 f +0000000015 00000 n +0000000225 00000 n +0000000286 00000 n +0000000364 00000 n +0000000441 00000 n +0000000520 00000 n +0000000596 00000 n +0000000677 00000 n +0000000735 00000 n +0000000837 00000 n +0000000941 00000 n +0000001046 00000 n +0000001151 00000 n +0000001256 00000 n +0000001361 00000 n +0000001466 00000 n +0000001571 00000 n +0000001676 00000 n +0000001781 00000 n +0000001884 00000 n +0000001988 00000 n +0000002093 00000 n +0000002198 00000 n +0000002303 00000 n +0000002408 00000 n +0000002513 00000 n +0000002618 00000 n +0000002721 00000 n +0000002825 00000 n +0000002930 00000 n +0000003035 00000 n +0000003140 00000 n +0000003245 00000 n +0000003350 00000 n +0000003455 00000 n +0000003560 00000 n +0000003665 00000 n +0000003770 00000 n +0000003875 00000 n +0000003980 00000 n +0000004085 00000 n +0000004190 00000 n +0000004295 00000 n +0000004400 00000 n +0000004505 00000 n +0000004610 00000 n +0000004715 00000 n +0000004820 00000 n +0000004925 00000 n +0000005030 00000 n +0000005135 00000 n +0000005240 00000 n +0000005345 00000 n +0000005450 00000 n +0000005555 00000 n +0000005660 00000 n +0000005765 00000 n +0000005868 00000 n +0000005972 00000 n +0000006077 00000 n +0000006182 00000 n +0000006287 00000 n +0000006392 00000 n +0000006497 00000 n +0000006602 00000 n +0000006707 00000 n +0000006812 00000 n +0000006917 00000 n +0000007022 00000 n +0000007127 00000 n +0000007232 00000 n +0000007337 00000 n +0000007442 00000 n +0000007547 00000 n +0000007652 00000 n +0000007757 00000 n +0000007862 00000 n +0000007967 00000 n +0000008072 00000 n +0000008177 00000 n +0000008282 00000 n +0000008387 00000 n +0000008492 00000 n +0000008597 00000 n +0000008702 00000 n +0000008807 00000 n +0000008912 00000 n +0000009017 00000 n +0000009122 00000 n +0000009227 00000 n +0000009332 00000 n +0000009437 00000 n +0000009542 00000 n +0000009647 00000 n +0000009752 00000 n +0000009857 00000 n +0000009962 00000 n +0000010067 00000 n +0000010172 00000 n +0000010277 00000 n +0000010383 00000 n +0000010487 00000 n +0000010592 00000 n +0000010698 00000 n +0000010804 00000 n +0000010910 00000 n +0000011016 00000 n +0000011122 00000 n +0000011228 00000 n +0000011334 00000 n +0000011438 00000 n +0000011543 00000 n +0000011649 00000 n +0000011755 00000 n +0000011861 00000 n +0000011967 00000 n +0000012749 00000 n +0000012783 00000 n +0000012817 00000 n +0000013281 00000 n +0000013330 00000 n +0000013379 00000 n +0000013428 00000 n +0000013477 00000 n +0000013526 00000 n +0000013575 00000 n +0000013624 00000 n +0000013673 00000 n +0000013722 00000 n +0000013771 00000 n +0000013820 00000 n +0000013869 00000 n +0000013918 00000 n +0000013967 00000 n +0000014016 00000 n +0000014065 00000 n +0000014114 00000 n +0000014163 00000 n +0000014212 00000 n +0000014261 00000 n +0000014310 00000 n +0000014359 00000 n +0000014408 00000 n +0000014457 00000 n +0000014506 00000 n +0000014555 00000 n +0000014604 00000 n +0000014653 00000 n +0000014702 00000 n +0000014751 00000 n +0000014800 00000 n +0000014849 00000 n +0000014898 00000 n +0000014947 00000 n +0000014996 00000 n +0000015209 00000 n +0000015361 00000 n +0000021757 00000 n +0000021779 00000 n +0000021892 00000 n +0000021994 00000 n +0000022014 00000 n +0000022154 00000 n +0000022976 00000 n +0000022997 00000 n +0000023110 00000 n +0000023301 00000 n +0000023322 00000 n +0000023462 00000 n +0000024055 00000 n +0000024076 00000 n +0000024189 00000 n +0000024383 00000 n +0000024404 00000 n +0000024526 00000 n +0000024840 00000 n +0000024861 00000 n +0000024974 00000 n +0000025167 00000 n +0000025188 00000 n +0000025328 00000 n +0000026506 00000 n +0000026528 00000 n +0000026650 00000 n +0000027826 00000 n +0000027848 00000 n +0000027970 00000 n +0000028373 00000 n +0000028394 00000 n +0000028507 00000 n +0000028707 00000 n +0000028728 00000 n +0000028850 00000 n +0000029061 00000 n +0000029082 00000 n +0000029195 00000 n +0000029397 00000 n +0000029418 00000 n +0000029558 00000 n +0000030055 00000 n +0000030076 00000 n +0000030207 00000 n +0000030654 00000 n +0000030675 00000 n +0000030830 00000 n +0000033063 00000 n +0000033085 00000 n +0000033198 00000 n +0000033373 00000 n +0000033394 00000 n +0000033449 00000 n +0000033554 00000 n +0000033698 00000 n +0000033804 00000 n +0000033924 00000 n +0000034033 00000 n +0000034182 00000 n +0000034292 00000 n +0000034399 00000 n +0000034557 00000 n +0000034668 00000 n +0000034787 00000 n +0000034938 00000 n +0000035042 00000 n +0000035146 00000 n +0000035260 00000 n +0000035417 00000 n +0000035521 00000 n +0000035641 00000 n +0000035747 00000 n +0000035906 00000 n +0000036025 00000 n +0000036152 00000 n +0000036277 00000 n +0000036398 00000 n +0000036529 00000 n +0000036662 00000 n +0000036782 00000 n +0000036900 00000 n +0000037034 00000 n +0000037157 00000 n +0000037319 00000 n +0000037429 00000 n +0000037538 00000 n +0000037672 00000 n +0000037769 00000 n +0000037869 00000 n +trailer +<> +startxref +38055 +%%EOF diff --git a/doc/idd.shtml b/doc/idd.shtml new file mode 100644 index 0000000000..29b7a7b89b --- /dev/null +++ b/doc/idd.shtml @@ -0,0 +1,381 @@ + + + + + + DRAFT - CUPS Interface Design Description + + + +

Scope

+ +

Identification

+ +This interface design description document provides detailed file +formats, message formats, and program conventions for the Common UNIX +Printing System ("CUPS") Version 1.0. + +

System Overview

+ +The Common UNIX Printing System provides a portable printing layer for +UNIX® operating systems. It has been developed by Easy Software +Products to promote a standard printing solution for all UNIX vendors +and users. CUPS provides the System V and Berkeley command-line interfaces. + +

CUPS uses the Internet Printing Protocol (IETF-IPP) as the basis +for managing print jobs and queues. The Line Printer Daemon (LPD, +RFC1179), Server Message Block (SMB), and AppSocket protocols are also +supported with reduced functionality. + +

CUPS adds network printer browsing and PostScript Printer +Description ("PPD")-based printing options to support real +world applications under UNIX. + +

Document Overview

+ +This interface design description document is organized into the following +sections: + +
    +
  • 1 - Scope +
  • 2 - References +
  • 3 - Internal Interfaces +
  • 4 - External Interfaces +
  • 5 - Command-Line Interfaces +
  • A - Glossary +
+ +

References

+ +

CUPS Documentation

+ +The following CUPS documentation is referenced by this document: + +
    +
  • CUPS-CMP-1.0: CUPS Configuration Management Plan +
  • CUPS-IDD-1.0: CUPS System Interface Design Description +
  • CUPS-SAM-1.0.x: CUPS Software Administrators Manual +
  • CUPS-SDD-1.0: CUPS Software Design Description +
  • CUPS-SPM-1.0: CUPS Software Programming Manual +
  • CUPS-SSR-1.0: CUPS Software Security Report +
  • CUPS-STP-1.0: CUPS Software Test Plan +
  • CUPS-SUM-1.0.x: CUPS Software Users Manual +
  • CUPS-SVD-1.0.x: CUPS Software Version Description +
+ +

Other Documents

+ +The following non-CUPS documents are referenced by this document: + +
    +
  • IEEE 1387.4, System Administration: Printing (draft) +
  • IPP/1.0: Additional Optional Operations - Set 1 +
  • IPP/1.0: Encoding and Transport +
  • IPP/1.0: Implementers Guide +
  • IPP/1.0: Model and Semantics +
  • RFC 1179, Line Printer Daemon Protocol +
+ +

Internal Interfaces

+ +

Character Set Files

+ +

Language Files

+ +

MIME Files

+ +

mime.types

+ +

mime.convs

+ +

PPD Files

+ +

Scheduler Configuration Files

+ +

cupsd.conf

+ +

printers.conf

+ +

classes.conf

+ +

External Interfaces

+ +

Application Socket Protocol

+ +

CUPS Browsing Protocol

+ +

CUPS PostScript File

+ +CUPS PostScript files are device-dependent Adobe PostScript program files. +The PostScript language is described in the PostScript Language Reference +Manual, Third Edition. + +

CUPS Raster File

+ +CUPS raster files are device-dependent raster image files that contain a +PostScript page device dictionary and device-dependent raster imagery for +each page in the document. These files are used to transfer raster data +from the PostScript and image file RIPs to device-dependent filters that +convert the raster data to a printable format. + +

A raster file begins with a four byte synchronization word: 0x52615374 +("RaSt") for big-endian architectures and 0x74536152 ("tSaR") for little-endian +architectures. The writer of the raster file will use the native word order, +and the reader is responsible for detecting a reversed word order file and +swapping bytes as needed. The CUPS Interface Library raster functions perform +this function automatically. + +

Following the synchronization word are a series of raster pages. Each page +starts with a page device dictionary header and is followed immediately by the +raster data for that page. + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BytesDescriptionValues
0-63MediaClassNul-terminated ASCII string
64-127MediaColorNul-terminated ASCII string
128-191MediaTypeNul-terminated ASCII string
192-255OutputTypeNul-terminated ASCII string
256-259AdvanceDistance0 to 232 - 1 pixels
260-263AdvanceMedia0 = Never advance roll
+ 1 = Advance roll after file
+ 2 = Advance roll after job
+ 3 = Advance roll after set
+ 4 = Advance roll after page
264-267Collate0 = do not collate copies
+ 1 = collate copies
268-271CutMedia0 = Never cut media
+ 1 = Cut roll after file
+ 2 = Cut roll after job
+ 3 = Cut roll after set
+ 4 = Cut roll after page
272-275Duplex0 = Print single-sided
+ 1 = Print double-sided
276-283HWResolutionHorizontal and vertical resolution in dots-per-inch.
284-299ImagingBoundingBoxFour integers giving the left, bottom, right, and top positions + of the page bounding box in pixels
300-303InsertSheet0 = Do not insert separator sheets
+ 1 = Insert separator sheets
304-307Jog0 = Do no jog pages
+ 1 = Jog pages after file
+ 2 = Jog pages after job
+ 3 = Jog pages after set
308-311LeadingEdge0 = Top edge is first
+ 1 = Right edge is first
+ 2 = Bottom edge is first
+ 3 = Left edge is first
312-319MarginsLeft and bottom origin of image in pixels
320-323ManualFeed0 = Do not manually feed media
+ 1 = Manually feed media
324-327MediaPositionInput slot position from 0 to N
328-331MediaWeightMedia weight in grams per meter squared
332-335MirrorPrint0 = Do not mirror prints
+ 1 = Mirror prints
336-339NegativePrint
+ +

Internet Printing Protocol

+ +

Line Printer Daemon Protocol

+ +

Parallel Device

+ +

Serial Device

+ +

Server Message Block Protocol

+ +

Trivial File Transfer Protocol

+ +

Command-Line Interfaces

+ +

Backend Interfaces

+ +

Filter Interfaces

+ +

Glossary

+ +

Terms

+ +
+ +
C +
A computer language. + +
parallel +
Sending or receiving data more than 1 bit at a time. + +
pipe +
A one-way communications channel between two programs. + +
serial +
Sending or receiving data 1 bit at a time. + +
socket +
A two-way network communications channel. + +
+ +

Acronyms

+ +
+ +
ASCII +
American Standard Code for Information Interchange + +
CUPS +
Common UNIX Printing System + +
ESC/P +
EPSON Standard Code for Printers + +
FTP +
File Transfer Protocol + +
HP-GL +
Hewlett-Packard Graphics Language + +
HP-PCL +
Hewlett-Packard Printer Control Language + +
HP-PJL +
Hewlett-Packard Printer Job Language + +
IETF +
Internet Engineering Task Force + +
IPP +
Internet Printing Protocol + +
ISO +
International Standards Organization + +
LPD +
Line Printer Daemon + +
MIME +
Multimedia Internet Mail Exchange + +
PCL +
Page Control Language + +
PPD +
PostScript Printer Description + +
SMB +
Server Message Block + +
TFTP +
Trivial File Transfer Protocol + +
+ + + diff --git a/doc/images/cups-bar.gif b/doc/images/cups-bar.gif new file mode 100644 index 0000000000000000000000000000000000000000..b2bdf4b520db437c310a503ba6b27bd696fe580c GIT binary patch literal 1242 zc-jHl1SR`NNk%w1VMhQ`0P_F) z%*@RH0002Y%*@Qp%*@QpA^8LW000dDEC2ui07n2)07C@+u*pfQy*TU5@nB#mj$~-m;k{Y;ytnIwsiZN&m4v7XswuJ8gOvP;Gl130ww6EH@o#Dg|j9ca1AmkDFj8 zS{XKXAY>9XR*yh;F?nB{3I?LFK|*ykoVOOI8aS=Ez7hkevLz`Ky1x^{C@{=11JBPe z!#)kYEq7h8bV`VXN;m-rY8O>d zV4O-5gpmkfKwlewP0FNM(xAYTdTbgbP$5T20E_-I9Aa?dDMbQn$TDCdW`L3hRp?Su zSefM$3x&#Zmgo{wrj<0&!r?>#rCE;wE@l2gpdhHUX3w^j(xkKlO`R|&P)&)oD+y}t zHUJpLEGj^I5&{Ap`l2TWbE5UJJ5R+JO2wxz2F8>U3ulsNgIVvisq2rrP#;&yS( zbrdkBC76bwM#^&|K|2~%USCfQ3$59c$cZ-)bpQkAh5&@OU=j=j(3+4300C&f#o5S! z@{__U4n#D3nji=rWRA~B#>1_=DqA;MG35)U$TJ{9?g&X>Wysze;W7wKq{oiLFH4F% zg^{lW%l|6;3%EuStFR5&j#?Ks`YsM9$o`O9Df;12N>z%f!#DYgV7OBY^vsFGJ*#emy$DgA^Ui$uZT;BpW~qJjVg@QBm^ zJ{Eu!M@dkCSB@N*GUAddBDq0R1)A_oT}L9R7ma{aV@r-EVrgNHQF{56dz-Xa)Kgdq zsO2LFgt<&v+^GQdFoY=os0k$>s%z?nfpc*hu38 z12|;4#{!gEB*<*>7-K|pWWqAb2g%4&USOq-vW5nS!cahw@<~XCYH{o#4RD`^QyB&b z2*+3^>6Ao`iCQ#4SQ*EAQtp~OoLKq1siTrXA{MkkiG z;fSqcU|Itaq11MWr@$zv2M%Qnm(h4)lsZr%r}C>$0r2J*gbJr5;+vdL^wZm|g{^8D zH?sY<(FYqk zgh>kCxWq2|DxU44`wI^Fm&<5&ru~QwqLPKla&$zaOj)E`ph=@*rp#yWzUW;2h77%` zlobTInG;k~d`?-HIvMrMTmybS0Z^L-!%#B@0MLk8`eg3@ZUk*aN8cJ5-u?#YiwFP! EJKUogO#lD@ literal 0 Hc-jL100001 diff --git a/doc/images/cups-block-diagram.gif b/doc/images/cups-block-diagram.gif new file mode 100644 index 0000000000000000000000000000000000000000..156a2e78ee1f774975bd80528700bc169892e8e8 GIT binary patch literal 3509 zc-jHA4NCGyNk%v~VH^U;0P+9;aB#*qj*f7~Z~y=R#&B@||NsC0|NsC0EC2ui02~6y z073))Si0Q)Fv>}*y*TU5yZ>M)j$~<`XsWJk>%MR-&vb3yc&_h!@BcvFU^omIkI1BQ z$!t1_gWzN!s9LYstai)odcWYXcuX#vxlyTl%_%zH@VI<#9Fpw!vwr^_R;gHk0)S9{ zf_{Tmgnxy9e2s-ixWmah?*owKx@tRJqh zYPq_-ZMVL#vb0d0MZ>kABfP;q%+1ge&(XWJ!*1BJ*L6qQ-o(2A;^XAy=I7|?>g(+7 z?(gvN^7HAyJJZxb$kt2R-JbyfCaV*Up1J|%5CTv*jv>Q?4;MC^C{bJ?gby7;v6%j_ zP`QW|Gjg=Ju_8&62J1<|m+!~EfiPj(yO*-2&6_xL>a;mC2g{buVhWWR0I1OhKacuK zs#IU0p|dVFo$5d;)uk5;UERvH>xryHyuJb}wyfE+8JMEI7j`X;0R-a8olCc_-Me`6 z>fOt?uiw9b0}IC6Gt{oZh!ZPb%($^*y@l^Q&I@;L<-M0F4<2GU^W?yuKT~$0_O0mC zf4MK>mN$nf=$E zexg<9fq5_x_*s5`DF|6z=_%+SeRdgm;Ccd5s9|sxPBr0%AchEZ#;R z`jx6bR=Q}K0@+f~PD7-sP(%)WG!jL;o+BzcztR(Iu&BbrYN*Hd{^;r^QEKX{nFA$z zN3qmaYi&EVnkwxm+v>RNt7mpwT%qKaYp!#2MtUH$;Krnhx+Ee9?*;PCyXJECmT6VK z=o!cFzhou{FfLjRY;eHh&RegYAByPk!*?aDz``sv4DrPfOFZ#y0akXAf1UOBvB!n@ z2bXH0oxI;=EVCw8%O(@y^2{Iu2%yD?X-x47IAe_R%q*AOanBh0XJ64sCtcxtD=F=? z(i$JEY}AhKEcMl5SuM5JKob4**T3mZ^#)#pZT4$Xmkk(aY=`{v%`(?4H_9ic3?a=R z!(6l8LB|bq&@X3LAd6~))*0L$Ll}3=GXEX;-E+UqxNUs?LxDHqBp06A(PwwA;n+=k zF1mc6V{Q8BsHd*_>a4f!`s=XAF8l1X*KYgmxaY3>?!5QTdRE|Om5-Zp7H|CVefVx2 zyX_Lgb;Za((g+$|QXhSirSHys^HM&4;`Mq!5y&EgkdKHVgpi-e`sb$)e)#7KjQaN6 zcdx4V@0)>0`HXydNdNq6pa0C~zV+p=OX*4-CSp~;WPIX&tRmh4CrCk4WKUA6tJG5( zc&TDss!_|Rpa@5JiVIfYc|Q7lkmh?TOk{D^F zBr6HaLQ=$%uB4@{h-F7kV$G9M{38}Y$v|tAGLOhi<~-_1sxCfYhdBbK8P9l3Wm@x^ z$aH2^wAmGDPBTrtgC-MKN55|}t4h36lkUVhwQ`zsPuy&0TV{tZ+94-e$5Gx1g=fzd z>GPlE@mD{|0?>lSKz{V(r$HB5G3C^5U;Ye@DAU$CPl;NTXYsrdJ8h)7(Rp-pE!b!W zI{ML)_9bl`E7?hFlNifUh@=gg=p;;vIhDzcra9x>Yy$K+lljzTA|u(}gsL~mDb8j; zr5sX~8o8wQv~54ljf~)9(x2_^sdWPyOh2bnv>h&~Hr47(5OtV1%jVWoQy110mB||Qy&sN+7oQl`tTJ@%v{`)H1gqm04HkGMm6)W1Ny4bMo=ecc-YILE?+?Cyx zxzTNEbHPhi-;QRr)5U6c+X`N_M$E5(8>@J~>t5%QSGzkUoNziOUFgc!r+@3ND`5$DHbE86aD6<>;SPKF!ypc^h(}D~5}WwMC{D48 zSIpuTyZFU0j{2qF}k3hGO=p&1cpG8b8(W!$q3mxv2MANqfR;F19i zQRqOMuhRwuv}HjH9(PK5g_J&!rM2YgR)^ZtiT0nEEd2*xUd_~}hSd-AuxjxgTGN|e zbomf{X;=@M)}zMr@Nk`LE-o!z%Zc55w8cHoc^qRvyA9_dwU7kv7Hms;+b>i$5fvT{ zgYOyPIApkxt=;UX{2NgO7b3+gE~|O}E90$_crzTXW{8h7ogxp0G%>YiP7TH6@B+CL zH*O1EU*mzAxHg|ABrt7@&89m&jQH-P^NxtcEFS&p zF8B9Jp3e2IpDOCVR5G-@jC7=@dFj>ky4u$+53t|*%Qpwd)|)xYU0t%4kW{5D*TKtp z+|lk`cRSH#!Y56&i|L~xq%7UYON}t{@shmA8+WtW3$9ePlm_=9mMhgx`pDrkpW zA%vIZgL;^T;gpA#5OjoCh*VfxbYh5#xQNj~VH$>7ilq;as9_5>i56yB&R~fZR*9OJ z{#ubZQ=RBwoah?-#Zs7&GXfSL4K`tjSY01wSIKpW=(SU?6*y%DRd3~1mXlz$_+CNv zF*P+bwwNDK)ml46U6M#su;^0E*f@SQI-`ghS;1Ce6*JdWjE|Fw$fZ~G1vK^bRNuH< z9D<2LP**CIUDWtihZT*d!64hnQ{pvX6|#*{1z;;vUj{Z@^HqwuL5}xOSMzvP$(1sz z$R6xiAi2djcvCsLxH!+Kki!^`Y&Bp)!;NhdTm9II$yikZX;u)~Hw9^sjwm`INs|7k z10@-X8*-2;Nm!pqS1n0eEE$t^b&@_olcP10IN4V=i32IQlLKNOf0!1w^?^hFIfp2B zloS<+N_mG#*_5}#hkXc@Q7MR2A(d1)Bv$DmTe${|_?2MkP#WnHVOf@D>4zxrlR$|f zJ$VCaxt9Ail5lB~V+oUUS(CGPmwQ#0r=^$5D3`s}Q>K_$y{KGoc~;}dmzl^RU$s*F z0Xc|yif5yffOS;V2v-m}ImU=o^+=BqshPi+kk$w{Zqqlc1tWrm8}2xoHxrJ2BV4#h zk)fHH)5w~(8C#pFnt+KPe)C`Qm{t>cRIo)DtC5f22#((9oB0)R3?`axWsBDsR^P>2 z#tEG7cvotbRU(;}?bwUe2%N_iS8qc%%2k~BD3Qr2ke&IE_yJ+S;f{~`h>q|0o1Lki z`go1!nVy!Jm?3qV@kN@giJQk+m=$7-%$T41xQp3YUhLVP%*i3S1&j{4pxtPV)VZLv zNujqGGMK4gyV;$7Ns8_nq8>$=B*#;;2iXXb7MU$drBU+<{)_Y?7Z literal 0 Hc-jL100001 diff --git a/doc/images/cups-large.gif b/doc/images/cups-large.gif new file mode 100644 index 0000000000000000000000000000000000000000..fc66ef07c01137f4eccbb23328f27c1de5abce14 GIT binary patch literal 7457 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 B-D3a% literal 0 Hc-jL100001 diff --git a/doc/images/cups-small.gif b/doc/images/cups-small.gif new file mode 100644 index 0000000000000000000000000000000000000000..6adb4a29ffbd6b806d8eed34fdad33f6138e8890 GIT binary patch literal 1266 zc-jH-1P%K~Nk%w1VQ2t*0P+9;%*@Q0nVDv0W-~K000030|NsC0|NsC0A^8LW000F5 zEC2ui0B8Vv073))Si0Q)Fv>}*y;P9RyZ>M)f&+k^&M>Z|5CEnF2ZGAp#DF#d?g_gf zMB^g>Geuovvm_`sy(66bkjl^nG{>zj(HFtg+CH;@**F8gro_jj zgj?4byer~)Nf456i8gNvL_|X0AKjZb>HiP(?JJY134<#O)`DciDjrm5wU?-9CnKXPnbDTvVa3|4f5K7S6B=AM! zSYIVh=MMvpL6%}^eK=5Ac<_z(R8;T0D3mP`7Qt9sGhSe$EOS+sTM)thaLtgUiD6_2 zhR`Sjh1$62wZ88{PYI*?4fc95P!hd?1I4wU9X6lPAS{=i&_ zo?VF1doqTGo^>DAmj)l0_Jo62Oos5|L@{Wf#B=Lafe9Y8?x1TS<83QJnBi<_-$QF~ zvqbn}J9Ra2PGl=fQ*CO_rXl%ZbOXykTl6(kKS27Gix4ug5I1RZMXO zBbFK{-Eb^oSCF{BD!VbP${lImYwjA1)NIC4D-y>1WqfmY9^86Ew$5hPT}r(E%AOU% zhC(C`+PyIFy&mz^)!zKG&baOq|v6_F*_C|4I;#4HBJ&n(8w@p2}RL(2}!DTz7 zIG=4kc*1vOOfO{;dR^(rrfcEDoT>YJgRMGB_C>cOroJw|OtX+}?8J8AwwtsUuK4Sw z5B0$9=>jZSq?PU7mVgl?>3n3RM_&Z&00rl%Ljuo*JnjL4`dgCQKS1hOMq(ehtE`8? zrH@~CI=#Aew*Nrz)z~kCpmbjemmzCuiKEn_sG606e}~$YGVqr`cF?JT*DDeP!%`*$ cc1nF?aZ~|iF+YF}&@50&%OUg^gaiNpJ5-EOApigX literal 0 Hc-jL100001 diff --git a/doc/images/draft.gif b/doc/images/draft.gif new file mode 100644 index 0000000000000000000000000000000000000000..77d9716abdee066f1d5907c2748a595ef174d6a5 GIT binary patch literal 926 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 literal 0 Hc-jL100001 diff --git a/doc/images/navbar.gif b/doc/images/navbar.gif new file mode 100644 index 0000000000000000000000000000000000000000..3389d2338cf4f739ce4f67fe5a443c5bd11e792b GIT binary patch literal 2251 zc-jHW2sHOcNk%v~VH^S|0P_F<%*_AH%*-=0GXMZH|NsC0|IEzHnVFfHGc#spW@ct) zGntvp000000000000000EC2ui02~4+07C@+kjY7_y*TU5yZ>M)j$~<`XsWJk>%MR- z&vb3yc&_h!?`H`DVL=HFB|?HR!AMGshotZziAoU+K|o5NR)t0)W5EpwJkAP~5uRA3 ziir_E(Q>_Csaeh?#7Aj)NqZ6oQ+j6-c2am8fr^2PNsSC|Q*L0G1XxXnNeOdZ6qW>p zPKD!~zKdi3#wQV8F+TUp8_={%Au6 z3`wpr4d-R)_YYo&Y{`fScqDP1CMN#RCM4q&$dEa3R0LjthLYR2kPf%CjLGn1%roUU zF|fFSSOq6*KGKv>?HhxlQK&@W33DL>lT2Jjokq2))vH*uYTe4UtJkk!!-^eCw(Qqm zQl?@P@*yY>X085RGP_o02P+C&^ckd!t_HU~=Q_2KtW4hxZ-@Z)8w2g63AQMtLF!Em z<-sjILT+{7@L$0LLCZ-N=gk4N;7auy)o`I{)FRRpcqsB=(~SfQqz2uOn@0Mi?=o0d4hi_cDd%TKEt260MO~xA98=A4%zcaZ9x613)IY@rG(CF`f3R zak{qlK^mqC`{<#htxh{wP*&XYsCo`zo5sAQ5HU%-+-WsWKcHBUO&Sup zBnC8lB|(HqeH}>N2Dkwb*f+m0wbyeVi!z=RsXW@#0Snxc21c0#ELnUrE{ls@?h<_S zHd9*gZB2g!Vo$p(1Jz`87HiT9#oEP}O^4AaWb+7;R87HUfn=IYC!P3gVkrl6mvpsQ zQFp<_INLbW90dd?+yaGp*KiUAEU=^pg&hz;VN4#uqCb0^2IX#kZ#MNJVI1Jn28|KgoUVTTSx{rBL9FaG%C zmv8?0=%=s#`s}yw{`>I9FaP}X*Khy*_~)xtlvkM18E=%xF9N(kbXf4e z0*)_%FJMNJI z>TicLQIFa17#f* zSw;#`GLVNX1FS5VQ2trOS!j8TFr1y(rXkxjMoma{iHb38pn0I_ zLsjAwb;SpyEX{+zhIAovCZZ_*T0|ncCWKZBWGSL3N<12phBw3tSncA9J0~HtYRM80 zzig^7g|ShmakT>x-4r9uX{u&IQ#esM+cw(zvDiqhjR>`gQ#@7xX->0*ETPE)g<`G2 zzyvxd+=g4iYLp*wp=m?OhLm7xEDq?XO3?{QAaaL?;^cxYR-jTJ3OlyZa)q-2^lE&l za~Yp~f)}t&PGuEPyvnYvVddf46lggW@gV6Oq$tv9dI-rw{&oW}iY#8u{t=x>Yzwz_ z`D1--Dp=c=wXA`F2~vp#F^Iv_D3?j=!*;h?u`1VvleNiU<7h>Rfwnam%a0U4B8n}j zWV}w%<`h7I9Dew(vF>$YcCKk7g9^qXP1!DFN2cB;$>YGW@4h5b61B5BU0C#m3f_Yl30rpsm71xD`ZVPTihqeeTm5k+NrjjArq3LmDd zUNhh_p=M#B!%E&mg*nw2r`X3fsc}fRLfru4M<(+P;Wyffqdvs7H7jdrcrtd4NqNj7 zbX_Puk4#oJ_ra1VP9`|b8;#6CxXn8okuFxI5XU4U&7I1Rc5Rf1W|GmlwP^u#e7LM+ zF0}Hx>y4u=mkgI#MB<$$($8^5^wZW9+Jf9GE(Iw<0y|k!00?lRKhih>QJd0^apVV_ zC+Xh{)j9+IfRn3TkZL^v5d(N+fvjf@vWS^L0HSn(tnu*|5~Bb)A{ci6rcLc?Tl?DB Z&bGF<&FyY```h3Sx46emZmdKA06R~F3cUaT literal 0 Hc-jL100001 diff --git a/doc/images/navbar.xcf.gz b/doc/images/navbar.xcf.gz new file mode 100644 index 0000000000000000000000000000000000000000..28438a6bb82303522c41ea5b3ce198a9de9a23bb GIT binary patch literal 4253 zc-jG-5Mu8iiwFq#oEJ9$17~S%a9?y~ZE!9*Gc`CdE_h>R0PP%0%Oyv(`gPy;dw-Le zNhg^&<6txai6%C2RM3TDW@+Kpm>0qLXhm>0@qvoa3lRi$<3@xA1vlbGh!7gw`2$?_ z${(N*=XQ5_UR7OvAK%OvAE5Vxx?O#$PF3}(>htdJ)z`lGm22O4@s(?@y!QIbN~th~ zpZ6&KJBAVj@N)v?Q3HR0`w8g>;4}IORR8yaQlI`~f9r|8Dp#6_`80H~0Iz-{<{4|F7+{zNtD5t7&TuQU|vk zZh?$B$fM94;9YAtL(|s?BPsX?1m@EmU1jl}_nE-&MNIuo9>))hnH; zyler2BNS$3DxE^T(`8c@8O+uXqGb>~Qn_hhE;?5LZ%kRk(dr7-s?tPerBzxRB=2_Y zdVoDPO-5*qRu$}nk5xe>M=WTqdXxa~avTb$;r%am~A3lZhi6SUHyhIK^` zgjCY0xM%;s#QFg+T7}e4LFst_l)^St{n@z~56?r^(caZ%W$q6xgX0FrrSOl-?*33I za2`zygsrUAbMWfj3GpTTCA``P^yW?IH4TB)T?ZC~920qitpfokz>S$t5Gy4}1pE{s zhw_F4@IaXCj2LmyHyk=ni$l(VqugX>>Q!(NS9$z^*!&1anKMo#9Au_0ad*54iTU4v z>x9u{vZ>?#r_i>v;4$1>hLM(p7|?t;^3){i1nw_EeF8+qhq%PkGV_{4!+~8p0xZYG zEtt~dB0PcXG2KrI5${iEmNBh=1obnh<8n>__c9dbhWm}!Z^V8hh8xjkAgMtfd`Puv z1wxPoimyOY3l!ZV`PEKpve6az(J1uc#Zm%y+a4P&vOt*JFf<*@=o zyGvnRv!2UiLsOfYdWU9Jl?pL(7X7JmU8g-x2^|XPKy7&v6R}`98PdXk z3JvS;P@NzRjd5btXx6iGn8Femb+*En@v8z6SP@}F()3ywr%_o+9p|iB(cU6OH4I?) zsV76O9KLJN7C(1~i8hkfJlJZYPU@Z)rEUp*QF%m_qV`T{KESTiHpTf#TzkY#P;M{r zkc?O-bJVJtTC!F~p|c04u}We0_~q$}UJ=C!L)a~il%hAF1;zKoy>K(8Sqg9Ax1qeL zpc}rd&w%pI*N|T3{yK#hIDwZthLV_5GGfNWI*<`eiM7m$y#&B+5_RfW(q&>c#5>{V z3d0eJcw?xJnY9JPTV~9%0`-`%D>T$XYsH*VWu)dbd8p24(vaC@z;+JJ7!X6c#1o1Q zc#c2scAWfaLwdLUIdFDg;#iqTfsw4u8GADa;9d)X&8aZco)au2lWr=;(a74U698Zt zgCIg?9)rz`B?8X)t^I!N_hY{w7wt#%7FzRQ!sjR>+B9ctJ|<{eYN=8CIkLoJ22_;I1Sg(vl1>Nrr>r-*-j3 zo3Pmg2P3asmAR8iVcGWbiPeg}V_Q1hz~BQ$)=dCUNYaDF2taDr=L``tl)_cU5(~8# z)=eg+bxp@gEXM??&?s1I%%U96YA0}z7_45vGGVkPD=IuExZDOd0LM;Atg^Fbo&DR*6)5DIyZnZt;J|=5KsOfk<4Ag&g#!3)wRRh%PJI<|RXr-8N zfOp39OwLdM-`u!Q5+R7mE!`M;~Tm2s^SI zn@ucU{DL_sdS1s0mp7BgO$hUlY%$w;W{zkp?1&SvtR^5VCSpm&=A5iAw4i>lKM4DS zus;akxCg z7MokV0KQWoESEhJY5*7zA%!999R(TO*2<|~hYkauhX&N1OTbgQmiOw}lG+8dSzO#R zwCYxulA8p#M*>Hc>m-f|_IHuW<0)I%NieHSXj1ev>4{WB|Fk9tjHhy0^iZupx2cJ` zs2-#4Svr45$@evD!JfiJ%bv52Mxnv3bn~*NL{uX!Yk_YVo;y!vhk8VpQcmn$+qe5=?ICP zDd~2{LYhh!z-6-3{4S)lLRzw$8 z>SubT)2-vV0D|?-7b0pqqs5ILIe&u&L9+EJH%1|4M!ggK7`-^}WPrvLTuoUaV=_6C z_$q}{8@7*yK9yXNGKAZQN`TV|wD~(aUQ$X6X(gs4DG$5G%kU7TMvfpU1-0E;92GSN z_M(xGsFFa*=3q855|H93I;4&MB|Kn?r?}qnbbU_ENbxIEi(8GWp;Yr-q~boHUM3sc03+WnON60~*b&@`6PZC` zl28iR6Bdjt>%DB#bmGi?*oe1QK(RtE@Z7T7m@61WcKllyaAFr1+s+5VeG@mj>*K~6 z^htbX{!e$A`^^uFj2I18ca`{kXEW(+=`cVpF8A25S9)RClkSoWr(&?py#|&sk+Rlo z4@Yl%LM5>lW#1T)fyP4PaY~MRV}B<0XJUUQ_GjY$&V=SOAv(#T&$_sO=$WFVm+-=* z*qk$C7#KN(47&d1r67Q3ob&Xm#H{6Qgy)7JB16HZI9Se{d8rCcy=duD8) zFt;+ds%TG!Z9XGUb=;95tHsq3ZVa~RNus%(vbK>gnn)yTeV`5RQf%5?V}R>^L z1opNj<~DU!!jqL4uj@0fYwJ$ibZLbg@!OiN+v<$fO;Uy#A}87Ras}ey+MdEI5#FZO z_9+o+U!;K-jEu&I#MgE1!h_#c=mH$REhM4w>hOl$+71v&$esDo ze%}g@g~e2uP5+j;e?T8zw1o_IVR>? zps|{587ATk3AFGN0bW@L%&pk6XzXJLz=`9*+-qcIS|r{B+jwfcV8mEvc3BHEzjfsC z^kg9Eq=I3DheU|a$d6F$_iev#`+fTl?;EE>X6lqJ_s47+a*d%Kbh#mKevIQ02s{ur zZSz2{uoojNNvpvy*s99=wyKZ81m=)pChpsxKnLlnD2r5rVNMQmR4wOt86pPSYH1n! zr3&1U%w{3`u0+XXLJ@_rBZ{!hlu$>l$jN=u5j-Gij4u7Krwmwayc2C za=wYJhuCv|j*xStD<(*49dPTk#@w)OfX&|wRqzB(!>J?_iZ)cX869jHXOIujaZ4pp z8LP2q_=J@?uiXG?LD9MxHJFIrw2*9xkX}st3DZ?HQ9?cG6O?}>mhp4I1)c>K@j>7l zPlF{k!$?PY7i5N92c0l2j6gMl$yxehut3+N&cwrP>?OqC6U zFiT4~baE=dQ?bJXA9yA#?V+{%V=+>Bv?*sDgli2vbz-v+g!9_8&#B)+k9zD{M%FHl z)Md*9r{o$Cb~~};3AlM-4c(C9Ae`!OL@Av9{hVkO$^9|SG&MKr80eLTT3V}A39%3o7wB-MdQ$jhGDK! zf?53&r0H{_LH#*Vlp73vVNCn|kaMhfVYP`l}bL$DXFFsE595*wjgjy^c6)evYhnUZq57QB__EnXr$E%e}UA{1iv__}&SBtnLIKg-5(3 zujG+j4^<*p*6hc4juUqil6lmLXBz27cSp`rI&v0+=P4fm?8|Olw!80R$%4G-elVZ_ z`Y97)pzPy~U47&%Ci_uoOvw0+X9z3+UVHWHJ$?4{d1v&AKZpOI=>UGtiL(}mKFi*`%2xu0p)Xp4G literal 0 Hc-jL100001 diff --git a/doc/images/printer-idle.gif b/doc/images/printer-idle.gif new file mode 100644 index 0000000000000000000000000000000000000000..68d990c628dedbf4326390527ef72f2e90aa9841 GIT binary patch literal 706 zc-jHN0zLglNk%w1VOjuC0P+9;0RI40RaM~N;Hs*s0001gk-vYDzkiXxA^8LW000F5 zEC2ui09pW0073))Si0Q)Fv>}*y^CnUxh7pGd<14vpEz!6>%QY4&ve>uB}(tM*u$=0 zh~*0aj!0x6HzDkv(CC0T1OcxjAXDO$YNXGu%!(~jZg(+7?vyLqy7<$y%2h8}_!c5O1#O@a zR!WRP_!jAB`?Z9$cdG_4C31H(A zdizN3T)OVI;oZx(uiw9b{pt&>?ju3M1^W$@co=a3AuVIfv^w~$y{pB-h-^IRve9Bg zZG=2w@aN}0nh$QUqw#^j(+Ej~1F`Ce!zK{J!PXLzHp!B$F;!J<`YG|1zggYpvXeMA z%FvQ4S$-^KZ{23iki0V_sP*gF|CtQpooYbnMxmBBKcy4M-C5$iA{&z@e5CS~(%)GY zwuySBIn~$SY5(E223JIZ}*wI++r^T@^^jv{DWCws3gD8=aCR3G_lbf6jnVq1aqNAh{ODr@msT`{UV~RXa zb|9cdbtSI`sH!zhz8kV)B833O#aR`3i#xZty1;+Jjb~JacFD}j%SVjU-XDP2+p*dK zeBV&f;AMi7hp^*EQtE!0h@tlH+VmOukfogbDLI z6u`|b))n)fk!G4+fU%3!vgav2879Rp@fd}_GxTc(nAWJ z9e*AbdbDXnrc(x{OOD=pkAS@z@ztpvHjzaIt{&cubs z;yQA&y$zTrab7GZzJxB>Y%X@P*KC&P^ZNDKs^mw4WnkgPw59do|` ztnAKQ#LZWp6HV1LR8dE*F%mz^4M-q^n;i&Mf~G9fl!MTf#EyhSwRaa<3^J7lTTdNh z%^4piRp5wfVPaQVUP*`CTtSe9RE%Jlg9c&fOqWb|IHpA-J2omv4vx(1HDrx+q^Kia zN-pVFlQ8DEjgV3<=3|v_eHCSoe{6XpUdmwk4OX+H0HlgZ#&RZ!b+tnql6tx62V<3$ zl0{-@Y51l+0YS26pFx3HS_PT$Ne-T&dFD=JS87$6WqL+-)>fQRijZYxrqk$Zi86!B jr?YWNDsBxl`U$Fts>&*41HCGWVY1e0>#evxlmGxb6oz`@ literal 0 Hc-jL100001 diff --git a/doc/images/printer-stopped.gif b/doc/images/printer-stopped.gif new file mode 100644 index 0000000000000000000000000000000000000000..76f45649b132bde80d5a90530f0cf990aa4f5278 GIT binary patch literal 794 zc-jFP1LgcjNk%w1VOjuC0P+9;;Nak@s;d70099300001gk-vYDzkiXxA^8LW000F5 zEC2ui09pW0073))Si0Q)Fv>}*y^LtUxh7o*d<14vpEz!6>%LuB}(tM*u$=0 zh~*myj!5JnHzDkv&}e`-1OcxjAXDO$YNXGu%!(}weV8v8{Hb9z$++MQBS{AMyne4< zPg!tsf`dqaWG`DLdy9O1et%1cW{D@23XFLUVl$E}mY<-ZqN56DR9c&K9d@8jryiYU zvOce{9C&d{6`PNLh*qjAvjj$XH@joJy)|yLZ(7L9e^IH1F zLyI0wx-^8frUUk5m6{($lP6iX&TwkxP?)kaCyX2}-JSFs9tCLZ!0u1?hk zx4T9zA5O7W3S386j!j09Ix3mZRpw$`N+@{m&Z!V1q&>o0?%loOjx9b{`_quYOaEm? zeBmB*TIHu7fAQF47gS^=HD6Vck>^l?Vfa!Pbqz-Mo=eSm=fP9kC6i!R8dex!Qr>`w z9*6ENg&|ewfq>OPD^Oa}{c(S6uiji|^0mQ_G<_92nSAtu+6 z!Xz0%BoKbnq+e+5r`BDI%qXK(Sk8qNLTowarFngYDGoeAaEaH2Q@|I9nu$$_A_SFr zxno678s`-Tl`Rn=T!+QMrhK8~IpiZ692QAY4l0u8RvAT_sG=?*I$EIbHE3x=j+G)2 YPqX2ntm^8kuqFTiJFzuv761SM literal 0 Hc-jL100001 diff --git a/doc/index.html b/doc/index.html new file mode 100644 index 0000000000..b0b45f5ef2 --- /dev/null +++ b/doc/index.html @@ -0,0 +1,34 @@ + + + Common UNIX Printing System + + + Current Printer Status + Current Printer Classes Status + Current Jobs Status + Read CUPS Documentation On-Line + Download the Current CUPS Software + + + + +

+ +Easy Software Products Home Page + + +

Current Printer Status

+

Current Printer Classes Status

+

Current Jobs Status

+

Read CUPS Documentation On-Line

+

Download the Current CUPS Software

+ +
+ +

The Common UNIX Printing System, CUPS, and the CUPS logo are the +trademark property of Easy Software +Products. CUPS is copyright 1997-1999 by Easy Software Products, +All Rights Reserved. + + + diff --git a/doc/overview.html b/doc/overview.html new file mode 100644 index 0000000000..a3979ab1cf --- /dev/null +++ b/doc/overview.html @@ -0,0 +1,287 @@ + + + + An Overview of the Common UNIX Printing System + + + + + + + + +

An Overview of the
+ Common UNIX Printing System

+ +

May 11, 1999
+ Michael Sweet, Easy Software Products
+ Copyright 1998-1999, All Rights Reserved.

+
+ +

This whitepaper describes the Common UNIX Printing +SystemTM ("CUPSTM"), a portable and extensible +printing system for UNIX®. CUPS is being developed by +Easy Software Products, a software firm located in Hollywood, Maryland +that has been selling commercial software for Silicon +Graphics®, Sun®, and HP workstations +since 1993 through more than 40 distributors serving over 80 countries +worldwide. + +

Additional information on CUPS is available on the World Wide Web at +"http://www.cups.org". + +

Background

+ +Printing within UNIX has historically been done using one of two +printing systems - the Berkeley Line Printer Daemon ("LPD") [RFC1179] +and the AT&T Line Printer system. Replacements for these printing +systems have emerged [LPRng, Palladin, PLP], however none of the +replacements change the fundamental capabilities of these systems. + +

Over the last few years several attempts at developing a standard +printing interface have been made, including the draft POSIX Printing +standard [IEEE-1387.4, last updated in 1994] and Internet Printing +Protocol [IETF-IPP]. The POSIX printing standard defines a common set +of command-line tools as well as a C interface for printer +administration and print jobs. The Internet Printing Protocol defines +extensions to the HyperText Transport Protocol 1.1 [RFC2068] to provide +support for remote printing services. + +

Weaknesses in Existing Printing Systems

+ +Easy Software Products has identified several major weaknesses in +the printing systems currently in use: + +
    + +
  1. Users must print text or Adobe® + PostScriptTM files; other formats may be + supported, but not universally. + +
  2. Lack of a standard command-line interface; each operating + system and driver package provides different command-line + options, e.g. setting the media size with one driver may + involve passing a single option ("letter") while another + requires two ("mediasize letter"). + +
  3. Lack of a standard application interface; most UNIX + applications either do not provide an interface for sending + printer options, or restrict the options to those in printer + description files supplied with the application. + +
  4. Remote printing problems; no vendor seems to use the same + remote printing protocol (many use an "enhanced" version of the + LPD protocol with vendor-specific extensions). + +
  5. Client printer administration hassles; most vendors + require that you install remote printers on each client by + hand, and many do not even provide the ability to browse + printers on the "server" system. + +
  6. Drivers typically are hardcoded to handle printing to + parallel or serial printers; support for other types of + interfaces or networking protocols requires that a driver be + rewritten to support them. + +
  7. Security, accounting, and quotas; most printing systems do + not support access control lists ("ACLs"), and printer + accounting and quotas are not well supported, if at all. + +
+ +

Goals of CUPS

+ +The basic goals of CUPS are: + +
    + +
  1. Provide standard support for text (US ASCII, UTF-8, and + ISO-8859-x), Adobe PostScript, PDF, HP-GL/2, TIFF, JPEG, PNG, + PBM, PGM, PPM, GIF, SGI RGB, Sun Raster, and Kodak + PhotoCDTM files. + +
  2. Provide a standard command-line interface with a standard + minimum set of options (media size and so forth). + +
  3. Provide a standard application interface. + +
  4. Provide a common remote printing interface (IPP). + +
  5. Provide a printer browsing interface and allow users to + print to remote printers using a "printer@server" notation + rather than adding the printer locally. + +
  6. Provide a scheduler extension interface to support + different interfaces separate from the printer driver (e.g. + serial, parallel, lpd, tftp, ipp, etc.) + +
  7. Provide a standard interface for ACLs, quotas, accounting, + and logging. + +
+ +

Design Overview

+ +Like most printing systems, CUPS is designed around a central print +scheduling process that dispatches print jobs, processes administrative +commands, provides printer status information to local and remote +programs, and informs users as needed. Figure 1 shows the basic +organization of CUPS. + +

+
Figure 1 - CUPS Block Diagram + +

Scheduler

+ +The scheduler is a HTTP/1.1 server application that handles HTTP +requests. Besides handling printer requests via IPP POST requests, the +scheduler also acts as a full-featured web server for documentation and +status monitoring. + +

The scheduler also monitors the LAN for printer browsing information +and dispatches print jobs as needed using the appropriate filters and +backends. + +

Configuration Files

+ +The configuration files consist of: + +
    + +
  • A HTTP server configuration file. + +
  • Printer and class definition files. + +
  • MIME type and conversion rule files. + +
  • PostScript Printer Description (PPD) files. + +
+ +The HTTP server configuration file is purposely similar to the +Apache server configuration file and defines all of the access control +properties for the server. + +

The printer and class definition files list the available printer +queues and classes. + +

The MIME type files list the supported MIME types (text/plain, +application/postscript, etc.) and "magic" rules for automatically +detecting the format of a file. These are used by the HTTP server to +determine the Content-Type field for GET and HEAD +requests, and by the IPP request handler to determine the file type +when a Print-Job request is received with a +document-format of application/octet-stream. + +

The MIME conversion rule files list the available filters. These +files are augmented by AddFilter entries in the printer +definition files. The filters are used when a job is dispatched so that +an application can send a convenient file format to the printing system +which then converts the document into a printable format as needed. + +

The PPD files describe the capabilities of PostScript printers. There is +one PPD file for each printer. + +

CUPS Interface Library

+ +The CUPS interface library contains CUPS-specific convenience functions +for queuing print jobs, etc. It also contains functions to access +resources via HTTP and IPP, perform MIME typing and conversion, and +manipulate PPD files. + +

Filters

+ +A filter program reads from the standard input or from a file if a +filename is supplied. All filters must support a common set of options +including printer name, job ID, username, job title, number of copies, +and job options. All output is sent to the standard output. + +

Backends

+ +A backend program is a special filter that writes incoming data to a +device or network connection. Backends for serial, parallel, LPD, TFTP, +FTP, IPP, SMB, and AppSocket (JetDirect) connections are provided in +CUPS 1.0. + +

Berkeley and System V Commands

+ +CUPS provides the System V and Berkeley command-line interfaces +for submitting jobs and checking the printer status. The "lpstat" and +"lpc status" commands also show network printers ("printer@hostname") +when printer browsing is enabled. + +

The System V administation commands are supplied for managing +printers local to the system. The Berkeley printer administration tool +("lpc") is only supported in a "read-only" mode to check the current +status of the printer queues and scheduler. + +

Summary

+ +The Common UNIX Printing System provides a modern printing interface +for UNIX applications that is both flexible and user-friendly. The +software provides System V and Berkeley compatible command-line +interfaces to ensure compatibility with existing applications. + +

Licensing

+ +CUPS is available under the terms of the Aladdin Free Public +License, which means that it is basically free except for commercial +distribution. Vendors wishing to license CUPS for their printing +solution should contact Easy Software Products at: + +
    +

    Attn: CUPS Licensing
    +Easy Software Products
    +44141 Airport View Drive Suite 204
    +Hollywood, Maryland 20636-3111 USA +

    +1.301.373.9600
    +cups-info@cups.org +

+ +

References

+ +
+ +
IEEE-1387.4
+ +
System Administration - Part 4: Printing Interfaces (draft)
+ +
IETF-IPP
+ +
Internet Printing Protocol/1.0
+ +
LPRng
+ +
An enhanced, extended, and portable implementation of the Berkeley LPR + print spooler functionality
+ +
Palladin
+ +
A printing system developed at the Massachussetts Institute of Technology
+ +
PLP
+ +
The Portable Line Printer spooler system
+ +
RFC1179
+ +
Line Printer Daemon Protocol
+ +
RFC2046
+ +
Multipurpose Internet Mail Extensions (MIME) Part Two: Media Types
+ +
RFC2068
+ +
Hypertext Transfer Protocol -- HTTP/1.1
+ +
+ +

Trademarks

+ +The Common UNIX Printing System, CUPS, and the CUPS logo are +trademarks of Easy Software Products. All other trademarks are the +property of their respective owners. + + + diff --git a/doc/overview.pdf b/doc/overview.pdf new file mode 100644 index 0000000000000000000000000000000000000000..a7f17a14f415ea2f623a9c1c3de89efb14aa15c0 GIT binary patch literal 21771 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 + +DRAFT - CUPS Software Administrators Manual + + + + + +


+

DRAFT - CUPS Software Administrators Manual


+CUPS-SAM-1.0.0
+Easy Software Products
+Copyright 1997-1999, All Rights Reserved
+
+
+

Table of Contents

+
+
1 Scope + +2 Printing System Overview +
+
3 Printer Queue Management + +4 Printing System Management + +
+

1 Scope

+

1.1 Identification

+ This softwae administrators manual provides printer administration +information for the Common UNIX Printing System ("CUPS") Version 1.0.0. +

1.2 Document Overview

+

This software administrators manual is organized into the following +sections:

+
    +
  • 1 - Scope
  • +
  • 2 - References
  • +
  • 3 - Printing System Overview
  • +
  • 4 - Printer Queue Management
  • +
  • 5 - Printing System Management
  • +
  • A - Glossary
  • +
+

2 Printing System Overview

+

3 Printer Queue Management

+

3.1 Adding Printers

+

3.2 Removing Printers

+

3.3 Reconfiguring Printers

+

3.4 Printer Options

+

3.5 Printer Security

+

3.6 Printer Accounting

+

4 Printing System Management

+

4.1 Log Files

+

4.2 Network Configuration

+

4.3 Adding File Types

+ + diff --git a/doc/sam.pdf b/doc/sam.pdf new file mode 100644 index 0000000000000000000000000000000000000000..eeed961260c893f363057823feb57c9117340767 GIT binary patch literal 23287 zc-qCB2|SeF_xQCDA!IEwDzY{EN|Zfh8_QURY-7nfV~Zp$k~L&WDQzOlkdn1h%D$I~ zlAW|7M5+HUQh7enw|=kJzh1BL%$fV#_c`aDd+xct+LjgQ31 zDAH5{V&LfMO#1+@plSfx0a7y5)d%Uj*?Ia{QAi*KTNg)HM-NYmm8ToU1Egi;>Sg6D z0a5Vsba11Ht5|vX{%A|r+tWirUY_J?OS6RqzF?DquR95%;%eh&>*#6^QMB?PExaK( zx+=JOIDUV>a5Cc8lU3bZJt6vD)}FI(W+kw>Zsx=WjxHpR9e6hvE7t`GXcmrN=neV5 z_NM6OZ2P;;P=DUp9+I;+$UVvi|DvxYmBajbhx)!Q)^5%VXJQx5{N8@AqpK4H zPqOhe!_a~dgvKDia1a(sdqHE-V7NI%(T!qDqL@KxXF|;($|Mg@Gwf_6;~~Z-rXW`@ zT0ml9w0_MOAh;zU^q%J+FenC${d)=wx&#IW#m*XohSFYPa3mNt$Atb72ZO-;!htQt zq4!PaU=g$S{51!@ygf)XjWEwd;lS8G;-FE#`VFzXJ#-Gu64*a*kV|psea~^=Ff z-*X%|6amKk0|&R<;Gl3w+AH0Iw1n{AQwN7wk^+Y=H#l?(42Jn9%#xX4uJ3sc3Oeh+ zzve8N3Fi8ybKo%eKiPv=HshdZ-us?$P&mYIX6RzhqRa+IE}L=YIcWM={VivyOfcU! zorC)~d(g}K4UGY#K|gFm{}Bg`!TrL)EbliuXD*xmJqNpNrlxb?v`9nz0|&Rf-%!Z8 zB>LSpNg>1}G$KwxU|F4gN63PgIV5hbPg@E;r@YxUEXgnEMWwFF$(<$&U`*Fn~iV$+%+pa{hAV< ze#r+)tmmBc(>j8NBejQKWPUGpjT|9j|il=WE@$}ssp1#?_)AvGn z`c?%`-$~%uo?Zju=_MMTUP0mM1rDBGf8gom0iM2kTz=%6y^b!9o*ri6FbQ$wK7@ohMBB=R zH1{4gr0 zl0akU57826IteL(p>vS5t}w9qL%0M6K7WXiz#tYG@*|-s|L3*L*@GX=(aoii4~Q1Y*3nAQ?Z8~FMd45&431V;D7ksLdeW9M`kcnlGYV!tD?;Z}CY1i39<3}` zdfuQ1BMXk6Vdx%Z!O?RO?t50IC!C*DLjhHzy--LrCFaz|(=>ARq`mb3Vdnaxtsfq4 zUKAUW2mSV&jXufK45F*73NauZ@Pw$l(0Wj$|52ju zo_da@RHV3$hb1F#zVp#OwP{aa+dBcB4tvmA2)V-Ii3;X`CmqjTS=4}+aX-rf0Bmb~wI72gg2 z5yFV;crixU`>_Ay*O_y1pI%g8T6?CahwJL7PgC8~)KO8DmgS>6BJbVow|H?V7``JEZejk`sD2bm^&RQ>%9MDMCw*+8^YktafU z!@_R5Jo{op9)o&=eeYq{$r<8g@A>m@Pbj&oyOpPl7qhiDrqyNdss1nU&FlC!4+nZ9 z7^$Dvog#iwd4p{=9~!BiYPX^~f#bA1R@+ZkyC$0q6!Bf~of7d5mn!~{$^ETag6h;@ znwWXMJLbVn6R=P>{OP)4bGr~tivv%?zU_CXN`EX8-^E(%HRxp^HWEc7SlB<>x4xWY z!nEVakq+Z?qx(6)0)7|5EW569#Mjhx7W&<{K5~C;4%QOND9y-^-67yV5=gf6?abXy zt)GccJZ9%H9-g-%>~oi?@0|qo^~C&622wkYFwBOx@UD#uDs$&l=6p^#5bs^ee>Lio z5R|L#B0EfmFu-Q|)SMhtMiB|-4=)w*DB%w;^N4Opr+yrMz^D-4kjQ1$M|s4eryX9(B)e~ae`s6^kM>$!Y@5aVnKmIG_TUGhP8$_?D@_%eKw;v39 zlo9Mw*sB)p9J2zd`FdIcRSDy}z6)$n0-&|F0| z#F!ht$qO3K*(~!0tT=t6Z-6oT8S#zov3PL(wsVxif=i5Yau^#e0c$b7o5jYjo+N?S zogrrKzHpAMY6zZO5$Ad3EpM@NRS(PO-1}EB>$3L9we4$xsvjKOwkcD9csc*lqlOZe zA>uOzV_Rr)y$Y}I%X&_At4zT<;wmf7`_~MpwhUYQ&RFm5<5Hr%A3#!TLxcN{2C0Hs z-)NOs3>azdw>@dOBPKswMdlDH)m@bLfxwkqcmd8B&$jD!gNlPf_+ZR{!db_vPbbm_ zk18;=-hH0S#+g~GE9R@F;?BnDTMY`Qvll^ca@3^=ea1c_hm4<>^T<3kuiP%@ z)?J-MuDT_*W(P6E<3&&y*Y+L62RE96;&Th4HD%h&3t;!0`!s~!fS<$hjg>(LzV`^y zu{>HE3l)R6C|#x?$ySDU?WLc5Fvhrx7|IWwliL1_!`(38g)H9#j#M@xduG-RHuB{` z4RdbaTNfXhg5CA{n%Et#_j5(2GuFr2$$(#_@9#SC)u1A-S+Oj4yX=esY@*_2S$CqC zsG;_afPf%3{+y#}xKJl*e@sg7CY0zcE_0{MZmwI#SE8NL`(>VAOY`8b5E)su8e1k+ zO7`^wi>DDztjDZrj|oJS#P6Y|#7jx-6fQk0Vi&u5KNuvFZAaZ*lb3&|>iPz;_}GBU z16<03Ew!j7kMp+_@pf`U_Uz$Z?jiktNbs6g^$z_K0qaVnQ?!Al11g-R?nzQtq73`EF_Fxaoch6PQ3Efr(-fe_*j$l(q|iVNj8y#p__$|ot3hx z!<#8RG>MSfdd><#Fnw^Htp3zm{pe#9sJeVxg-4azOG2NzX9~M$}ceSH- zHhPF=qGXdASLvbSxxv`ys%4@kPTpBrnPgZq-?_rvW8w}4>{{EX&s5UHR%)Tea6wYL z#P39|!*0@MuD%*5wh6JZRpFHvku&ukK6d-cv(D0vM5dHha!}HUs9wY7f=x%osmGd~ z3hp^@Fq;(HFkIncdI9UX5#z0;gg z2p<5e9wpcAHtndqPCS@G@Ho=RTD#>sobZs};w@2@CSbN3h@L1us_xoP(ocW=%0GLW&~t)cM-R(`Wd2yzt%CNMhBI?N>HgAB|c8 zs_Z7(a6O)0-!k4H(>gpNa?wYs>B8-YqS#!$_Kopt_8D}A#u7){j`BR?5Pd)mVtDiI3t zuAW0!!swH}52ZXet|;Xf8hsgRbOet)vHe=gBag!EbSK9TsFjK)C)K_$Y~H?o%$TZI z=}+cbi_L!%fP_rGG@{%EyQ?@SLZ0IGWdyuFZyp~%qn&Xluh+lYq4@2Vx-ILvo{w_f z_cG1D&R%a^g&K6PYau?0{y17G+V)N}B3tjg#)ecuDs2Gt-$R0(CsP<3&yZ6>HV4<} zQ<%r^t~%VL>XKdb{E5bf1VL)bQK{=0f)}5UuC76~9EWJ~5K6mQxQSLXFw=qdO_^XH zYV$+pU?=>bA2-`K>7DIz7oSrC2Taoo{doxESmDqNZ^jSegJy>*!kcRuD^N~-?K7_} z4y5qbR!52&k?Z29X@aM=fF)%TE9%g@gEozMQ_I3Wq~@6in`L|Myx8_oA~?fa&y>Ot z+_7Rm=fRLJ$*U=`#h+q3^j$7jbf=pebb8A4jW9@to7xm;J1U1tPbKDtXtEQ=x9G9g z`XE>I9WT3CN5q%$yeeEtlU}ag^DMD{wXT&xWVg)B#mcV)k10WFwMxseRIY}8pZh7; z`quiC0`V-Fwnx{9E5&vuo$+Y#QX(g1pV#zZgzDBM$jQ=r%fr7e>A?yg%?QxD>X{SB zeC6nK<@IGY^)7`WIpYI|vWfUtw{<`m6ME$z>Y|4wkvMfF+G~ zz2JP5SI;)M&x5qVsbUIB%nQ3kEM0$v;#J{bWay-|^CUVV!!LRTA##Al;NG~6)`pCV zDP3X7Cj49M)3Jf5B+W)wNr zT_DLfQYf|ueAwjE+xrmVc)5Y$@A8nN)(HiQvc#Y-W!5D(_D!sPqLoQgm23!3f27A8 zFI7n%izPlXJg_VFa)@lxHA)=B)Nt$Nq0)Y@nm9B$?$nq_A-6q4m=@8h&`y<@2)?k3 zG45!k;a&0T>~Zc5qOt=qXY~a`d;RxNM^zkEa#Mo)&u$|3M-WT9CC#@1v8q~lMQ^IU-#Jz%b zLKBTlyJ7@s9rxV&<~7J!&;u?Et(a;g_J_r^2c)bcG6!e)>xpu4%Ysk8f`>{u4^(4m zpH(AzE&Ep!y0O9+GAMf2%X-q(sCjooIAv3CyNjdPO5<>Vf)<7iKKrkc=EJjm5R zY#`cnot4+4S|$;@5v}w8`68VrYR79^kSuE08nHuIVyO;8T+ADavYasD_MH zYo8O!KeNFwi&!(d>g@?lN$=Qd2y$9ld?-d=ece|ISMBqnHEvA?E+**Kzlz~(9#j7Zf2P95G5xc zS$CRwx?4kgmyo{Y#iXlQ>6$$(p{HE!%3ERr4t(+OzAZ6!)c8>l0zX}}jrw*fyVvHd zPc^D(#;QhtkEE;VaD_)m8R!LjH_4uO2`n_2lbXb1`QXG8p`ES6AACD>EPTrIPOWY| zTR_HdRBfkqF$7XF(>x{HEAz(dLUzlFr{L2)di8l;>O}YIfbp^Vf=Cg+th~>VfVJ!H z8t)@i8S1=wuD30Cq{wUE3o_5Bf@D_2<~wywe6L^Q3!0Cu$h@fUi|IR8hs#;;pkd7cPcI4L!HT4J{{9KXQ%qJ)g$C)i zkIRd&)H^oXKI3%-rek;CDYm3>RtI0EhE3MUV))&@z0Y@lR%u^+FHL7ZSKT%>!-Uef zH`4Bd@x_BOdETbXDNoaiR@2V!EbNyr*sNl8SqQ1+#Z04=c+{LAw)uoztFvx2NGKH* zzSEWoq3ZW|$r4h)N1WcDncVWMk`#05&Y`&4+&7_lL@kHlbrj9?>E~tLTW6CG% zH7lz6@c51mvM-eUI(WxiqmB#OCB0$8GQDSGoon3snp;xb?|+46zAPtE-l@iZmEP!e z_c}O8>REDT;u((}=Ti5L_3X4w@86%U*{z|YeFs6k+LoMA?IIcBLX%W$-#nrUKJ9Vx zv(wDE$Jd_XYg!EQMK3_^xM;@vtYIq{$oia?#PaC)u+ZW)RuD1c*0qt*i;I`fM{!H$v}%L!{DYuC1c(&4!|=;l-N`uLbt%JNCi- zzNz}|7$9|4retgOG~Y>X0TV9WNbp^kaGQ39-1J8~@Rgu9S(u`=d7DJVydpxo4<2L> z8XfnW@#jhIJ{X_02kD0vX~OtmT!+$wYJhDEBw?Yh17lbog|~ zPATqo!kv1yd%>=0%}@J8-yK|ae%)0rSz`SfybGRhQvhU8S5%Q4bY&g3U6J|CWM>ht z`$_a?#Q>cfPEsyb=Qe}x5!&+t%aq9X+g7qa8+MC+>GsaJG`goib@I?hbtepiSUaU2 zrt~^zMR=ji;2A;|oQdC;Tz@3QD1SA-Pgl~ab!G=w=zgK%awc-t>rM=xSyj{C!k|0d z(^d<2A-L_HT2&!v+}vrrTaJNt@WhoE2sf^;dJJ9%wou9G>J-x27J-Rvp}Tc&ef z9Fn6{aWda|xChf`d?`6Xl|5k%7`9nqFLWzolt_ZoQGP3Kc1mXBL7Ql$dzEpKY8-ke z*5FKsghDtF1`nBNN5`ToyE7|;IQ-O(uhR9N`;0S^M}vtW>jHJH+Q~DAcnV^omGN1M zIWIK=1tA~ri`&}Z2Nc)N*mCD`#ujpDV!qNOM%`S!9FZKUD+3R6Xe$eHO?_D5R-nCB zE%amV?t%wvx=%*A98UtBWS6$fPcOYy9mJu`v=iZ7xRMeIs(&tQQL~YNJi6k9{5qE7 z;~Y$iejiPoD%BsrJ~AlXyRw23X7Q-U$8FkH zoH!*I*eA%i*-|1va?Mp^->wy^ZHHFJgt7~6;qtyOvYn+Oa8-D&I@7Iy&7SP4&y*N? zf|S4%<>Tcm^wffheHW$kR*@~)(>@B2q8M(ZG8ykOL0xRk7AXOb_&=2T@08QH)3?*ED?t0Og7ri4&QhUkGhX~o1*-@~2VX;pPIha- zSDPoFSc$wASoQ77^ed>{8HO*>?K;6hB{}SEkvYlinrG^{KXE&L; zJ}I>WVNlAuHXHZG^{la5*^wgJ>F1AlLQ!{f(5wx=x{hL_^k&b7py>5$dKEgNeN@dZ z`H@(|)m$*0IK(Yp=*0MWR+zxXYTmX3))V&9QjgVGcp0gOAl_;PWbJ;9JwkT+vf^iX zq6)8KIL@%vF)_5kDCaEk#sw0_aHg;oJdVT$0pcxL=j!!xnpR3_t9Xt0Sd6Twp#<-} ztDS2JJB~Kxd>mmgHrXd$aM~-`*zfvEGre}sH-*8`mO}KL$9^>nZffFLOw=g&(q?h zMhn(_OBtIyiVFAG0Dd)6gR9rc zN)viru1!{f1G9hsrd$TzfJSpSs7*tcp?zC_E0lDgi7hgXXIepn6RPw$cy(W?p003 zA`vw!G?m?iVhR}ZmHnTth>+S8!hI=vts|oW?B8)$!Ww@j1yO{ z;^3{8O5yPnih~;+PI7Lj;U|`{!g@Nv$DE=>RO{ef?t0Cuf*V=Ug!k>U_8%%9X!m(OalEXj$Jwl&FRUgwxZdsA zx>klYJvxvWKA+J?9m2apGfpXf)gxxV^yk22U@(ebKdxW@>g_3f3GXD%cFX7SQ!l^0 zA8Up5Or-Am_9Y?t-l1>PQ=hZ<-3xhn_-l<@^5H49sh8(;3ONac4xPg39Nz5g&O3#j z0o4=3thb3aehfp8Q<=F!|oh+mEk4jJGBSd@h@GEB3>@?<|4% zH)eku%g^5Rtu^_sTl@4#+3UJ*@?TFE%=Gg`yB?m>y1MV~p{eP6`vTf6HrB8``?ktj z`=b=e)pq{Y#rL}&^S9er&zM;ftSO z?tOkGYjM8q0RasSMiwg>&1F~_IX`lVpY7VVo*e?W6zJn2#VD})7B*NC(*!p6HOP0Y z*H3=`@p0o;MaD9&6rMQo0v-)Nch>M7m-KorO`V2X8j$z|k0eAyJut4zYG&LBHnS+( zn^7p zf4=i&IeUzfFVj!yPtLBl|<HQFQ6O@{^a%O}nl~h79K#mAlUj>%W4x zjAWcFzOiq*eS64b*E5_q4|+|G?c`tc9?>{{8yHuJ?{S4eEy$4nLtvr)b@pIUfapR0 z&FpFRxv2|98mv{5omUnZ9K9gJ{0~mV{)H3&`zA0J3-BiHfAFTqR+>YD`iS6E4)7t2<{Bl< zpeW?U@WjFp#XX@Xq7`@R*;%ODSrjR{lgR4(sYef+?AJ4~+h1t6hgbJl(9ugG%E!QZ zGJB<2KT01-Kf)5B;7@m(;X1KHK)2z(yA6u?F2h0p+-*46zs4R8w%A)Z`10P`5vIxh z0K}j?nPeSbbdlHeaLx3qdgC?gcbo2q#;ca1J1z7OHxm$ItO=Cx+3mXp(Q@}MVDSDv{!G|*na-FQc8xAH@-vk-U)_B z(#l4$-5d{AhZY$X&0G^c_LUQsM6$ndQ*1<)|3%u<@taVgeZD0oq>l!Tdc>MnJ2Q58Xp-QHaMbzBZ2xp64-^DfJ6Te zBZ2wn;Kl$30Q(2Q9Z|=A6e?Ku{#)vh-g+hUTE9o@UBy6SD|iKL%OkM2KTYR4v}>OG z+KeIhWne=kr>tIyJGKgz;`-KttM^($D3w+ocUvM>m%Zwo7#f86$F`<1IVG7KC0I?Y zqgJbow^wh!Azb^_Gp^_|w}~IoN3q{M zioh+%aDVPm7!>+{7Tol{esL}g3j2fbj=V?nF8{+x`9~2l#^Q%N^dk1|M^3Cc$&HUQ zx>WvQqPfdjuoiQu@bilo$Dqf1VSSuEtb_5H+n8Bah=E?~RgJFBJu8a!Y{$B6Oghnd zowv9-He!Dq*~2$6Dt46F^lFkeKdG&qG3f5~&d+ymtv%Rpal6>sMJwx^Jwe8$?i8dv zH{Cz))DgjV`bN6$&-{$AH#)L&GQAa^zHLBIJPe=d(6UoJ zdAZz&Fm!CZYMObJ=QP=*gqQ8FOLMYM_(R~A%4T-p$~XWZlBf}s~W$x z<<^!l)TL1S@HEBYLH}{9yPw8&PrGWl7T4YFeB&cL_-*gkGdiQvt=wZ52gsADjvS9P z1fUoO2z!-Aan)u^ByBo$p;ypMM)RWY()!?YaK7e*CCJjHBxp;fqa?X$>z%8~0bR zkNF>GWQh*p7?J^vbm-qXw10RopNDI2_RIs8CI^S;lqa&s8&|%!58^eEd|~)L?2%Gf zSq)KkN7pePiI@2iU)wR0oaYY)T4Xj~W<(;lx=!SFw7S@mW)5V*Qm6TYoL0#;b8(I7 z2`X$Rm>8jlj8i)%72>??NtlNls<+@P^{?fvEE_g;3s&zOisw!t7oS>*$O#Y}R+8I0 z%6QJ>Tr!pAP2jZC4U^}sVjQfipAL^!plfV*CTWO#c4vtg!^d&6So7(KNnz9+QR9QV z5izbt8AGqe%bmz=89Y~n96zEsO_yU|w?yE}&JW?K#}(iyDPLn( zA=`w8sTSVnygUxKmA8yw&q_{_$F+rqx^kGk+JfGPNtjbeuQ}Y~T$H`4)`{;e==4|Q z+m?V%{$z{XDv_AIGmzPKirfN@IwC}Vxw)?Y(5K9Bv6z%tPM-HQTO1zJ{$AiqYR1Ur`)Dd1%S$p~y2Nn8yI|8(%|k;IkX4t{!oTV?hl!`le^c6;uAW$&nT<~e2|OP- zegDlK`{AR=>XuiE_usi=YDhjgq|#EYj&MN_3an}Oo`B5Mu9-|fjXf(ki4Wagu)DoJ zAGqFVgz7h3V4M-Iqjd9tnq0r7K}ox8d$f1?+t1C1wI#XK8shoh4LvLOCAf)*+cHL% z_!Z+=0+OKELH|m}{Y-}~qQjP>BNql( z$9;BI{T2(u{DP(1`5g;igoQ7MMJ-_UNj5aQJ$-+}MWS%Oa$!Gn7v(fKVmU5)fvaF+ zGdl}t9{(Mgw*CBtyx2(OGSdt3eR|P<2>5+^{j3lYkN|)a47bb#TQuw8!2Cv^cHfb- zIknf#9z(pFm|D3Y{yhSr=-eL3b#Rg)Q zgCo8tjaeH(vxUp=3|%~#0ERBAf0V2|t(@KL=|7YDUIEShViAO*Cpsfq@+MJez1fjy zy3JQXwAOpAeBHb}AqGBfN^Z_xF0OOW_oM9rb-X;C9bIYXe-ED7##*%U24d(z`u-t= zwm))Ju$lEBU=3P$`SHuC12j6z?2ol^AQtGtKM)#)LZCo)KV-8@;oK*#3o`hucNfcM zuXit!A!dKDw@8MZ{mJPf8EQ5?Es~*Uuj?$9p@0kw3V1Gd_BWA>WH>ay4%!|Xa4v18 z0Q92;6Tn^=0t;ZkkXYckC@jDSFf(3@{GhSOk!PLjV{EC<4Ghz<{xVfFl761Of$MAdn~^0|kr? zT1WyJ7&MT9#Q+&N41j@zVgL*z3>X_oI2JIzNCa@sAd#~-4i?E!z&Jo+fb#>1g#sBk zD1d>2!T=1^Tn)BJ28RO}CPTaX=YRKQs~;_h=*rsNZbq1CXHszCxpca}fO>c@2$$0`0({fOcSj`2dYY0_>oL z3xJD(p%&W#L!glVAp_)77y^v}$}s;W!vXul0rCcI<^#_~B5*(%3JR2=0rLZf#K3?u zEFd;$9suM?nhdBP3Wfm65CA{ZWN4rai3M^oKtI#!44@1Ph&31*iopV9IG_v;1Imy< z1{w*-S1>dRhXBa1(EpGD@&Rpm1FV;{j0n^P3j_K93kSqF42wh{figh8hhb4LV1H;B zupI^k)CCJz7ih~bFeY(O9Kbdl9I(#7a0o!X0mC5ywEzr<2IOKG4ub%4u_&Mn2N+8@ z6b8sIa9V)?lpzpkfDDQJ$ + + + + + DRAFT - CUPS Software Administrators Manual + + + +

Scope

+ +

Identification

+ +This softwae administrators manual provides printer administration +information for the Common UNIX Printing System ("CUPS") Version 1.0.0. + +

Document Overview

+ +

This software administrators manual is organized into the following sections:

+ +
    +
  • 1 - Scope
  • +
  • 2 - References
  • +
  • 3 - Printing System Overview
  • +
  • 4 - Printer Queue Management
  • +
  • 5 - Printing System Management
  • +
  • A - Glossary
  • +
+ +

Printing System Overview

+ +

Printer Queue Management

+ +

Adding Printers

+ +

Removing Printers

+ +

Reconfiguring Printers

+ +

Printer Options

+ +

Printer Security

+ +

Printer Accounting

+ +

Printing System Management

+ +

Log Files

+ +

Network Configuration

+ +

Adding File Types

+ + + diff --git a/doc/sdd.html b/doc/sdd.html new file mode 100644 index 0000000000..aaa2ebcd66 --- /dev/null +++ b/doc/sdd.html @@ -0,0 +1,470 @@ + + +DRAFT - CUPS Software Design Description + + + + + +

+

DRAFT - CUPS Software Design Description


+CUPS-SDD-1.0
+Easy Software Products
+Copyright 1997-1999, All Rights Reserved
+
+
+

Table of Contents

+
+
1 Scope + +2 References + +3 Design Overview + +4 Detailed Design +
+
A Glossary + +
+

1 Scope

+

1.1 Identification

+ This software design description document provides detailed +information on the architecture and coding of the Common UNIX Printing +System ("CUPS") Version 1.0. +

1.2 System Overview

+ The Common UNIX Printing System provides a portable printing layer for + UNIX® operating systems. It has been developed by Easy Software + Products to promote a standard printing solution for all UNIX vendors + and users. CUPS provides the System V and Berkeley command-line +interfaces. +

CUPS uses the Internet Printing Protocol (IETF-IPP) as the basis for +managing print jobs and queues. The Line Printer Daemon (LPD, RFC1179), +Server Message Block (SMB), and AppSocket protocols are also supported +with reduced functionality.

+

CUPS adds network printer browsing and PostScript Printer +Description ("PPD")-based printing options to support real world +applications under UNIX.

+

1.3 Document Overview

+ This software design description document is organized into the + following sections: +
    +
  • 1 - Scope
  • +
  • 2 - References
  • +
  • 3 - Design Overview
  • +
  • 4 - Detailed Design
  • +
  • A - Glossary
  • +
+

2 References

+

2.1 CUPS Documentation

+ The following CUPS documentation is referenced by this document: +
    +
  • CUPS-CMP-1.0: CUPS Configuration Management Plan
  • +
  • CUPS-IDD-1.0: CUPS System Interface Design Description
  • +
  • CUPS-SAM-1.0.x: CUPS Software Administrators Manual
  • +
  • CUPS-SDD-1.0: CUPS Software Design Description
  • +
  • CUPS-SPM-1.0: CUPS Software Programming Manual
  • +
  • CUPS-SSR-1.0: CUPS Software Security Report
  • +
  • CUPS-STP-1.0: CUPS Software Test Plan
  • +
  • CUPS-SUM-1.0.x: CUPS Software Users Manual
  • +
  • CUPS-SVD-1.0.x: CUPS Software Version Description
  • +
+

2.2 Other Documents

+ The following non-CUPS documents are referenced by this document: +
    +
  • IEEE 1387.4, System Administration: Printing (draft)
  • +
  • IPP/1.0: Additional Optional Operations - Set 1
  • +
  • IPP/1.0: Encoding and Transport
  • +
  • IPP/1.0: Implementers Guide
  • +
  • IPP/1.0: Model and Semantics
  • +
  • RFC 1179, Line Printer Daemon Protocol
  • +
+

3 Design Overview

+ CUPS is composed of 7 software sub-systems that operate together to + perform common printing tasks: +
    +
  • Backends
  • +
  • Berkeley Commands
  • +
  • CGI
  • +
  • CUPS Interface Library
  • +
  • Filters
  • +
  • Scheduler
  • +
  • System V Commands
  • +
+

3.1 Backends

+ The backends implement communications over a number of different +interfaces. All backends are called with a common set of arguments: +
    +
  • Device URI - the Uniform Resource Identifier for the output device + (e.g. parallel:/dev/plp, ipp://hostname/resource +).
  • +
  • Job Identifier - the job identifier for this job (integer).
  • +
  • User Name - the user associated with this job (name string).
  • +
  • Title - the title/job-name associated with this job (name string).
  • +
  • Copies - the number of copies required (integer).
  • +
  • Options - the options associated with this job (space separated + option strings).
  • +
  • Filename (optional) - the file to print; if this option is not + specified, the backend must read the print file from the standard + input.
  • +
+ Backends are named using the method of the URI, so a URI of +"ipp://hostname/resource" would be processed by the "ipp" backend. +

3.1.1 ipp

+ The ipp backend sends the specified job to a network printer or host +using the Internet Printing Protocol. The URI is as specified by the +printer-uri-supported attribute from the printer or host. +

3.1.2 lpd

+ The lpd backend sends the specified job to a network printer or host +using the Line Printer Daemon protocol. The URI is of the form: +
    +
    lpd://hostname/queue
    +
    +
+

3.1.3 parallel

+ The parallel backend sends the specified job to a local printer +connected via the specified parallel port device. The URI is of the +form: +
    +
    parallel:/dev/file
    +
    +
+

3.1.4 serial

+ The serial backend sends the specified job to a local printer +connected via the specified serial port device. The URI is of the +form: +
    +
    serial:/dev/file?option[+option+...]
    +
    +
+ The options can be any combination of the following: +
    +
  • baud=rate - Sets the baud rate for the device.
  • +
  • bits=7 or 8 - Sets the number of data bits.
  • +
  • parity=even - Sets even parity checking.
  • +
  • parity=odd - Sets odd parity checking.
  • +
  • parity=none - Turns parity checking off.
  • +
+

3.1.5 smb

+ The smb backend sends the specified job to a network host using the +Server Message Block protocol, which is used by most machines running +Microsoft® Windows®. The URI is of the form: +
    +
    smb://hostname/queue
    +
    +
+ Usernames and passwords required to access the printer are stored in +an external file. +

3.1.6 socket

+ The socket backend sends the specified job to a network host using the +AppSocket protocol commonly used by Hewlett-Packard and Tektronix +printers. The URI is of the form: +
    +
    socket://hostname[:port]
    +
    +
+ The default port number is 9100. +

3.2 Berkeley Commands

+ The Berkeley commands provide a simple command-line interface to CUPS +to submit and control print jobs. It is provided for compatibility with +existing software that is hard coded to use the Berkeley commands, +however since printer options cannot be specified using the Berkeley +commands their use it not encouraged. +

3.2.1 lpc

+ The lpc command allows users and administrators to check the status +and control print queues. The version provided with CUPS supports the +following commands: +
    +
  • abort - Stops a printer or all printers and any active print jobs.
  • +
  • disable - Prevents new jobs from being submitted to the specified + printer or all printers.
  • +
  • down - Stops a printer or all printers after completing the current + print jobs.
  • +
  • enable - Allows new jobs to be submitted.
  • +
  • start - Starts a printer or all printers.
  • +
  • status - Shows the status of printers and jobs in the queue.
  • +
  • up - Starts a printer or all printers.
  • +
+

3.2.2 lpr

+ The lpr command submits a job for printing. The CUPS version of lpr +silently ignores the "i", "p", "t", "m", "h", and "s" options. +

3.2.3 lprm

+ The lprm removes one or more print jobs. +

3.3 CGI

+ The Common Gateway Interface (CGI) programs provide a web-based status +interface to monitor the status of printers, classes, and jobs. +

3.3.1 classes

+ The classes CGI lists the available printer classes and any pending +jobs for the class. The user can click on individual classes to limit +the display and click on jobs to see the job status. +

3.3.2 jobs

+ The jobs CGI lists the queued print jobs in order of priority. The +list can be limited by printer or job. When the user displays the +status of an individual print job all job options are displayed. +

3.3.3 printers

+ The printers CGI lists the available printer queues and any pending +jobs for the printer. The user can click on individual printers to +limit the display and click on jobs to see the job status. +

3.4 CUPS Interface Library

+ The CUPS interface library provides common convenience, HTTP, IPP, +language, MIME, PPD, and raster functions used by the CUPS software. +

3.4.1 Convenience Functions

+ Convenience functions are provided to submit an IPP request, send a +print file, cancel a job, get a list of available printers, and get a +list of available classes. +

3.4.2 HTTP Functions

+ The HTTP functions provide functions to connect to HTTP servers, issue +requests, read data from a server, and write data to a server. +

3.4.3 IPP Functions

+ The IPP function provide functions to manage IPP request data and +attributes, read IPP responses from a server, and write IPP requests to +a server. +

3.4.4 Language Functions

+ The language functions provide a standard interface for retrieving +common textual messages for a particular locale and determining the +correct encoding (e.g. US ASCII, ISO-8859-1, etc.) +

3.4.5 MIME Functions

+ The Multimedia Internet Mail Exchange functions manage a MIME type and +conversion database that supports file typing by extension and content, +and least-cost file filtering from a source to a destination file type. +

3.4.6 PPD Functions

+ The PostScript Printer Description functions manage PPD files, select +options, check for option conflicts, and emit selected options in the +correct order. +

3.4.7 Raster Functions

+ The raster functions manage streams of CUPS raster data (described in +the Interface Design Document) used by non-PostScript printer drivers. +

3.5 Filters

+ The filters implement file conversion services for CUPS. All filters +are called with a common set of arguments: +
    +
  • Printer name - the name of the destination printer (name string).
  • +
  • Job Identifier - the job identifier for this job (integer).
  • +
  • User Name - the user associated with this job (name string).
  • +
  • Title - the title/job-name associated with this job (name string).
  • +
  • Copies - the number of copies required (integer).
  • +
  • Options - the options associated with this job (space separated + option strings).
  • +
  • Filename (optional) - the file to print; if this option is not + specified, the filter must read the input file from the standard + input.
  • +
+ Filters are added to the MIME conversion data file and implement all +necessary conversions from one file type to another. +

3.5.1 hpgltops

+ The hpgltops filter converts HP-GL/2 files into PostScript. +

3.5.2 imagetops

+ The imagetops filter converts image files into PostScript. +

3.5.3 pstops

+ The pstops filter inserts printer-specific commands from PPD files and +performs page filtering as requested by the user. +

3.5.4 texttops

+ The texttops filter converts text files into PostScript. +

3.6 Scheduler

+ The scheduler is a fully-functional HTTP/1.1 server that manages the +printers, classes, and jobs in the system. It also handles a simple +broadcast-based directory service so that remote print queues and +classes can be accessed transparently from the local system. +

3.6.1 Authorization

+ The authorization module is responsible for performing access control +and authentication for all HTTP and IPP requests entering the system. +

3.6.2 Classes

+ The classes module is responsible for managing printer classes in the +system. Each class is a collection of local and/or remote printers. + The classes module also reads and writes the classes configuration +file. +

3.6.3 Client

+ The client module is responsible for all HTTP client communications. + It handles listening on selected interfaces, accepting connections +from prospective clients, processing incoming HTTP requests, and +sending HTTP responses to those requests. The client module also is +responsible for executing the external CGI programs as needed to +support web-based printer, class, and job status monitoring. +

Once authorized, all IPP requests are sent to the IPP module.

+

3.6.4 Configuration

+ The configuration module is responsible for reading the CUPS +configuration file and initializing the appropriate data structures and +values. The configuration module also stops CUPS services before +reading the configuration file and restarts them after the +configuration file has been read. +

3.6.5 Directory Services

+ The directory services module sends and recieves printer state +information over a broadcast socket. Remote printers and classes are +automatically added to or removed from the local printer and class +lists as needed. +

The directory services module can only recieve printer state +information over a single UDP port, however it can broadcast to +multiple addresses and ports as needed.

+

3.6.6 IPP

+ The IPP module handles IPP requests and acts accordingly. URI +validation is also performed here, as a client can post IPP data to any +URI on the server (which might sidestep the access control or +authentication of the HTTP server.) +

3.6.7 Jobs

+ The jobs module manages print jobs, starts filter and backend +processes for jobs to be printed, and monitors status messages from +those filters and backends. +

3.6.8 Main

+ The main module is responsible for timing out and dispatching input +and output for client connections. It also watches for incoming +SIGHUP signals and reloads the server configuration files as +needed. +

3.6.9 Printers

+ The printers module is responsible for managing printers and PPD files +in the system. The printers module also reads and writes the printers +configuration file. +

3.7 System V Commands

+ The System V commands provide a robust command-line interface to CUPS +to submit and control print jobs. +

3.7.1 accept

+ The accept command tells the scheduler to accept new jobs for specific +printers. +

3.7.2 cancel

+ The cancel command tells the scheduler to cancel one or more jobs that +are queued for printing. +

3.7.3 disable

+ The disable command tells the scheduler to stop printing jobs on the +specified printers. +

3.7.4 enable

+ The enable command tells the scheduler to start printing jobs on the +specified printers. +

3.7.5 lp

+ The lp command submits submits files for printing. Unlike the +standard System V lp command, a single CUPS lp command will generate a +separate job ID for each file that is printed. Also, the Solaris "f", +"H", "P", "S", and "y" options are silently ignored. +

3.7.6 lpadmin

+ The lpadmin command manages printer queues and classes. The Solaris +"A", "F", "I", "M", "P", "Q", "S", "T", "U", "W", "f", "l", "m", "o", +"s", "t", and "u" options are not supported, and new options "P" (PPD +file) and "F" (filter) are provided to configure CUPS-specific features +such as PPD file and conversion filters. +

3.7.7 lpstat

+ The lpstat command lists printers, classes, and jobs as requested by +the user. +

3.7.8 reject

+ The reject command tells the scheduler not to accept new jobs for +specific printers. +

4 Detailed Design

+

A Glossary

+

A.1 Terms

+
+
C
+
A computer language.
+
parallel
+
Sending or receiving data more than 1 bit at a time.
+
pipe
+
A one-way communications channel between two programs.
+
serial
+
Sending or receiving data 1 bit at a time.
+
socket
+
A two-way network communications channel.
+
+

A.2 Acronyms

+
+
ASCII
+
American Standard Code for Information Interchange
+
CUPS
+
Common UNIX Printing System
+
ESC/P
+
EPSON Standard Code for Printers
+
FTP
+
File Transfer Protocol
+
HP-GL
+
Hewlett-Packard Graphics Language
+
HP-PCL
+
Hewlett-Packard Printer Control Language
+
HP-PJL
+
Hewlett-Packard Printer Job Language
+
IETF
+
Internet Engineering Task Force
+
IPP
+
Internet Printing Protocol
+
ISO
+
International Standards Organization
+
LPD
+
Line Printer Daemon
+
MIME
+
Multimedia Internet Mail Exchange
+
PCL
+
Page Control Language
+
PPD
+
PostScript Printer Description
+
SMB
+
Server Message Block
+
TFTP
+
Trivial File Transfer Protocol
+
+ + diff --git a/doc/sdd.pdf b/doc/sdd.pdf new file mode 100644 index 0000000000..213f4e36f5 --- /dev/null +++ b/doc/sdd.pdf @@ -0,0 +1,993 @@ +%PDF-1.2 +%âãÏÓ +1 0 obj<>endobj +2 0 obj<>endobj +3 0 obj<>endobj +4 0 obj<>endobj +5 0 obj<>endobj +6 0 obj<>endobj +7 0 obj<>endobj +8 0 obj<>endobj +9 0 obj<>endobj +10 0 obj<>endobj +11 0 obj<>endobj +12 0 obj<>endobj +13 0 obj<>endobj +14 0 obj<>endobj +15 0 obj<>endobj +16 0 obj<>endobj +17 0 obj<>endobj +18 0 obj<>endobj +19 0 obj<>endobj +20 0 obj<>endobj +21 0 obj<>endobj +22 0 obj<>endobj +23 0 obj<>endobj +24 0 obj<>endobj +25 0 obj<>endobj +26 0 obj<>endobj +27 0 obj<>endobj +28 0 obj<>endobj +29 0 obj<>endobj +30 0 obj<>endobj +31 0 obj<>endobj +32 0 obj<>endobj +33 0 obj<>endobj +34 0 obj<>endobj +35 0 obj<>endobj +36 0 obj<>endobj +37 0 obj<>endobj +38 0 obj<>endobj +39 0 obj<>endobj +40 0 obj<>endobj +41 0 obj<>endobj +42 0 obj<>endobj +43 0 obj<>endobj +44 0 obj<>endobj +45 0 obj<>endobj +46 0 obj<>endobj +47 0 obj<>endobj +48 0 obj<>endobj +49 0 obj<>endobj +50 0 obj<>endobj +51 0 obj<>endobj +52 0 obj<>endobj +53 0 obj<>endobj +54 0 obj<>endobj +55 0 obj<>endobj +56 0 obj<>endobj +57 0 obj<>endobj +58 0 obj<>endobj +59 0 obj<>endobj +60 0 obj<>endobj +61 0 obj<>endobj +62 0 obj<>endobj +63 0 obj<>endobj +64 0 obj<>endobj +65 0 obj<>endobj +66 0 obj<>endobj +67 0 obj<>endobj +68 0 obj<>endobj +69 0 obj<>endobj +70 0 obj<>endobj +71 0 obj<>endobj +72 0 obj<>endobj +73 0 obj<>endobj +74 0 obj<>endobj +75 0 obj<>endobj +76 0 obj<>endobj +77 0 obj<>endobj +78 0 obj<>endobj +79 0 obj<>endobj +80 0 obj<>endobj +81 0 obj<>endobj +82 0 obj<>endobj +83 0 obj<>endobj +84 0 obj<>endobj +85 0 obj<>endobj +86 0 obj<>endobj +87 0 obj<>endobj +88 0 obj<>endobj +89 0 obj<>endobj +90 0 obj<>endobj +91 0 obj<>endobj +92 0 obj<>endobj +93 0 obj<>endobj +94 0 obj<>endobj +95 0 obj<>endobj +96 0 obj<>endobj +97 0 obj<>endobj +98 0 obj<>endobj +99 0 obj<>endobj +100 0 obj<>endobj +101 0 obj<>endobj +102 0 obj<>endobj +103 0 obj<>endobj +104 0 obj<>endobj +105 0 obj<>endobj +106 0 obj<>endobj +107 0 obj<>endobj +108 0 obj<>endobj +109 0 obj<>endobj +110 0 obj<>endobj +111 0 obj<>endobj +112 0 obj<>endobj +113 0 obj<>endobj +114 0 obj<>endobj +115 0 obj<>endobj +116 0 obj<>endobj +117 0 obj[11 0 R +12 0 R +13 0 R +14 0 R +15 0 R +16 0 R +17 0 R +18 0 R +19 0 R +20 0 R +21 0 R +22 0 R +23 0 R +24 0 R +25 0 R +26 0 R +27 0 R +28 0 R +29 0 R +30 0 R +31 0 R +32 0 R +33 0 R +34 0 R +35 0 R +36 0 R +37 0 R +38 0 R +39 0 R +40 0 R +41 0 R +42 0 R +43 0 R +44 0 R +45 0 R +46 0 R +47 0 R +48 0 R +49 0 R +50 0 R +51 0 R +52 0 R +53 0 R +54 0 R +55 0 R +56 0 R +57 0 R +58 0 R +59 0 R +60 0 R +61 0 R +62 0 R +63 0 R +64 0 R +65 0 R +66 0 R +67 0 R +68 0 R +69 0 R +70 0 R +71 0 R +72 0 R +73 0 R +74 0 R +75 0 R +76 0 R +77 0 R +78 0 R +79 0 R +80 0 R +81 0 R +82 0 R +83 0 R +84 0 R +85 0 R +86 0 R +87 0 R +88 0 R +89 0 R +90 0 R +91 0 R +92 0 R +93 0 R +94 0 R +95 0 R +96 0 R +97 0 R +98 0 R +99 0 R +100 0 R +101 0 R +102 0 R +103 0 R +104 0 R +105 0 R +106 0 R +107 0 R +108 0 R +109 0 R +110 0 R +111 0 R +112 0 R +113 0 R +114 0 R +115 0 R +116 0 R +]endobj +118 0 obj<>endobj +119 0 obj<>endobj +120 0 obj<>endobj +121 0 obj<>endobj +122 0 obj<>endobj +123 0 obj<>endobj +124 0 obj<>endobj +125 0 obj<>endobj +126 0 obj<>endobj +127 0 obj<>endobj +128 0 obj<>endobj +129 0 obj<>endobj +130 0 obj<>endobj +131 0 obj<>endobj +132 0 obj<>endobj +133 0 obj<>endobj +134 0 obj<>endobj +135 0 obj<>endobj +136 0 obj<>endobj +137 0 obj<>endobj +138 0 obj<>endobj +139 0 obj<>endobj +140 0 obj<>endobj +141 0 obj<>endobj +142 0 obj<>endobj +143 0 obj<>endobj +144 0 obj<>endobj +145 0 obj<>endobj +146 0 obj<>endobj +147 0 obj<>endobj +148 0 obj<>endobj +149 0 obj[118 0 R +119 0 R +120 0 R +121 0 R +122 0 R +123 0 R +124 0 R +125 0 R +126 0 R +127 0 R +128 0 R +129 0 R +130 0 R +131 0 R +132 0 R +133 0 R +134 0 R +135 0 R +136 0 R +137 0 R +138 0 R +139 0 R +140 0 R +141 0 R +142 0 R +143 0 R +144 0 R +145 0 R +146 0 R +147 0 R +148 0 R +]endobj +150 0 obj<>endobj +151 0 obj<>endobj +152 0 obj<>endobj +153 0 obj<>endobj +154 0 obj<>endobj +155 0 obj<>endobj +156 0 obj<>endobj +157 0 obj<>endobj +158 0 obj<>endobj +159 0 obj<>endobj +160 0 obj<>endobj +161 0 obj<>endobj +162 0 obj<>endobj +163 0 obj<>endobj +164 0 obj<>endobj +165 0 obj<>endobj +166 0 obj<>endobj +167 0 obj<>endobj +168 0 obj<>endobj +169 0 obj<>endobj +170 0 obj<>endobj +171 0 obj<>endobj +172 0 obj<>endobj +173 0 obj<>endobj +174 0 obj<>endobj +175 0 obj<>endobj +176 0 obj<>endobj +177 0 obj<>endobj +178 0 obj<>endobj +179 0 obj<>endobj +180 0 obj<>endobj +181 0 obj<>endobj +182 0 obj<>endobj +183 0 obj<>endobj +184 0 obj<>endobj +185 0 obj<>endobj +186 0 obj<>endobj +187 0 obj<>endobj +188 0 obj<>endobj +189 0 obj<>endobj +190 0 obj<>endobj +191 0 obj<>endobj +192 0 obj<>endobj +193 0 obj<>endobj +194 0 obj<>endobj +195 0 obj<>endobj +196 0 obj<>endobj +197 0 obj<>endobj +198 0 obj<>endobj +199 0 obj<>endobj +200 0 obj<>endobj +201 0 obj<>endobj +202 0 obj<>endobj +203 0 obj<>endobj +204 0 obj<>endobj +205 0 obj<>endobj +206 0 obj<>endobj +207 0 obj<>endobj +208 0 obj<>endobj +209 0 obj<>endobj +210 0 obj<>endobj +211 0 obj<>endobj +212 0 obj<>endobj +213 0 obj<>>>>>endobj +214 0 obj<>stream +xÚíßoä8rÇ%µúeždïö;ݞ 3Óö¸go€ h“y+Iòäá°;wÙàr{73w‡ûïãþáný ¥ª"%Q>sÝµMµø‹ß*’EõŸ_]‰õã?Wâ‡kñþƒøéÿ^ÝÉW‰|õgñ~ý›·?ìþøþÇ·kñ›o¯ÅõõÕۛ]­Oïîóÿz÷é]öïwbó¯ë]y¿+våã®Üïʏ»òoÿýî“øöå/Ÿßý§¸yõî?ÄæêêÝ܋ñéáUñ< ¼p™ùp½\./ζåñ–7Sç’÷˳ÈS•³óˇirÉë 5R ny31.yÝÅôTÎ/“©pá¡h7S຿ðÈÅ_&ŽsÝE¯œoæºæRÙ4Gp¦¯ìö™e®{ᙗïǸò ÏJñ/âºö¬•`㠗žÍré—±^Øí2K\ò³^ü×£så‘×Gùnd®;¯§$cr]y½3—e´nc=–×£pÉÈó\'…°Z¾œk,L‹SÀb€Ó’Á˜–ç­âêÝo™9h6×ÀX`É\koð ÀuëPf½seÞ(åûž¹òh.‚(‚û +ÏÒ˜‚2´&¢Ô!FçʽQ˦/®h\.äƒ 8dŽƒix.²Ø¹äøXžß—p€Ë ­sežec™KFnp–¹Öž#ea•+óœ)‰E.W¬åÄ\±çPÙXãÊ]Âꔘžh ¢˜ h`¢˜T¤×z,WêVG‡Áô4Õa0AÇ8g—t«5®‡)jt Ï½B<×LÏ?=¢ˆ2ùα‚ä¹v%”ïàòô\Ùá³rŠ"J¨âŠˆfØÉµÒríï5ßÿ +¿d×)l3—¤ša'W¨çZïDsÕh¹ÍWpeT3ìäòõ\û›=§Rì•,×ìX[ɵ7Ž3êÊ12BªW +,×0§÷óâ2W5#jÝCF#ÐSÅjåVåáëe®¸bØi©€–Cíäïô^“×…’K6¸¢Šåå=¤j:êÕÛI¾{ñ©>ÀR*Wʔ粬îquGó~1©X™&É%xQ”ó\/ŠrKšÈ¡Ã\¹¡ºÊ•q£CǹÒç&‡®˜ºÍµæG‡Ns‰ç&ó®è¹É။³4?.ùìd~ϕ=;™ÇrMBæË“@À¹e÷£y¹ÿ¶’óM‰+fË|¹ÎùFõ[ïì²²ìwZímçSFÛ]iYç–W®ÓºM}p&J®‡k¡æ*¤ï\‚í¾ÔøÕ©5qÆáš)¹rõþrÄv_jךèq¸<%—Pï;ðmÔöªËM­5qÅáZ)¸Ò¦ÊÊ-X®™&|Y©¸BW¨àŠšÑ2×Þ`u¹sµ&® Éõ$þYt´{@¹å͵Rsù*®úq>Wã àQηþä>:˜ ŽkÞʵû¿{áUZ0¯:–DŵPº¢j<Џ¨ìdž6Ûn,º¹/Ÿ5vn½Êñ€rg®ÆEYÅn¨Eì‚«”–RíâSnO½‰‡«qQuÓéÇ¨0jƒá:¥)²äçÊ&®8\õ‹D50ßфP϶sI W¬ç +9\õ‹j#eg– Â¨ÃuúA‘ý¯æò9\µ‹êO%žËïƒKqœ¯›KqQVw°ËÇr ˜ð00çjê†â8_7—î `¨š/{v¸¤†k­ÖyÅq>Wó¢Xé`F……‰FǜÛj›Çù\͋„Ò¡¸æ(®Lí¿2M¥8·àj^¤åÊ,qÅÊxãþ†ÔšØ<·àj^)Šká’^C‘[ç)Šã|®ÆEZ®”F•ÚpøŠÆz^©8·áj\T®~º#ŠkSοÊ&6Žóa¸i¹€FêŽÑ¬ª6šxmWý"®Íª~ë'š&֏ó¡¸êi¹b‹\u/&ê&֏ó¡¸êi¹Öüð°Pœfy¿ÑÄúq>Wý¢¨–¦zäÖ¸üDÃU +U+M¬çÃqÕ.âsH.UúíÁ/–=ê&֎óá¸j‰’bW¸";\¥üÃr¼±_öÕM¬çÃqÕ.jÄQ)–+,pó”BÅUz?”¢‰;ѦrU/Z×#¢øÀåõ˕µqUó!¹gËM\c¹æF\¹.ž?•‚ÈU½(­•hÏ%{撚SŠã|H®êEYM²¥‡åZq­\Àáª\$k¡yêWÎáª^U˜8puç®zäªçÃrU/ŠÉø\Ù¸\1‡«rQzÚU>-òŽÎ•q¸*Ér+³c¼a2­´À%9\ՋÄiÿëÎ#p%}r•ó¡¹ª¥ýJ¸RWõ¢Z$(v\&ÓeWÔΕs¸ªUgÆáÚ ®Òq>WJ©;.×Ýîfþ%¦¹”º#s]ԏ¯U_6TzÜ¢®z7@½Så)Ji[gÌ%éÕ<ýòöT³.ƒkS] í‰ë¶9£©¾Ì+?mvÜbNTur­ª´.©ØQª¾Ð0=.ñKÔÉ£N®Å\ šZ‹ò«¥oÔê2¸æEehöé¶Ê <¢JšL½.ƒ+¬ZJ/\ùÓÆÓY¹nùÕµ§Ýze]WP¹u?\éq£P^•nZ’ÀSv…².Ÿ+ë“+.íX¯OÞ¥ä²NÉ皺ªe~õ]«Û;iŸ\¢$ò4ªNXz!³¦.Ë?nŸ>â 7®¨¼ 'jJ2ž¤¥.+8>ޏ‹Ë$ž¯üNjq`Y5I[U—Ä5;>ŽÇ'՞~:¦À@5I[U—Ä–Ý܌«#ýðøçüì±,Jb•”ÎHé뒸¶ç¿ŽiÑ+W ûÖ§”Tܶԏç‡Aº«޸"]:ÎaO9/ÁD-©;x®õá󶟼ék n4qcPFÚº$®ø C[KOzã:ìužoÔÖ.“âIεuI\pÊ~õ‹Þ¸Ž!z£µû/~ˆJ¾X_WÉÕLìÜQ¤‡ñºu_ýq•òAj­Ÿ¼ÍÑëëR¸²ƒ¬·lÆÕ¶¯W®Wy/qÚÌ¢ÕÖ¥p凷nِ«m6Vžã¨LŽ“Îº.é_ˆ>oç2Ú_–ÚÌRÑÈjÑ×%pǼûm\µ,Z?iôdˆ¨KáÚ;æ[ô¢­*…êKætu)\{ǜí||Ÿ\Oa¹TªdÓÖº8®½cÎvõ͸:ó¾î"Õ¨ʇ¢®‹÷Ë;7˜lÿíwpÙÈg»¿hNjRÍ$GU—À•î,pç–ûç:µvV ¥6¨º®½cÞ¹å!¸žD!К¶º®½cÞ¹eC.ì»E³v1h«Kà’O^l>×)ñº›«V—ÀµwÌ{‘lå2ÉÇÞ¾JfUuÅZ®¶º®G òÓúi/\U÷ +‹ºº®GÉð³½c4äJpë‡\mu)\۞N½ã‹êzã +*¶å·réêR¸`Öïâ29w#*­:ßV—•îOÖæ\«öé×¢<™i¹ÚêR¸²“Sï+-÷çºv›ZcÛêR¸òÓl •ËäâþZÿæ´©µÒrµÕíˆç+oےÕ]A®Eç>ìiR?Yl«Ká*½¶?®¸e®Vçj©Kâ8.£sÙyKÕ:WK]WbÎ5Ç¥ÛÔCÿF¬¢¯K⊿é+×+Lƒ+ç®GU)àøTZ¹ŒÞ¿Q]‹ù¾håÒ×%qéÞÏj—«ÔØË¢ƒK[—Ä•}z;—ÑBöÖ]Dڍ“ºFÅð½=‡Bùz½a¾ŠÏð=KÎÃ÷b½p ÏÕýºåirÅÿ°\É$¹º86“ä2™0¿p Ïe4±œ4×|’\ò–+œ$W÷löL¹‚irEÏ0ð5ü>Ž®¸ÖÏ0ðÅ}Ïj’\ðL¹Òg ~¯ÙX¥ëe¯ Ãï¡«t5y…ûÞ@ç©Ô—sT—Ô%†ßË9V‰Q\Ñ䎮Pû½·®¢Ë¾ßSìÚJ[Ô¥Èï•v-àðP\0µ€Cvú[ä÷›;pd8®É}}ÚÙ €‰¶œsÌÐ9lc®Î9æu§ÌF^œs`¢Ó-Æ8çÀ¢Î^¿k¬;씽:æÀòn5”¾86³ÌºÕPþÀ1–v7PÀ1w  Ö±غ;êTé˜Ý"8átKèmœ£sJès„m®gú ¡€S§„A:àª:%ô1¢©€ìZ—„^ L CÑ¥ˆ>êv_O\rBB/1Ò Vè瓑ÃU‰KLGS̈dÈå Æ…ƒ+ôÞTäÐ/seÓD”aAzG"ÄñAúp"r8/s!„Þá”]AzG„cÒ@«§+Â!f_%®t"‘T§ì· À }8 Ùª\¡&!a• ±tãOB6æ5.1 áˆp*øáDÄ!‘ð†ë„pdH/ „+\ŽÙF(‚èÀbv§ +Ìê\AtÀ3c—+  âÜýáµjpÅ`è³ @Xq ¤GŸµ†‚$c0ô;  ÇȬûÑÏ\Âù†O¼’ñŽ=ÀÖèM8Æ`øÈHÎaä–á§R@Š•G`„ÝG ©èÈ!"a +¢pŒ8À(›t@ëçQç`”= ^8æ"GLhutÌEÊR;æˆJŸS {zD¥'­HõÒñ”^PšT%mµM’4 ¨Cs4CDØÒL˵v×iË/PÐØÂQ3,ÇB@vé#bJ3$ ÏpF2Ä5íy݊G1DI ]<ÅÇSâㆂ1ÀFˆqx@Á`¡‹fX™içÁ ?YI© +Î|Ö,¨jk€ œd™‘½¬6° ‹ÉcX]>°rHz‹€5DVFÔ +œéöÐ1‡  à, sd Þ Tê׌ÌÇ3 ÔKÎcîç $ÆÇÜa:\‡±†;peu°õfŽàB*ý@±ž1ð?j˜c† À©ÃtXÄ ë€í‡é°”éL/AƒÈ!Qà¸ÖX°•Ý5CreŽt˜Œ¸A8F†Xûª¥qB Õ, +3Cìuâ,ùV…™!öªõا»@sá ±GéÈ l +SCô“‘5^)^`&°}Zâ­Ç7C-—ôƶÄÜHº 06Ğ4QùP0´=yg´ªWÆÀxÔöãsCkc_ßË“‘¡l'fƲ6}¤`aàÚ÷bw„T®”Ôa6µƒ¢Y!™Kz#ÉÈ|€#· &……›‚%s°P‘Æõ‚ÁE»Ãcùn`)l uÀÂêBÉ*ÌUñʎ‰€ùªE0–>+ë %w²K/U`+J;‚½H Û7ƒÁ¢6™ª«å4Øóü'ëàÙbQo²¹ŠˆVÿ¦sT¹¦ßfÃçJY\žCí,†Å·Å]\Ìó¼ó¤çÎjŸurÅ·à¿tþ^°†qaÂ%=~9GYc~Áûô•—A‡mÇÙe—9Þ3©:¦Ý\&¶G{ÐöuÄþ܅!u¦4ÈˇF¿Éûedò¸ +S®Ü³SÎΗËåë‡Çr¿\^D†Ÿ¶0æ²ÑaÖKWþ#†K:ȵ°Àe&‰£tŽË½[Yár®Ãº—¾p\rj݅ä"ìÚ Q zH®"r‰kc+›Vw¡¹X+=i|b“+w†kQØärFëqÛx.MEãi\Ü%œDƒÆå„t`÷{)\r2VHãrÀÑ[‡$®Ñ-Ÿu@ãÊ'b…T®‘ã_Â6‘kTK¤ä¾P¹ÆôΔí'*׈=)iŽÌ5Ú£¥½Ð¹FbÄÄ2×8CŒ¸·ËàeˆQ³ 8\”ôÀ14ƒÍ5¸vÐSåx\k#É%…»RhÂ5¤(²R‡¹\Áñ2ÉØ\Œ´ŸA—1×@“1扮!ü³Ï=HaÂÕ¿)ò³4¸ú3H>5ãêWM’… ¹útÐF9Ц\ý™%ãs‘s¨{š˜ØçêcÚb˜®n‡Ë¾,šŸ›°ÂUH»¶xiÞ";\¶h¯Ë‚MáW!/Üé,›\–ºì|S¸ÆUÈkc|m«-6¹ø©ÕªK{-±Ëe^HÝ“‹Kf—ª.ÙùkÛm胋˜ï/{xÏE?\å—ïŸßôrûÞ¸v½Öagˇ¾îÝ'×®Û®—gê~º|èó¾}sí;n{Âayq¶-çËååÃCï·„k„ɧWé«;ùêݏÅÕG!'n®ÅÍú퍐?ÿÓCvû£oÄ}¹ÈýÝ·¿ýöËgñðùë/¿ÿãö??}ùåOß~ùõÿ,ÿ÷ñnÄÕÕö®>¼ûA¼¹zÿözû!ۋßäo®Þ®·ß\ݼýA¼¹þ°¿GòÛ¯?}6|ùõç¿üôíë®âMõs~ýÓß¿üòûÿùöØÎ?¼yü×Ç·øƒÈ¶¿ü*²Ï_?ùë矷—&ò‘êÿTMòšendstream +endobj +215 0 obj +6311 +endobj +216 0 obj<>>>>>endobj +217 0 obj<>stream +xÚ+ä2T0BCc3JÎår +ár á +äHÉHendstream +endobj +218 0 obj +31 +endobj +219 0 obj<>>>>>endobj +220 0 obj<>stream +xڕUKoâ0¾ó+F{j¥’m€òØ[)í +©ÝÍ6´ÚcOÀ­§¶býŽPh…ªV ¡dßcÆæ¥Ã9}bt Ûž·Æ³Ö÷›Ä#˜eéz0'1¤\—x:{ª£ѰŽ·/†QÅ0X8™IΜÔEÜƒ8nR;ý:u¶’¬Î܆V. ÿÍ,}!Í«œZAiôZR„¢ŽI…d‘i“‡þ@_·B`†¯¤Cî*êÆ +\ Y,AgžáÆÝ¨ãq}ò•Îsª{ø5ý ‰‘D—2Ó­u˜ÃüäÛÕC’~›ŸÂ#ë!âè<:"º;ډî슯Ѭ%n>Pý1ú«V¥6Ž-Ò»&G±- é¡vÞ¹èÃ°´¡`ê`Åì;Õ DïîUXlášÙ-¤;ÿ£Eŝ§=‡\;r¬#'™{ +V«*ØîY0¥jk,„6Öûþ·²äaÞѽ6?‚Fïc˜ÕÍ3*ÜÒÐòœ^´•,¦ìÐdŒ£š®;C;j]·šú¼ÝÞLRã4׊†9½žÝ´§IBãduú‚YÚ<ϟ ØÒçyð¤A¼TX(аÞɹõ¼ bÂÐÏq~r›LÎàþæ*Ž£ù餴¿CkÙa¬4¦´ônì£á²,Sz‰a¹UBö‹«¬~i«Òo m#Ý + Ҝè!« +îÁ”tÛ£þ0!,-mžk…ÄiaôÆzɞE¢­KÃyÛk:8€t’dB¡M–áÁè÷»rœ+‘d +W `e©š«ÀBU¬—÷ãóԅÉîðâD}ö¡Yß õÍeZ7úRý%ÕÿTšÖÛlëа µ·z]½áy4¢Îþ­¾žµþ´þDgý9endstream +endobj +221 0 obj +738 +endobj +222 0 obj<>>>>>endobj +223 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS046Ò3W072PIÑp rt QÐUp VÎO+)O,JUpI-ÎLÏQÉE™%™ùyš!Y\ººP­F 13=30ßP!89¿ $êÂÈäÀ"wendstream +endobj +224 0 obj +121 +endobj +225 0 obj<>>>>>endobj +226 0 obj<>stream +xÚ­•OÚ0Åï|Š9²Ò&K 7 +l…T´) {ââÆp•ØÔ6Úòíkc•V%]å@Æ¿7ö¼?ZtÌÀ „nòªõ)k=½ÄĐæMЃŒ¶CX`yŽê!ûîJžýÈyϑïÊüÆË$…‰ÈwrM4Ü-èAËþ+Ï6…(KñÎøÚ-¤— )µ.…o{ÐóU]3tàü#?<³Wa×Êm«àç‰ø¡Ó ^°õN:½9ád– IIø5ß4tÄßà³Éäžî•Æ +f\£,HŽ0AÅÖÜÞrɶ糹G"Í­„ÿ³…~'aD+ƙÒf/B*»—)ð¯·PÓ?¤õd~ H±–¤ª¬ w.n¡SÌw’é½±ïVH݀›%·¸ª¦I—˜ßRáÿŒímrûf¨ÖÛ¿Mîœ`ÏE§×)áUoPžb¬þ1Â\pï*Æ +l ™áÙt:…  üÞc° ç›Ý ¡×¶ŸU›JRèÕÃ]ç9K’§ÃÌG”2K$%¼nOèdxÆ^‚fì)ϵ=N!“„«» zbͪmyøÕ²ú¼c›qæ‚byh(Ŋ˜#ÌÕ] ÅËØ<âGøÂ8º1X¬ŒM̵ÈÅÑÛÑqÑÑ{aßúŸéE?6²æU×~žf­¯­_Ð&Ùûendstream +endobj +227 0 obj +522 +endobj +228 0 obj<>>>>>endobj +229 0 obj<>stream +xÚ-‹Á‚0DïûsÔÈ^U䬰~€©[S‹_«f&™ÌLޓÅGŒ²N¶wÚ +­º5˜!\š¼Ac +ÈeÑö›Naw: F7¿ÎQÑêä¯!…þ1û1,åFُÌþh•¶Êp^ãÛ zu5XÒµ:ÒŸ"${endstream +endobj +230 0 obj +125 +endobj +231 0 obj<>>>>>endobj +232 0 obj<>stream +xÚµVMsÛ6½ëWìø$Ϙ”%9úpNµÝtÔÉ$®#÷¤ D.%Ä$ 5þ÷ÝH™bc§j’Ñöë=<ìê±7„sú a:‚ñ’¢wµì >Ìa8‡eF'“é,ÓþnÐÊM ŸŸÐ[‡…·”F#‚St[4´Úʔ)8F¡JÐF–N–pÂ>ØË:©Sfñè%ûj4™Âamý+‘<`™ÚC?*y8&×לÐ<`ŽÏpM5ˆc½¯ÿXgϤ-JG¸E‚ðQ®0ÏG…ø sr?®Ì/ÉÓ*Gsœ—¿>ø»C iæ];´ŸÒ%ìáI­/ƒ­²®L]J'Âê4>DùÚ?Õº' þJ›² ’zï¯ú|C4ÿJö¹Ý[ +õ‰ª¯“Tü-¬U‰¤¾.µ†‚uÔ36ǦZJ—7i¯2òMÂk¥%Ú:㋪“°m𱒆2þoî>ëðnBU½Åjî?Ys|\jtöØôԓг³ê‡@"_ÖÅdtæ{=7÷÷ ³PFV¥r`5&¬¥ôÌûÔoŠÊ:bG¤~×GàÌ¢õñ3£ +oc5*aRjôÞ<ŠˆæÝþA_µ»—œ’ÎüÈ!ç‚“òƒÌ?ë»ÅÍ3jCüÔióä•Gv;Uå)¬¹DE‰¦a§û¬Ÿ}HŽpÒ ‹÷íÔy’Ç£xR·Rj¦dýf¥ó=UÖ£ò4\ú«v  D·Sæ!0ÈÒ3À(ZÐýL"3¸mfð­QN%*Ruà0!’õÕJVCìö´1ªŒŒl¥µ2.ÓRG²[W®uJ¿ÇÕr¾Éÿ,®>ÊOt|#0üu©Ùê0µ Bb¶jYñ¨¸lXš4¬Ðƃ +m‹ì±Â +»è½¤ÛøÇÐ 7IhŒþ¹¢qºç!Qe‰ ÷Š'):.û¸|¿õûq&ç!¿ó`>>>>>endobj +235 0 obj<>stream +xÚµWÛnÛ8}÷WÌcŠÖò-qâ‹EÒn±}(mìCÛŠE¬%R!)»ùûΐ’oIܤÛEØ¡†s9ç̌r×Á~F0™ò¯¬z—óÞàý F“d óœžMÏFü5;š$£äZ%ÊWóodv £Q4ꏧôŒŒæ¶& +¹@ÑŸ:sàùARå +3øfRð”F’im•öhA­Qz2X*±w¥õZë!Ã¥’˜EãL(~Ì7;ºùô”“‡Û¹±ÕyÌu³X•¹¶Ž>Ïäo«ÿ4µWF~?_'Iòu·Ô>_ß.6Z:BCŠ ô=UQ¥J >ß$R–f¥ôm›lݍÏ(‘µ¿/ãé)téFƒ£T4ÙñlܝYáq7­#èÃ5ú3_¶áúÃI‹×nì-Ô ¬¼Û| +äðì@hÝT)ñHUg `/‹Z «üý~\\¢~"*?‚x drA ÿސ&˞ˆHOþ€ÚèGH7–ĵŽðÍې›NíG-MÆÉ´ëÖpUz¸U«ôy}ªÑ¯Œ]@aœ‡ÆqlyvI|DçÄ-Â%µó‚ºÙx#MùV…’Å^‡Rw6Ž\§÷P±³JÈBit`­ÙïG%­q&÷_Æ'SøWé̬ý/ìð*= 8k-*Ü5ØàŽ¾¡‰À†Ž™YvŽª&T,Þ5ÊRÖ †”TnˆÞÍ-a 4oØ@iº +øÝ³£xª< j¸KÓÁ†þ0SÁä?‘uQ××ÑKǏªÊèò>P²Gô7®Jô¾EQ…Í(s\xk´úÞUï~‰—È5ŸÏy²ÿlÚf˜‹¦ôq ´Ã†‚ÎFÃáå“ä¬Cy¯rÐK´ ,ñÞRÍTˆ;÷ÚZ¶ÖŒÙRe4áÁ©ª.±{Ò/I½È…DfàíÍÕ5º&­”¨Ñf#ÔÚMÇLʏ÷ϕ´Q²0º)BMk$U%wÿJù‚„¥œgB¹AV¬;_ˆp³`‚¤É¢H‰ÏÀÃ:Þì…-Ì +¹…I%r#è­­¦çŶ‘ÙFPA¢SeCpª›o¢–¦±4²Ã]0NFPÖò 'ô¼‹‚÷i˜$6öªÈ*¥ Ú{†Ž‚0-c‹xá÷a´ú%Õ¼Ϛ€~ Ö55ËÏí.ö5ÏÝðë)/R3-ojJrÁå*×]«¤× !½Z⾒~¶}Öá2åDJòíÕååI…h\G[SÙA_A»>ªiwÎ<‘à Ó0+ýœ¢óø^Èç;ÝÉÆZJü—!@Ý"pU´®ŸJe©w¥¿Ì+©¬åQ°:ÄïÁ©Õ.¹-8Õ-9Ó¤ÝÑF¨€Ö›a¿,PS??÷³öÒhxL/ÓÙ0™±ÛwŸ.ÞÏÉKh“ën@½C§n5H«Â\a'”Ë89…þéxÈW§|v<áü†ý³ñ×¼÷Oï)~×Çendstream +endobj +236 0 obj +1084 +endobj +237 0 obj<>>>>>endobj +238 0 obj<>stream +xÚ­V]oÚ0}çW\ñÔJ!k€}ÜèǐV‰­™öÒ'q¨»Ä¡¶Cſ߱J;ؤ )Îý:ç_ó܋迈¦CM(-{Ÿãއ›KŠFáâß&³È>fgXÁC±VçñlÆEÞb0œ„ck?rûÒª,™ÌH×I)Œ&FOUBy¥h­„4B®B²¶óË{Úp¥E%©Ê¯—¦Ø’XÉJqM†}Ѩ¿¶c/e?°E µ¯3;ë?bÝæìë>Ukƒˆ:ô…†á¤3² ËShJR¼¬6¨¤’œ€¡DYˆ…µ—åc8k³\ú#ä˜ß.ަ˜ƒ,À¿e†¿°--¤á*g)§‡3¸>œ#UµR¬Ôöa#2:_x2H˜æ Ø0Sk—©P …Zæü÷²@µ«Ì”Lk®={¯½GÛ(ŒZ—£° Ÿ +¡o$Û0Q°¤àmÍÎä–Ö\fˆ«ÄIÆ´Á¼fjm˜ÄšH¡'ØÜÁR͊.4()„èBeB¯ ðlóµ!|2˜iΝ‘•«gîCç{” ü5 Ï5¯Ñ¼ˆÐ@H+4ߛJ ³õ€­—œpŽÉ¶ã !@H?ù!¦¥«Á¬÷aó æ[]1ĊÂݛmDLu´ñì!£NZGIiNêÃQuBí? ¤+âÿ(ä½ý?öCn·«¿ŠD1µ=>¬ËnKÞ¥ÝÿÚÍWԔVrÃ¥à2å}‰ãe@‹%.“«š­°x·¸»h¹¼ò»[1˜|äµL}Ÿkí¥eÚt•›tÿxÏǘó])tÓü#Æ}ë]zæÆªƒ˜9ªÝéaU +TÂP‚6:`¥ÐÈ5ÇiØn§¼ðÇL@+'¿mªüì}5sï•Ïž +›rŠ€¡£ÿ/Ûî:ÓìvªïV€­•<5öљCÓW¬Ðºæ-xWœe”1Ã(WU Þòðx´_0S¸·EØÖ²6kjkJ“\áwõýÓML/‡ûFtÅ5Ng{K•pCÂxßÁtxñæïÂxv^’[ŸÚ÷ë¸÷­÷{–žÊendstream +endobj +239 0 obj +808 +endobj +240 0 obj<>>>>>endobj +241 0 obj<>stream +xÚµVßsÚ8~ç¯ØG2ƒ ÞS. =nš+Wț_„$ƒZ[r%9iþûîJ68ôš¤í܄ɨòj÷û>í}é á þ a<¡/{®{§ó ŽÓ¬sü6™ éQôÇéY:†År óZs¯Œv'ëOh}Ãa´MF“ôŒl×;,óÆ*kûÞ@É4ÛFC+¿ÔÒyÌ3`ZóÞªMí¥àG&+Wá^é ·¦Fñ1j+úNÚ{iaÿƒUþ‰ë‘A´I#ò.Ïd>>>>>endobj +244 0 obj<>stream +xڍVËvÚ0Ýó³lÏ)N ”$Ë6é#«Ò†~€Ç [r¥qRúõ‘dB)käû˜«1?G%\ò§„« Lç ÛÑûåèâ㠔ÓbËš×æ×¥\V¯¦Å[¾0­Z#¹.¼^þàÊ”eªOæÅLê–|®‚Ú4„´³è)¤¹‹|mÉÁÂzÐÞtT¤G§“b>€O¡ g‘SÉklˆ¨g,ôãС6µŅ̃m•­¸Ð»‹»L‰ïA‡¾v¾å]™*ï4v *€ÇŸ=ÂJ80rbZ½Zm¼g´s*f@ø‹ÎêŠþ1PÎù÷¶¸oÒ#§LàAo°êô'ÃP†í€ºoší¸î­&ã¬jàór¹¸(‹X+3b݊€½d¯B4!{ހnTÈâê·ÆRr`^ز£m÷ª 6\{Á´]ƒ°òNUZ¯TÀ +*ãQ“óÛÈÁh&폭£L¸U}nifZÙÃÎ!(­1ÈsÉ+:åÑR³MÉAÓ¬;³<ÙÝ9Ûò®§óæ·¿N:­ö+¡u⺘î1tγâŸÄ!1‚‘ª„¼k¢4y +6:=F6¨&µIÖäÞ/Cˆ ÍÉ•ÿ§o·ÉʓÊ»_Ö#Ð9-»-)!ø ô&­¥8j×4£®>ЖúĚ/`? ÆŽðŠi󨪒'o(gx—gk³î}ö–OÝ9ƒ¦lacÏø#%'ìÙu0WʸêmîqˆGe8%a§¬XÉ Š;ÿŒ§èA­t<‹¡Ž¤žÅÙäeƒw2 É<¹žoJædƒ±ÌC."µ!Féx´/çÂ(N¬•cêîömÙ·#våˆ'ø uOC\y +¢—ytûéþ”¯½âùÍÛ"Vr²„¾ëœ'xÂU#9yNí¦RÔKH¬á!ÀEZøÅêçӋ՛خ¿NÏq„’bŒ‹IÞ¹üÌàv?s§côW:_N“D|ðíöûâáH¬£xjÌï\|à«êØY6Mñ¹ªñx&ßkê}²ªaõ¹¥Ç¨ÅΦ÷s¤‘§w€2MÜçyýaF&_ŠlAÕßGxLßF Ú’›pm-¹W0ŸMSî¾½û¸„qâøàjz’vÞa0k+_ñe›{3N{ÇW“Ëþ#Í®/‹ˆ«7òûÃrôuôHÆendstream +endobj +245 0 obj +911 +endobj +246 0 obj<>>>>>endobj +247 0 obj<>stream +xڕVÁ’Ú8½ó}$Uƒƒ!™c6l6³U[Å̞r²Œ•µ%G’¡øû}mÉLÂ&ÔLFju¿÷úµÌ—QNSüå4_ð¿lF¿mG¯?

Ïf´-±·¸Ïù±ϳEö–VÚ)¬;ÑF¹ƒ–Ê¿Ú~Ƒ7”çñÀd¶ÈÞðm¥¨8‡ûN-ºZá»)< S"´:`§uÚåÈiSZ׈ ­!{À² ³¢ÂòVþ«BFOª±A1Ž ‹qʳËZxäÂ)]°œQŠº>‘( +UP°d04¨QPélCÀk‹ 3¢s"ªµHæÉ(…ãY*ýsœ¥ƒÒ‰òmÆ^›=>¯ÖÔZGÅ[:\æÜ/ú€UÓÕA·8 žNE @ƒÓ\ø¶ã“ù,[ _Ðãz}µÅØøU(P£/9õ¥S½V(*$?Hi]Á„N=?=ÒAÔºˆt5¶ko©UŽ5@'*åÔãP^+ó=¾­U.†,‚9 sê3##7‘õ‡VŸÆÇJˊ½¯`]—jû`‚4$­ ÎÖìx¤B5x$ö¡ä¸‹Ú·ÛuJž}zuCÁ%ýiw×§ä3 aÄ~†~çŽíÁM+u=˜q'à2ö²Å<a78«¸ë£k4 é/h°ë:F‚¾d2¿õ*•ò_×ò·¬rO m®m0EËaËÖ¯wøÊøƒn`²]è Ú·"Ȋ״iÓ*vù‘ã£1¸{‡vùŒCï¤ ªGΓTÒFÚ¾N„:MPǛÇ?>>_x} »ì ¦›ªÆ€ù¯½…Ú¥Þw.º²©_®Z§«êªjçûìÇÊõ®aNßÜ}ëõ*AÒi Np~“Ñw²^ÖO£S"ÝÑG§ƒŠÄÏçþOý…ï[¸!ñ}ˆDæ„M_žþ¡÷¶ââ:ís´LÑìö¦W‚³»Î‡agRkÃ×'`•B*÷Ïë ún×èhœaÈ_&ëz–YÞßm¸ +3† P(¨ºNãXY×ßL1ʨcœRnšoñ(µæ@l{®± ·z”M—ºÝ§‚9@-i±˜£(ºzz÷aK“h‰-Ñù­O6H§[¶0'™Ä³“ålÊGó)/ΗSðÞúôûvô÷è?¢÷†endstream +endobj +248 0 obj +920 +endobj +249 0 obj<>>>>>endobj +250 0 obj<>stream +xڅTQoÚ0~çWœòT$È À»1´>L¢#l/}1ɅºsìÔvZñïwgCDÙŠtI|ç»ï¾ïì×^·ôd0Áx +EÝû’÷>-?C6NGWä›Î3þ,oÆé,j±UØÏ_(lYƒ†£)ù((ÆC¦®….Á£R<9\ñŒe«Ð‚7༰+µ—z/fëÀè×`!+‰et£ui,xŠk8¥Ó#®;PÍELªéð¸v[Kïºw%’5¶“ÂF+ù#O›„-a½wkøu’kmˆ„Pɯ¼ùºY­Ok¾K¥`‡­ðț°á“Ú†‡E¨Ž¢x`¨¬ð Ý¡û2…{åÌ  Y%,¹’*@òÍ*œUOÖ´Îe“}¦ñÒhÂR/”]{µ¹ÓÆRæ+´N©QÖR_á6Ät͒;<·ðÚbK¿ì*”p] +ùi/÷ÜÆ’Í›‡® yd³þ·¿œ×7l~³ \(65ÃÆ±ñGڏ(`ñ!é˜<»æ‡bá™Áøn¥Zü¼_æ0 *мUþ•Z £À¯ÂÊ 9'ƽÃÙèö×Ýd6¡ƒ+Ëxá[Þ{ìýt_‘"endstream +endobj +251 0 obj +601 +endobj +252 0 obj<>>>>>endobj +253 0 obj<>stream +xÚ-‹A‚0D÷ÿ³ÔE+¿EêVEÖ*ß S£E‘ÄëkÕÌ$“¼É{#û„a‹ÔöF+¡Yµ3¤[£œÉ §I¹_V…õa[£î»ñÕ ¥†sLÓá>†>NåBêgª¿Ê&ÁÜzŽ/°Úé>6Ç«O×FhGo³Ó#Ûendstream +endobj +254 0 obj +126 +endobj +255 0 obj<>>>>>endobj +256 0 obj<>stream +xÚ+ä2T0BCs#c3…ä\.§.}7KCK…4 Œ™¹‰BHІ‰‚KjIbfNj +Qœ™ž§’Tg¡`hQ§‹O¡‰¹‰žPPÞÐ$àÂÈe!endstream +endobj +257 0 obj +94 +endobj +258 0 obj<>>>>>endobj +259 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS046Ò3W072PIÑp rt QÐUp VÎO+)O,JUpI-ÎLÏQÉE™%™ùyš!Y\ººP­†& A=#°€ PCIbfNj +Ԑ¼kW ~ö&;endstream +endobj +260 0 obj +126 +endobj +261 0 obj<>>>>>endobj +262 0 obj<>stream +xڝTÛn£0}ç+æqû-)¹=fQ’Fªº¬ Ò¾ºfBÝøBm§Qþ~Ç¡•öR,í +„€9œ9ÇsÌk’à 9Ì'p;®’¯Mr½YB¾„fO•Ù¼€¦ý²‚­4Î1{¾j^À4[ tºÈP–CƒV¹3ƒ<âM'³R¥â“Ò +¸QýÑ£Étwdf¿¥¿Â{f™”(Ç kÔ­Ð 9Š·ðÐ2Ï@‹àŸ™&ãO£¼Pñ†¢Ç˜z£1=±sp¡ŽZpæ…Ñ8µÑ(á ý Qƒ?è­é,S.ÖΡì¿Üýƒ'gø}Ìɽ¸Ò$ßØÃˆ»ìÏT¤”§ôvù‘‹ ¬¸5ú‹Æª.w»ˆE Âidµgºe¶…Ò´{ò¿ÓtUEtO +ª:Œø.«z¼UI‰êña÷*+´K[ŸGá\×åu5Nº®êoŸˆ¿4@ë"̛&»¡±L»=6ã 72ÂvW¥Ûûq¾;­?¡[ËúgÁÜ¿oÊáÓÅut±  ÿõ—(æ…á&òix±n’ïÉOÇ^8Tendstream +endobj +263 0 obj +425 +endobj +264 0 obj<>>>>>endobj +265 0 obj<>stream +xڝ’ÝRÂ0…ïû{©­´@©—ü´# ¢C¨‘’h@}z“ª08ӈN{µgöۜ³ûâ…Ð1_ÝØþt㍰w•ņ€W¶'½ ¼¼¸A>Ï/ñ“Ñ{Gݏâ ×èl_1­}D蚨% Ņf +ÆRh%+˜QnIÉ> ßü„1ûLj™|8?MqÖŸZ”`RQrÁ˜a—€I½†L*êä"t¶y¬e"%µ¤²r‹ÅoD¢¹¤‚B±4aÔ°P%ü½ì9š´³çÆù!Ö a'*Ÿæi;+ßVšoؒ8„^AúJͶ\‘:/ ™5ÿ嬐Ë1’µ.¨âÏúè›ÕMÁc‘Ú©S;CÊY]Ûǎ*I×ΰ㄰â;nVñŠVDÔ+Ã>=£ä«/îè'×Al;'wà ƒã{T@!WzO³þx)~ÚôÃndzýAÔ±­al‹½0 úІACª¤xÛÔVJ±wë}ûì'endstream +endobj +266 0 obj +380 +endobj +267 0 obj<>>>/Annots 117 0 R>>endobj +268 0 obj<>stream +xÚݛÛrÛ6†ïý¼l/Âgâ2±ãԝdâØêÈ2m3Ñ©”œÔ}úâ° ‰õUD7QYò£ø/°‹ÃêïRTæ?R(Z0Y,V'ïg'oÏuAt1»+ˆd%-¤æsvûÛl~³lŠÍ]qºYï›õ~÷ûìÛɇÙIUV†b?ˆý¸úh…dµ¹mUØOÿ÷²¸¶üƒË»ûâí¹(±O´·iÿ4RŒâäª`¢¬S¾·åz±Ù64P*x*æqæ’ròÿȨLZ¥©0Ÿ«BÐR@##5©¿%•Né2£u]™;‰U;~ØèâÖôŠö®]Ì÷ífý¼êB•jJºcÚº7ںƨ¶VQBÍNSŠi +äZ•2%ƒH×O»}³Ê †á~ã Fú/†ƒ·íˏ¦ûÑ6?Ÿw'¥ž„s¯]›—¯øFÎ+Bëz:C¼Ȥ²£"AƒPg›ÅãÊt÷q^Œ0@ÎKžÃ@D\CM:²kH6à Eû€ïÿ~QÀŠùPMó?à…•+á{+P®š»¦k֋f7¢£žVüyæC:¿Q ÷¾ñ²p/¤{oІûð„ڍä Þì9§]^g\6Ük:¿¨¬Ób’·{RK™´!åq†ù„‹!MøF6 qéÃ1EÓD ו‰] Ì@ú²hºŒ;†Ûm–¨l,Ša`XpÈø¢“C,ˆ6¯ Éýý²€D­:æåÏ]OŽùÎ(gÍ®½_£¢ÛÍW­ûï ,o04GL3¶ dôT҇v×£]ã…­R>ê3<¦Á3´°=~˜ô~¾øÞ¬ow£$:=…Çå5i²2Õ¹(¬íèöQyÍBk’æD`v]P¢ÁîPívû¼œ„•“Z„aB*íâ§7×È +YW>œZ))&%°AÊîí¶ÜÞþ?ĔÒMŒýÛ¹FVL©ü4يÉ01M¨í%p°l;ïæËe³|^Q6•xŠI)˜ËþÝ\#+¥àe?Ä9&%° µS¸v€íš®Iízt*]S"bòÊ' +÷v®‘Ó¥S`b›abk;Àv«›‘A.'•€0-©Š2kdµ¤}¸”˜’@&”—:EƒÝ¡v“Í÷#R™82 )e~~ÄMhïW¾‘[]pÂCÞÁV¬Eÿ˜xVԓÞ7Ý÷fÙì2I†6ßȅ]&AGl9p•}%\0;ÎéNjÑ)À”O®°îÉÕ°†òl÷4ÙrCCg`—Ú8ضXÎw»±bVMC]LHƇäY!™9ˆáQØ~žšÀÁ°o››Ý«˜¨bbR¥ ×ȊIiHA šÀö»® ìÛvízßt»ÑÅè4ÖPXÔ¬êa3Ï7²Q³Ò!ÿp,nÙ$d0ée—2eXÖ#wóE“9ç‹ö¨CÀüÔÞtóîiÔËüˆ^F† ÕbXÏùFn˜P ‡£¡;‰f=— Á.ýÊaý£Y·ö|/㐈±*he6b¸À!Ï× {î4¾ãûKW#˜j2¤OßÈz ¦!}r4ê6q«év€ý1›]æÆƒŠ¾(Q6ê%0sÁÀBå?ÒhÀü ë!ûúFÖR—ýXÀF`ÛìËS8Øvq™sCt·Wõá  Ç<‚­w1äoßȺÃ܁í€6áÔFv€}š¯ïç÷¹È! °–62ÅÀp§èÌœËOßÈz‚³>ý£Û§m·õy +;À>_|þ PÃí6@ÑÃo.ÚÄ2ÄË]Au”­©Æ²5«‚#°Ý×@&Я$ho÷¨Ë˳\|î]¹RS’’àÂ|pÌÉ1æ"¢”M–²‰R¶Âl›se +;À®æ»}®>$Ø1Aú/>$mw|Yڶޜؘp«ZÑ¡rÐ7r«Z±·²: äÚnØ&d0é¼]Ž/ò¨šìÞÒËI­‡ ì¹^Nt(²)º8lâ6"¸·ØÃö~¹ßlÇVÐbâbJ*9dPßÈ*©úNñÛÎ3ªv€µ+3‘—’³ lFhDG•½øFVGÙ÷Gl‚Èþð1AƒÝïçìÆ¤j2Ûc˜Œ<*zñ¬Œ¢/zèÔ:°mÙºLáÞ`ûæŸ}f`OekLç“arH>¾‘K>„õ%/I>¬å!Ì@º^<4·Ë¦{MåmX¥Qõ‹od;(í«_$žy€mwõt +;ÀÞ=î6]ûo®„¹:ê¹6¦"‰Ê^|#«"éË^$žu€m×Up°ì4{.3ýQî”ÔQ͋ÆJ^tDĒŽ/6èÃzÏ9]¶Íz¬Ü…Ogj‰(X³!ãÔ I8u_ì"Ñ|`»&²·öå)ë»öþ±Ëe:ݱ¬¢ê…§¨¾6E¢0&&O¨„ì­@:k»f±ßtO¹°ž`W›µ ®1ÌÀ»¶5ï£?èqk‚_î +Rå] ¢’U´ˆzÈHØÖ € ¡îgPù(../_C‘0¦"çq)&V‰)†Œ¤ÐBL¨c±q—–±ҟã§Û“©bÁ$ddÈFŒ وõÖØ¡6lT…g¤GÚnvÞ®G끧RSåõ{{^ïJˆí ²ö?ƒºzw>+Þî@ùzs·ÿ9ïš~Ðcþ·èÚmÈLØßξQÔ½V ê}=ù41ž×endstream +endobj +269 0 obj +2170 +endobj +270 0 obj<>>>/Annots 149 0 R>>endobj +271 0 obj<>stream +xÚ՘Ms›0†ïþ:¶‡(è8ºIkšÐÞ)&2`»ÀL'ÿ¾+i1à‰Dn¦q{gÑ+ô¬V+ñgÃHF„6ÿE³ù–mnw)a)É^ӂr¢c×lÿ%Ë×%9¾»ã¡/}÷5{Û|Ï6@Å\˜¹<=˜Óˆh‘@»†¤š&hÔäÙôpÑ }%·;I3}ÆÐ¡H]‡‚jšo/á†0ÁÎ}b7èG±Ç¶‚§níCZ>€à4p½æ‹¼£ڌ+¸6DqªÐð2…€j®ÇØOq"Ր$¦z®‹n«óüÞõe㗚´†°'TÌ¥Ðm¥~Â:6„°Êär¤è·2wǦÉ{OPe|å ÂéR„1˜¢CŠXÃN“ŒÃ. ”-%j3./ÅяbyQ”§þc‚<†ä¹~Z,“T0+ô@Ò!’*Mé0Â0ÉAۑœ‰£ŊüP”õÿN2QTžIZ#H2Ñp’K$Q›t.Ž~ÛW)6žµ:ZÈEŽp=—?g9Æb(z10XàˆÚ ÖE5G?Š•?FnⵊÉHªÔU;4kIêhਖ8¢2‹°˜I;¿“ªOLVï³¥k3‚¥k^âˆÚLðKqô£X}Ê÷Muð䵙ÌW'ºÈÆ8Vk9 +1Všx‰#j3Á÷Lý(VŸº>÷Õl¶Š­ì§X²tRk¬d Xε&Yb‰Ú xð¹¸óbmùV~–ÉúY‚Ad*Üë~[ +[¦™e(8£ ;"ØvÎԝ×jܗ}^Õå>pԛÃ2Ø̴Ѝb]õêY'x +-W´òŽ!áií²;‚u†7FæîØåúÖt¢dτ|.‹nÔy¨]—·ïžÅ7¥l•P§|Uøt,•°)¯¤™ZÖøÄ8'Kha§Ý6t¬šÈÂôç‡éëܨ”•mÓy7^ÉQ/║ÝuºZ#ôòAJæ6¡ÛÐ k"f2#43iôRE{<¼ûÀJ¹’íÒÛ]2Ì5['n7tÿ´Ýeä†Üý||&ÏǗþoޖÄ-}æ«h«S_í2xÃì+ª›˜ÛVý±ùõÖñfendstream +endobj +272 0 obj +837 +endobj +273 0 obj<>endobj +274 0 obj<>endobj +275 0 obj<>endobj +276 0 obj<>endobj +277 0 obj<>endobj +278 0 obj<>endobj +279 0 obj<>endobj +280 0 obj<>endobj +281 0 obj<>endobj +282 0 obj<>endobj +283 0 obj<>endobj +284 0 obj<>endobj +285 0 obj<>endobj +286 0 obj<>endobj +287 0 obj<>endobj +288 0 obj<>endobj +289 0 obj<>endobj +290 0 obj<>endobj +291 0 obj<>endobj +292 0 obj<>endobj +293 0 obj<>endobj +294 0 obj<>endobj +295 0 obj<>endobj +296 0 obj<>endobj +297 0 obj<>endobj +298 0 obj<>endobj +299 0 obj<>endobj +300 0 obj<>endobj +301 0 obj<>endobj +302 0 obj<>endobj +303 0 obj<>endobj +304 0 obj<>endobj +305 0 obj<>endobj +306 0 obj<>endobj +307 0 obj<>endobj +308 0 obj<>endobj +309 0 obj<>endobj +310 0 obj<>endobj +311 0 obj<>endobj +312 0 obj<>endobj +313 0 obj<>endobj +314 0 obj<>endobj +315 0 obj<>endobj +316 0 obj<>endobj +317 0 obj<>endobj +318 0 obj<>endobj +319 0 obj<>endobj +320 0 obj<>endobj +321 0 obj<>endobj +322 0 obj<>endobj +323 0 obj<>endobj +324 0 obj<>endobj +325 0 obj<>endobj +326 0 obj<>endobj +327 0 obj<>endobj +328 0 obj<>endobj +329 0 obj<>endobj +330 0 obj<>endobj +331 0 obj<>endobj +332 0 obj<>endobj +333 0 obj<>endobj +334 0 obj<>/Outlines 273 0 R/PageMode/UseOutlines/OpenAction[219 0 R/XYZ null null null]>>endobj +xref +0 335 +0000000000 65535 f +0000000015 00000 n +0000000224 00000 n +0000000285 00000 n +0000000359 00000 n +0000000441 00000 n +0000000519 00000 n +0000000596 00000 n +0000000675 00000 n +0000000751 00000 n +0000000832 00000 n +0000000891 00000 n +0000000994 00000 n +0000001098 00000 n +0000001203 00000 n +0000001308 00000 n +0000001413 00000 n +0000001518 00000 n +0000001623 00000 n +0000001728 00000 n +0000001833 00000 n +0000001938 00000 n +0000002041 00000 n +0000002145 00000 n +0000002250 00000 n +0000002355 00000 n +0000002460 00000 n +0000002565 00000 n +0000002670 00000 n +0000002775 00000 n +0000002878 00000 n +0000002982 00000 n +0000003087 00000 n +0000003192 00000 n +0000003297 00000 n +0000003402 00000 n +0000003507 00000 n +0000003612 00000 n +0000003717 00000 n +0000003822 00000 n +0000003927 00000 n +0000004032 00000 n +0000004137 00000 n +0000004242 00000 n +0000004347 00000 n +0000004452 00000 n +0000004557 00000 n +0000004662 00000 n +0000004767 00000 n +0000004872 00000 n +0000004977 00000 n +0000005082 00000 n +0000005187 00000 n +0000005292 00000 n +0000005397 00000 n +0000005502 00000 n +0000005607 00000 n +0000005712 00000 n +0000005817 00000 n +0000005922 00000 n +0000006027 00000 n +0000006132 00000 n +0000006237 00000 n +0000006342 00000 n +0000006447 00000 n +0000006552 00000 n +0000006657 00000 n +0000006762 00000 n +0000006867 00000 n +0000006972 00000 n +0000007077 00000 n +0000007182 00000 n +0000007287 00000 n +0000007392 00000 n +0000007497 00000 n +0000007602 00000 n +0000007707 00000 n +0000007812 00000 n +0000007917 00000 n +0000008022 00000 n +0000008127 00000 n +0000008232 00000 n +0000008337 00000 n +0000008442 00000 n +0000008547 00000 n +0000008652 00000 n +0000008757 00000 n +0000008862 00000 n +0000008967 00000 n +0000009072 00000 n +0000009177 00000 n +0000009282 00000 n +0000009387 00000 n +0000009492 00000 n +0000009597 00000 n +0000009702 00000 n +0000009807 00000 n +0000009912 00000 n +0000010017 00000 n +0000010122 00000 n +0000010227 00000 n +0000010333 00000 n +0000010439 00000 n +0000010545 00000 n +0000010651 00000 n +0000010757 00000 n +0000010863 00000 n +0000010969 00000 n +0000011075 00000 n +0000011181 00000 n +0000011287 00000 n +0000011393 00000 n +0000011498 00000 n +0000011603 00000 n +0000011707 00000 n +0000011811 00000 n +0000011915 00000 n +0000012019 00000 n +0000012796 00000 n +0000012902 00000 n +0000013008 00000 n +0000013112 00000 n +0000013217 00000 n +0000013323 00000 n +0000013429 00000 n +0000013535 00000 n +0000013641 00000 n +0000013747 00000 n +0000013853 00000 n +0000013959 00000 n +0000014065 00000 n +0000014171 00000 n +0000014277 00000 n +0000014383 00000 n +0000014489 00000 n +0000014595 00000 n +0000014701 00000 n +0000014807 00000 n +0000014913 00000 n +0000015019 00000 n +0000015125 00000 n +0000015229 00000 n +0000015333 00000 n +0000015438 00000 n +0000015542 00000 n +0000015646 00000 n +0000015750 00000 n +0000015855 00000 n +0000015959 00000 n +0000016064 00000 n +0000016330 00000 n +0000016364 00000 n +0000016398 00000 n +0000017221 00000 n +0000017270 00000 n +0000017319 00000 n +0000017368 00000 n +0000017417 00000 n +0000017466 00000 n +0000017515 00000 n +0000017564 00000 n +0000017613 00000 n +0000017662 00000 n +0000017711 00000 n +0000017760 00000 n +0000017809 00000 n +0000017858 00000 n +0000017907 00000 n +0000017956 00000 n +0000018005 00000 n +0000018054 00000 n +0000018103 00000 n +0000018152 00000 n +0000018201 00000 n +0000018250 00000 n +0000018299 00000 n +0000018348 00000 n +0000018397 00000 n +0000018446 00000 n +0000018495 00000 n +0000018544 00000 n +0000018593 00000 n +0000018642 00000 n +0000018691 00000 n +0000018740 00000 n +0000018789 00000 n +0000018838 00000 n +0000018887 00000 n +0000018936 00000 n +0000018985 00000 n +0000019034 00000 n +0000019083 00000 n +0000019132 00000 n +0000019181 00000 n +0000019230 00000 n +0000019279 00000 n +0000019328 00000 n +0000019377 00000 n +0000019426 00000 n +0000019475 00000 n +0000019524 00000 n +0000019573 00000 n +0000019622 00000 n +0000019671 00000 n +0000019720 00000 n +0000019769 00000 n +0000019818 00000 n +0000019867 00000 n +0000019916 00000 n +0000019965 00000 n +0000020014 00000 n +0000020063 00000 n +0000020112 00000 n +0000020341 00000 n +0000020493 00000 n +0000026875 00000 n +0000026897 00000 n +0000027010 00000 n +0000027112 00000 n +0000027132 00000 n +0000027273 00000 n +0000028082 00000 n +0000028103 00000 n +0000028216 00000 n +0000028408 00000 n +0000028429 00000 n +0000028570 00000 n +0000029163 00000 n +0000029184 00000 n +0000029297 00000 n +0000029493 00000 n +0000029514 00000 n +0000029664 00000 n +0000030677 00000 n +0000030698 00000 n +0000030857 00000 n +0000032012 00000 n +0000032034 00000 n +0000032165 00000 n +0000033044 00000 n +0000033065 00000 n +0000033206 00000 n +0000034316 00000 n +0000034338 00000 n +0000034469 00000 n +0000035451 00000 n +0000035472 00000 n +0000035612 00000 n +0000036603 00000 n +0000036624 00000 n +0000036755 00000 n +0000037427 00000 n +0000037448 00000 n +0000037561 00000 n +0000037758 00000 n +0000037779 00000 n +0000037901 00000 n +0000038066 00000 n +0000038086 00000 n +0000038199 00000 n +0000038396 00000 n +0000038417 00000 n +0000038557 00000 n +0000039053 00000 n +0000039074 00000 n +0000039205 00000 n +0000039656 00000 n +0000039677 00000 n +0000039832 00000 n +0000042073 00000 n +0000042095 00000 n +0000042250 00000 n +0000043158 00000 n +0000043179 00000 n +0000043234 00000 n +0000043339 00000 n +0000043483 00000 n +0000043589 00000 n +0000043709 00000 n +0000043818 00000 n +0000043967 00000 n +0000044077 00000 n +0000044184 00000 n +0000044338 00000 n +0000044474 00000 n +0000044571 00000 n +0000044681 00000 n +0000044796 00000 n +0000044909 00000 n +0000045019 00000 n +0000045119 00000 n +0000045277 00000 n +0000045374 00000 n +0000045484 00000 n +0000045582 00000 n +0000045726 00000 n +0000045827 00000 n +0000045938 00000 n +0000046040 00000 n +0000046203 00000 n +0000046318 00000 n +0000046439 00000 n +0000046559 00000 n +0000046684 00000 n +0000046805 00000 n +0000046925 00000 n +0000047035 00000 n +0000047183 00000 n +0000047285 00000 n +0000047401 00000 n +0000047514 00000 n +0000047616 00000 n +0000047766 00000 n +0000047873 00000 n +0000047987 00000 n +0000048100 00000 n +0000048220 00000 n +0000048345 00000 n +0000048455 00000 n +0000048566 00000 n +0000048677 00000 n +0000048779 00000 n +0000048924 00000 n +0000049024 00000 n +0000049137 00000 n +0000049251 00000 n +0000049364 00000 n +0000049473 00000 n +0000049587 00000 n +0000049700 00000 n +0000049800 00000 n +0000049918 00000 n +0000050052 00000 n +0000050149 00000 n +0000050249 00000 n +trailer +<> +startxref +50435 +%%EOF diff --git a/doc/sdd.shtml b/doc/sdd.shtml new file mode 100644 index 0000000000..edeb368070 --- /dev/null +++ b/doc/sdd.shtml @@ -0,0 +1,563 @@ + + + + + + DRAFT - CUPS Software Design Description + + + +

Scope

+ +

Identification

+ +This software design description document provides detailed information +on the architecture and coding of the Common UNIX Printing System +("CUPS") Version 1.0. + +

System Overview

+ +The Common UNIX Printing System provides a portable printing layer for +UNIX® operating systems. It has been developed by Easy Software +Products to promote a standard printing solution for all UNIX vendors +and users. CUPS provides the System V and Berkeley command-line interfaces. + +

CUPS uses the Internet Printing Protocol (IETF-IPP) as the basis +for managing print jobs and queues. The Line Printer Daemon (LPD, +RFC1179), Server Message Block (SMB), and AppSocket protocols are also +supported with reduced functionality. + +

CUPS adds network printer browsing and PostScript Printer +Description ("PPD")-based printing options to support real +world applications under UNIX. + +

Document Overview

+ +This software design description document is organized into the +following sections: + +
    + +
  • 1 - Scope + +
  • 2 - References + +
  • 3 - Design Overview + +
  • 4 - Detailed Design + +
  • A - Glossary + +
+ +

References

+ +

CUPS Documentation

+ +The following CUPS documentation is referenced by this document: + +
    +
  • CUPS-CMP-1.0: CUPS Configuration Management Plan +
  • CUPS-IDD-1.0: CUPS System Interface Design Description +
  • CUPS-SAM-1.0.x: CUPS Software Administrators Manual +
  • CUPS-SDD-1.0: CUPS Software Design Description +
  • CUPS-SPM-1.0: CUPS Software Programming Manual +
  • CUPS-SSR-1.0: CUPS Software Security Report +
  • CUPS-STP-1.0: CUPS Software Test Plan +
  • CUPS-SUM-1.0.x: CUPS Software Users Manual +
  • CUPS-SVD-1.0.x: CUPS Software Version Description +
+ +

Other Documents

+ +The following non-CUPS documents are referenced by this document: + +
    +
  • IEEE 1387.4, System Administration: Printing (draft) +
  • IPP/1.0: Additional Optional Operations - Set 1 +
  • IPP/1.0: Encoding and Transport +
  • IPP/1.0: Implementers Guide +
  • IPP/1.0: Model and Semantics +
  • RFC 1179, Line Printer Daemon Protocol +
+ +

Design Overview

+ +CUPS is composed of 7 software sub-systems that operate together to +perform common printing tasks: + +
    + +
  • Backends + +
  • Berkeley Commands + +
  • CGI + +
  • CUPS Interface Library + +
  • Filters + +
  • Scheduler + +
  • System V Commands + +
+ +

Backends

+ +The backends implement communications over a number of different interfaces. +All backends are called with a common set of arguments: + +
    + +
  • Device URI - the Uniform Resource Identifier for the output device + (e.g. parallel:/dev/plp, + ipp://hostname/resource). + +
  • Job Identifier - the job identifier for this job (integer). + +
  • User Name - the user associated with this job (name string). + +
  • Title - the title/job-name associated with this job (name string). + +
  • Copies - the number of copies required (integer). + +
  • Options - the options associated with this job (space separated + option strings). + +
  • Filename (optional) - the file to print; if this option is not + specified, the backend must read the print file from the standard + input. + +
+ +Backends are named using the method of the URI, so a URI of +"ipp://hostname/resource" would be processed by the "ipp" backend. + +

ipp

+ +The ipp backend sends the specified job to a network printer or host using +the Internet Printing Protocol. The URI is as specified by the +printer-uri-supported attribute from the printer or host. + +

lpd

+ +The lpd backend sends the specified job to a network printer or host using +the Line Printer Daemon protocol. The URI is of the form: + +
    lpd://hostname/queue
    +
+ +

parallel

+ +The parallel backend sends the specified job to a local printer connected +via the specified parallel port device. The URI is of the form: + +
    parallel:/dev/file
    +
+ +

serial

+ +The serial backend sends the specified job to a local printer connected +via the specified serial port device. The URI is of the form: + +
    serial:/dev/file?option[+option+...]
    +
+ +The options can be any combination of the following: + +
    + +
  • baud=rate - Sets the baud rate for the device. + +
  • bits=7 or 8 - Sets the number of data bits. + +
  • parity=even - Sets even parity checking. + +
  • parity=odd - Sets odd parity checking. + +
  • parity=none - Turns parity checking off. + +
+ +

smb

+ +The smb backend sends the specified job to a network host using the Server +Message Block protocol, which is used by most machines running Microsoft® +Windows®. The URI is of the form: + +
    smb://hostname/queue
    +
+ +Usernames and passwords required to access the printer are stored in an +external file. + +

socket

+ +The socket backend sends the specified job to a network host using the +AppSocket protocol commonly used by Hewlett-Packard and Tektronix +printers. The URI is of the form: + +
    socket://hostname[:port]
    +
+ +The default port number is 9100. + +

Berkeley Commands

+ +The Berkeley commands provide a simple command-line interface to CUPS +to submit and control print jobs. It is provided for compatibility with +existing software that is hard coded to use the Berkeley commands, +however since printer options cannot be specified using the Berkeley +commands their use it not encouraged. + +

lpc

+ +The lpc command allows users and administrators to check the status and +control print queues. The version provided with CUPS supports the following +commands: + +
    + +
  • abort - Stops a printer or all printers and any active print jobs. + +
  • disable - Prevents new jobs from being submitted to the specified + printer or all printers. + +
  • down - Stops a printer or all printers after completing the current + print jobs. + +
  • enable - Allows new jobs to be submitted. + +
  • start - Starts a printer or all printers. + +
  • status - Shows the status of printers and jobs in the queue. + +
  • up - Starts a printer or all printers. + +
+ +

lpr

+ +The lpr command submits a job for printing. The CUPS version of lpr silently +ignores the "i", "p", "t", "m", "h", and "s" options. + +

lprm

+ +The lprm removes one or more print jobs. + +

CGI

+ +The Common Gateway Interface (CGI) programs provide a web-based status interface +to monitor the status of printers, classes, and jobs. + +

classes

+ +The classes CGI lists the available printer classes and any pending jobs for +the class. The user can click on individual classes to limit the display and +click on jobs to see the job status. + +

jobs

+ +The jobs CGI lists the queued print jobs in order of priority. The list can +be limited by printer or job. When the user displays the status of an +individual print job all job options are displayed. + +

printers

+ +The printers CGI lists the available printer queues and any pending jobs for +the printer. The user can click on individual printers to limit the display and +click on jobs to see the job status. + +

CUPS Interface Library

+ +The CUPS interface library provides common convenience, HTTP, IPP, +language, MIME, PPD, and raster functions used by the CUPS software. + +

Convenience Functions

+ +Convenience functions are provided to submit an IPP request, send a print file, +cancel a job, get a list of available printers, and get a list of available +classes. + +

HTTP Functions

+ +The HTTP functions provide functions to connect to HTTP servers, issue requests, +read data from a server, and write data to a server. + +

IPP Functions

+ +The IPP function provide functions to manage IPP request data and attributes, +read IPP responses from a server, and write IPP requests to a server. + +

Language Functions

+ +The language functions provide a standard interface for retrieving common +textual messages for a particular locale and determining the correct encoding +(e.g. US ASCII, ISO-8859-1, etc.) + +

MIME Functions

+ +The Multimedia Internet Mail Exchange functions manage a MIME type and +conversion database that supports file typing by extension and content, and +least-cost file filtering from a source to a destination file type. + +

PPD Functions

+ +The PostScript Printer Description functions manage PPD files, select options, +check for option conflicts, and emit selected options in the correct order. + +

Raster Functions

+ +The raster functions manage streams of CUPS raster data (described in the +Interface Design Document) used by non-PostScript printer drivers. + +

Filters

+ +The filters implement file conversion services for CUPS. All filters +are called with a common set of arguments: + +
    + +
  • Printer name - the name of the destination printer (name string). + +
  • Job Identifier - the job identifier for this job (integer). + +
  • User Name - the user associated with this job (name string). + +
  • Title - the title/job-name associated with this job (name string). + +
  • Copies - the number of copies required (integer). + +
  • Options - the options associated with this job (space separated + option strings). + +
  • Filename (optional) - the file to print; if this option is not + specified, the filter must read the input file from the standard + input. + +
+ +Filters are added to the MIME conversion data file and implement all necessary +conversions from one file type to another. + +

hpgltops

+ +The hpgltops filter converts HP-GL/2 files into PostScript. + +

imagetops

+ +The imagetops filter converts image files into PostScript. + +

pstops

+ +The pstops filter inserts printer-specific commands from PPD files and +performs page filtering as requested by the user. + +

texttops

+ +The texttops filter converts text files into PostScript. + +

Scheduler

+ +The scheduler is a fully-functional HTTP/1.1 server that manages the printers, +classes, and jobs in the system. It also handles a simple broadcast-based +directory service so that remote print queues and classes can be accessed +transparently from the local system. + +

Authorization

+ +The authorization module is responsible for performing access control and +authentication for all HTTP and IPP requests entering the system. + +

Classes

+ +The classes module is responsible for managing printer classes in the system. +Each class is a collection of local and/or remote printers. The classes module +also reads and writes the classes configuration file. + +

Client

+ +The client module is responsible for all HTTP client communications. It handles +listening on selected interfaces, accepting connections from prospective +clients, processing incoming HTTP requests, and sending HTTP responses to +those requests. The client module also is responsible for executing the +external CGI programs as needed to support web-based printer, class, and job +status monitoring. + +

Once authorized, all IPP requests are sent to the IPP module. + +

Configuration

+ +The configuration module is responsible for reading the CUPS configuration file +and initializing the appropriate data structures and values. The configuration +module also stops CUPS services before reading the configuration file and +restarts them after the configuration file has been read. + +

Directory Services

+ +The directory services module sends and recieves printer state information over +a broadcast socket. Remote printers and classes are automatically added to or +removed from the local printer and class lists as needed. + +

The directory services module can only recieve printer state information +over a single UDP port, however it can broadcast to multiple addresses and +ports as needed. + +

IPP

+ +The IPP module handles IPP requests and acts accordingly. URI +validation is also performed here, as a client can post IPP data to any +URI on the server (which might sidestep the access control or +authentication of the HTTP server.) + +

Jobs

+ +The jobs module manages print jobs, starts filter and backend processes +for jobs to be printed, and monitors status messages from those filters +and backends. + +

Main

+ +The main module is responsible for timing out and dispatching input and output +for client connections. It also watches for incoming SIGHUP +signals and reloads the server configuration files as needed. + +

Printers

+ +The printers module is responsible for managing printers and PPD files +in the system. The printers module also reads and writes the printers +configuration file. + +

System V Commands

+ +The System V commands provide a robust command-line interface to CUPS +to submit and control print jobs. + +

accept

+ +The accept command tells the scheduler to accept new jobs for specific +printers. + +

cancel

+ +The cancel command tells the scheduler to cancel one or more jobs that are +queued for printing. + +

disable

+ +The disable command tells the scheduler to stop printing jobs on the +specified printers. + +

enable

+ +The enable command tells the scheduler to start printing jobs on the +specified printers. + +

lp

+ +The lp command submits submits files for printing. Unlike the standard +System V lp command, a single CUPS lp command will generate a separate +job ID for each file that is printed. Also, the Solaris "f", "H", "P", "S", +and "y" options are silently ignored. + +

lpadmin

+ +The lpadmin command manages printer queues and classes. The Solaris +"A", "F", "I", "M", "P", "Q", "S", "T", "U", "W", "f", "l", "m", "o", +"s", "t", and "u" options are not supported, and new options "P" (PPD +file) and "F" (filter) are provided to configure CUPS-specific features +such as PPD file and conversion filters. + +

lpstat

+ +The lpstat command lists printers, classes, and jobs as requested by the +user. + +

reject

+ +The reject command tells the scheduler not to accept new jobs for specific +printers. + +

Detailed Design

+ +

Glossary

+ +

Terms

+ +
+ +
C +
A computer language. + +
parallel +
Sending or receiving data more than 1 bit at a time. + +
pipe +
A one-way communications channel between two programs. + +
serial +
Sending or receiving data 1 bit at a time. + +
socket +
A two-way network communications channel. + +
+ +

Acronyms

+ +
+ +
ASCII +
American Standard Code for Information Interchange + +
CUPS +
Common UNIX Printing System + +
ESC/P +
EPSON Standard Code for Printers + +
FTP +
File Transfer Protocol + +
HP-GL +
Hewlett-Packard Graphics Language + +
HP-PCL +
Hewlett-Packard Printer Control Language + +
HP-PJL +
Hewlett-Packard Printer Job Language + +
IETF +
Internet Engineering Task Force + +
IPP +
Internet Printing Protocol + +
ISO +
International Standards Organization + +
LPD +
Line Printer Daemon + +
MIME +
Multimedia Internet Mail Exchange + +
PCL +
Page Control Language + +
PPD +
PostScript Printer Description + +
SMB +
Server Message Block + +
TFTP +
Trivial File Transfer Protocol + +
+ + + diff --git a/doc/ssr.html b/doc/ssr.html new file mode 100644 index 0000000000..097610d2a0 --- /dev/null +++ b/doc/ssr.html @@ -0,0 +1,153 @@ + + +DRAFT - CUPS Software Security Report + + + + + +

+

DRAFT - CUPS Software Security Report


+CUPS-SSR-1.0
+Easy Software Products
+Copyright 1997-1999, All Rights Reserved
+
+
+

Table of Contents

+
+
1 Scope + +2 References + +3 Risk Identification + +4 Risk Assessment + +A Glossary + +
+

1 Scope

+

1.1 Identification

+ This software security report provides an analysis of possible +security concerns for the Common UNIX Printing System ("CUPS") Version +1.0. +

1.2 System Overview

+ The Common UNIX Printing System provides a portable printing layer for + UNIX® operating systems. It has been developed by Easy Software + Products to promote a standard printing solution for all UNIX vendors + and users. CUPS provides the System V and Berkeley command-line +interfaces. +

CUPS uses the Internet Printing Protocol (IETF-IPP) as the basis for +managing print jobs and queues. The Line Printer Daemon (LPD, RFC1179), +Server Message Block (SMB), and AppSocket protocols are also supported +with reduced functionality.

+

CUPS adds network printer browsing and PostScript Printer +Description ("PPD")-based printing options to support real world +applications under UNIX.

+

1.3 Document Overview

+

This software security report is organized into the following +sections:

+
    +
  • 1 - Scope
  • +
  • 2 - References
  • +
  • 3 - Risk Identification
  • +
  • 4 - Risk Assessment
  • +
  • A - Glossary
  • +
+

2 References

+

2.1 CUPS Documentation

+ The following CUPS documentation is referenced by this document: +
    +
  • CUPS-CMP-1.0: CUPS Configuration Management Plan
  • +
  • CUPS-IDD-1.0: CUPS System Interface Design Description
  • +
  • CUPS-SAM-1.0.x: CUPS Software Administrators Manual
  • +
  • CUPS-SDD-1.0: CUPS Software Design Description
  • +
  • CUPS-SPM-1.0: CUPS Software Programming Manual
  • +
  • CUPS-SSR-1.0: CUPS Software Security Report
  • +
  • CUPS-STP-1.0: CUPS Software Test Plan
  • +
  • CUPS-SUM-1.0.x: CUPS Software Users Manual
  • +
  • CUPS-SVD-1.0.x: CUPS Software Version Description
  • +
+

2.2 Other Documents

+ The following non-CUPS documents are referenced by this document: +
    +
  • IEEE 1387.4, System Administration: Printing (draft)
  • +
  • IPP/1.0: Additional Optional Operations - Set 1
  • +
  • IPP/1.0: Encoding and Transport
  • +
  • IPP/1.0: Implementers Guide
  • +
  • IPP/1.0: Model and Semantics
  • +
  • RFC 1179, Line Printer Daemon Protocol
  • +
+

3 Risk Identification

+

3.1 Local Access Risks

+

3.2 Remote Access Risks

+

4 Risk Assessment

+

4.1 Local Access Risks

+

4.2 Remote Access Risks

+

A Glossary

+

A.1 Terms

+
+
C
+
A computer language.
+
parallel
+
Sending or receiving data more than 1 bit at a time.
+
pipe
+
A one-way communications channel between two programs.
+
serial
+
Sending or receiving data 1 bit at a time.
+
socket
+
A two-way network communications channel.
+
+

A.2 Acronyms

+
+
ASCII
+
American Standard Code for Information Interchange
+
CUPS
+
Common UNIX Printing System
+
ESC/P
+
EPSON Standard Code for Printers
+
FTP
+
File Transfer Protocol
+
HP-GL
+
Hewlett-Packard Graphics Language
+
HP-PCL
+
Hewlett-Packard Printer Control Language
+
HP-PJL
+
Hewlett-Packard Printer Job Language
+
IETF
+
Internet Engineering Task Force
+
IPP
+
Internet Printing Protocol
+
ISO
+
International Standards Organization
+
LPD
+
Line Printer Daemon
+
MIME
+
Multimedia Internet Mail Exchange
+
PCL
+
Page Control Language
+
PPD
+
PostScript Printer Description
+
SMB
+
Server Message Block
+
TFTP
+
Trivial File Transfer Protocol
+
+ + diff --git a/doc/ssr.pdf b/doc/ssr.pdf new file mode 100644 index 0000000000..a770ec4680 --- /dev/null +++ b/doc/ssr.pdf @@ -0,0 +1,452 @@ +%PDF-1.2 +%âãÏÓ +1 0 obj<>endobj +2 0 obj<>endobj +3 0 obj<>endobj +4 0 obj<>endobj +5 0 obj<>endobj +6 0 obj<>endobj +7 0 obj<>endobj +8 0 obj<>endobj +9 0 obj<>endobj +10 0 obj<>endobj +11 0 obj<>endobj +12 0 obj<>endobj +13 0 obj<>endobj +14 0 obj<>endobj +15 0 obj<>endobj +16 0 obj<>endobj +17 0 obj<>endobj +18 0 obj<>endobj +19 0 obj<>endobj +20 0 obj<>endobj +21 0 obj<>endobj +22 0 obj<>endobj +23 0 obj<>endobj +24 0 obj<>endobj +25 0 obj<>endobj +26 0 obj<>endobj +27 0 obj<>endobj +28 0 obj<>endobj +29 0 obj<>endobj +30 0 obj<>endobj +31 0 obj<>endobj +32 0 obj<>endobj +33 0 obj<>endobj +34 0 obj<>endobj +35 0 obj<>endobj +36 0 obj<>endobj +37 0 obj<>endobj +38 0 obj<>endobj +39 0 obj<>endobj +40 0 obj<>endobj +41 0 obj<>endobj +42 0 obj<>endobj +43 0 obj<>endobj +44 0 obj<>endobj +45 0 obj<>endobj +46 0 obj<>endobj +47 0 obj<>endobj +48 0 obj<>endobj +49 0 obj<>endobj +50 0 obj<>endobj +51 0 obj<>endobj +52 0 obj<>endobj +53 0 obj<>endobj +54 0 obj<>endobj +55 0 obj[9 0 R +10 0 R +11 0 R +12 0 R +13 0 R +14 0 R +15 0 R +16 0 R +17 0 R +18 0 R +19 0 R +20 0 R +21 0 R +22 0 R +23 0 R +24 0 R +25 0 R +26 0 R +27 0 R +28 0 R +29 0 R +30 0 R +31 0 R +32 0 R +33 0 R +34 0 R +35 0 R +36 0 R +37 0 R +38 0 R +39 0 R +40 0 R +41 0 R +42 0 R +43 0 R +44 0 R +45 0 R +46 0 R +47 0 R +48 0 R +49 0 R +50 0 R +51 0 R +52 0 R +53 0 R +54 0 R +]endobj +56 0 obj<>endobj +57 0 obj<>endobj +58 0 obj<>endobj +59 0 obj<>endobj +60 0 obj<>endobj +61 0 obj<>endobj +62 0 obj<>endobj +63 0 obj<>endobj +64 0 obj<>endobj +65 0 obj<>endobj +66 0 obj<>endobj +67 0 obj<>endobj +68 0 obj<>endobj +69 0 obj<>endobj +70 0 obj<>endobj +71 0 obj<>endobj +72 0 obj<>endobj +73 0 obj<>endobj +74 0 obj<>endobj +75 0 obj<>endobj +76 0 obj<>>>>>endobj +77 0 obj<>stream +xÚíßÜ8rÇ%µúÅOšÙíwNH€ØîO{Ï@pgF›ì[I¢‡ ‡]_r‡ öÎë½`ÿûô¯éÖRª*R57<à°¶Én~ÄⷊdQý·W7b½ýߍøîV¼ÿ ~üßW÷òU"_ýM¼_ÿîíwû|ÿáÃÛµøÝÇ··âööæíݾÖïòÿ|÷ûìßîÅæ_×ûò~_>ìËÇ}yؗï÷å÷ÿõîñõ˯Ÿßý‡¸{óîßÅæææÝ=<ˆ;ñÃã«âyxá2+òñv¹\^]ìÊö?–wSç’ˋÈS•‹ËëÇirÉÛ+5R ny71.yÛÅôT.¯“©pᡎhwSàz¸òÈÅ_&ŽsÝG¯\næºåRÙ4Gpf¬ìŽ™e®ᙗoǸò+ÏJñ¯âºõ¬•`㠗žÍrí—±^Ø2K\òʳ^ü×£så‘×Gùfd®{¯§$crÝx½3—e´ncmËëQ¸däy.‚“BX-ßÎ5 &€Åƒ)`1ÀÀiÉà‹LËóVqõî·Ì4›k`¬-X2×Ú¼p}òF(³Þ¹2o”òmÏ\y4AÁ}…giLA +ÚÑ ê£såÞ¨eÓW4.rŠÁ2NjÁ4<Yì‰\r|,ÏïK8Àå…Ö¹2ω²±Ì%#7¸Ë\kϑ²°Ê•yΔÄ"—+Vˆrb®Øs¨l¬qå.auJLO4PQLP40QL*ÒÀk=–+u «cÀ`z0˜ Æcœ3ŽKºˆÕ×Ã51Ã`z.5Ã`¸áº¸\._?îÊýîâC¿ƒ —ùº9Éw÷ z0è¸ü–¤ùpÕπAßÃuÙ¹Tº7@[p­ûªò¨-­‡õÐãpҏ%77xÃæb‡´tq&ٌËÅ 5èé¹9kɐ0¹˜ÃÅJ§æ YÈäbòÜlHƐù<®´m·8d+W4” ž¼YdEêÁþ®†IÚ;'Ù`ÃàƒM-~æUHçÊGÀ"ƒùt.²Èûv®H +cåhç ‹6£r¥#!Ç"— ‹¶ qåV<$,2ra`oáõmaµdF†Ö"yËX¤ÛW +Wj!œ1*kƒ/Kªá'ö¹=Hð\Ò@peüÀl¼Kº¹bWDƒ2`«n®È'õ'ìäÊÜ.䀝\±cÅôaIWäØp!Ÿô¢ƒ+wÆ%Óºvp¥Î .J :¸„c³ -eI+—tp¸ps~Õʕ98\¸m¤°• ©òþ X(+ +Z¹"‡"C¢r´qaU~`,ÔôØ´p!U>š« ÙpU~38Âg-\ì­± 1Ðse.ŠÜhKÎôZ!¹VZ®¼ô|k†˜Yª¹€è¼Ú¹B-×Áö‚ó –”>Ps ¢ójç +ô\g­”Uú™#8\a¹žŒKÁuÖö o†¥OT\95†êàZh¹Î"SöJRìCúÚ+ÄsÍô\ñÓ#Š(‹ï+ˆ@^kWBù.Oϕ?+§˜!b¢„*®ˆh†\+-×á»æ‡¿ÂoÙu +ÛLÁ%©fØÉê¹Ö ѕÃdu«;š÷‹IÀÊ|0I.Á‹¢œçŠxQ”ë\ÒDæÊ åÐU®Œ:Ε>79e´ÝÕH³É8·¼Bp÷mê“3Qr-8\ 5Wy&}{âl÷¥Æ×¨N­‹3×Lɕ«Ï—#¶ûRh̸ÖEÃå)¹„ú܁¿i£¶W]nj­‹+×JÁ•6UPn9ÀrÍ4áËJÅr¸BWÔ|Œ–¹«Ë«u1àpM®'Ñð/¢“ÝÊ-‡h®•šËWqÕ¯ó¡¸wOr¾ó'ÑÑlp\óV®ý=¯ÒƒyÕ±$*®…ÒUãQD£²“y:lT¸±èæ:¾Ö8uøäU®”»8ãp5epü:@mb¯\¥´”êŸs{ê]ô8\FÕC§c Â¨ †ëœF¤È’Ÿ+»¸âpÕ‰j`¾§ ¡ \žmç’®XÏr¸êj3eo– Â¨Ãuþƒ"û_Íås¸jêO%žËïƒKq¯›KÑ(«;Øå¶\&< ̹šº¡¸Î×Í¥»ªÖ˞.©áZ«u^qÁÕl+,`¨°0ÑÃè”s[íbó:‚«ÙH(ŠkŽâÊÔþ+ÓÄQŠë|®f#-Wf‰+VÆç0¤ÖÅæu>W³Q¤tD(®†Kz En]§(®óa¸´\)?Œ*õáø+ôºRqÃÕhT®~þFצ0\-”]l\çÃp5i¹€FêÑìª6ºxmW½‘Wæ +Uë'š.Ö¯ó¡¸ê´\±E®zuë×ùP\õFZ®5?<,Ô§ÙÞot±~ÅUoÕÒTO\—Ÿh¸J¡j¥‹µë|8®Z#>W€äòW¥¿=úåã¶ÇBÝÅÚu>W­‘()v…+²ÃUÊ?,LJmPÝÅÚu>W­Q#ŽJ±\a[§*®Òû¡]܋6•«Úh]ˆâ#—×/WÖÆU½Î‡äRÜ,wqåšqåºxþT +"WµQZŸ*сKöÌ%5·8×ù\ÕFYM²¥‡åZq­\Àáª4’µÐÿð›óûç;¹¦’+Ëw¡{›mr¹½.ñÂõÂ5®Ù3å +§É½p½p½p½p½pá¸æ/\/\ýsyæ\ەú^)¥î¸\÷ûw˜ùטîRêŽÌuU¿¾V}ÙPé sŠºêÓõI•§¸(¥í1—h¤oTóôËÇSͺ ®Mu3´'®OÍMõe^ùù°ãæFU'תú@ûᒊ¥ê ÓÓ¿DÝ<êäZ Áª¥µ(O°ZúF­.ƒk^T¦f?\‘ê¨ Êó ª¤ÉÔë2¸Âª¥ô•?<]”ë–_]{>­WÖep•¯î‡+=ʛҗ–$ðœ]¡¬ËçÊúäŠK'Öë³w)¹¬sò¹¦®j›_ý­Õ㝴O.QyžUg ,½YS—ÆåŸŽO·“8è+*oɚҟ'i©Kã +N#îâ2‰ç+ÿ gµ8M°¬š¤­ªK⚝ÇöɄÃp¥ç?R` š¤­ªKâ +ˏnnÆÕ‘~xúçüb[%±JJw¤ôuI\»û_§Ç´è•+ÐýΧ”TܶՏçÇIº›Â«Þ¸"]:ÎñL9/ÁD-©;x®õñóvŸ¼éë n4qcP™FÚº$®ø(C;KOzã:žu^nÔÖ>“âIεuI\pÎ~õ‹Þ¸N!z£·‡~ˆJ¾X_WÉÕLìÜS¤Çùºs_ýq•òAj½Ÿ¼ÍÉëëR¸²£¬wlÆÕv®W®Wy/qÚÌ¢ÕÖ¥påÇ?îܲ!WÛ9l¬¼ÇQY'u)\Ò;½}ÞÎet¾,µ™¥¢‘Õ¢¯Kà*ŽŽyÿ·ýqÕ²hý¤1’!¢.…ëà˜÷n¹O®Ò‹¶ªª™ÓÕ¥ps¶÷ñ}r=]„mäR©’M[ë⸎9Û×7ãêÌûºT³F(Šº.Þ/ïÝ`²û¿ƒËF>ÛÃUsQ“j9ªº®to{·Ü?×¹·³Z(µAÕ%póÞ-Áõ$ +vÒ´Õ%póÞ-raß-šµ‹A[]—|òbó¡¸Î‰×Ý\µº®ƒc>ˆd+—I>öîU2«ª+ÖrµÕ¥pmM0ÈÏû§½pUÝ+tnvêêR¸¶’ágÇhȕàö;¸ÚêR¸v#z§ÕõÆTlËoåÒÕ¥pÁá2¬ßÅerïFTþY´ê|[] +Wz¸Y˜s­Ú—_‹ò:d¦åj«KáÊÎN½7®´<žëÚ×Ô:ÛV—•ŸW­\&÷mý»ó¡ÖJËÕV·#ž¯¼mKVO ¸ç°çCHýb±­.…«ô^Øþ¸â–µZ«¥.‰Kฌîeç-Uë\-u\‰9×—nSý±Š¾.‰+nüM\¹^a\9w?ªJ§§ÒÊeôþê^Ì·E+—¾.‰K÷~V»\¥Î^\Úº$®ìäÓÛ¹Œ6²wÞè*Ò”˜Ô5*†ïí9ÊÏë óS|†ïYr¶¾ë…kx®î×-O“+þ‡åJ&ÉÕ½Á±™$—É‚ù…kx.£…夹æ“ä’ÿ°\á$¹º`³gÊL“+z†¯áïq¼pÀµ~†/îw|V“ä‚gʕ>ÃÑðwÍÆ*]/{]þÝX¥«Ë+Üï:H¥v¸œ ¤º¤.1ü]αJŒâŠ&pt…Øß½u-à]ö…üb×vÚ¢.=@þ®´k‡‡â‚©²Óß"ßܱ€#ÃqMî÷èÓÎaL´åœc†ÎisuÎ1¯;e0ò✝n 0îÀ9uŽ ø]s`Ýa ìÕ1–w« ôű•e֭ހòŽ9°´»³€zŽ9°¸Û¸e°Ž­ÀÖÝQ âHǘè9À §[Bè+àSBŸ#l p#ë”Ðg-œÂ8%ô€ÒWÕ)¡]äк$ôaZ€œŠ.EôQ·ûzâ’z‰‘n(°B?ŸŒ®J\b:‚˜bf C.‡1Æ(X¡÷¦"‡~™+›Ž ¢ +´Ð;!樈 +´Ð‡‘Ãy™ !ôŽ ì + +´Ð;"k”Z=]ޱú*q¥‰¤:…àp”^èÃIÈFPåB}0 Ù«\ˆ­²1¯q‰iG„SÀ?'"‰|ø€7\'„#CzY ´pA8bd¡ ¢›Ù*0«s!Ñόݮ€‚"ˆs÷§×ªÁO`‚¡ï‚a?ā}× +’pŒ=ÁÐïh€‚$#O°îG?Sp ç'>ñHÆ;ö[£' +4áw‚á# 9‡‘'X†_J)Vy‚N¤¢#‡ˆ„Sp(ˆÂ1â£ÒmœG]ƒQ΀ØpÌMŽ˜Ð9 ê蘛”­v NÌ•>§L ŽôˆJOڑjÓñ”^PºT%m·M’4 ¨Ss4CDØÒL˵v×iÛ/PÐ'ØÂQ3,ÇB@vé#bJ3$ ¯pF2Ä5íy݊G1DI ]¼ÄÇSâㆂ1ÁFˆqz@Á™`¡‹fXYiçÁ ¿XI© +Î|Õ,¨jk‚ œd™‘½¬ 6° ‹ÉsXC>°rHz€5EVFÔ +œåöÐ1‡ Ï àl sd Þ$Tê׌ ÌÇ3 ÔKÎcîç $ÆÇÜi:܀±¦;peu°ÃõfŽàB*ý@±ž1ð?j˜c† ÀŸ©Ã XÄ ë€í‡°”éL/AƒÈ)Qà¸ÖX°•Ã5CreŽ ˜Œ¸A8F†Xû©¥qB Õ* +3Cìuá,ùV…™!öªõا»@sá ±GéÈ l +SCô“‘5^)^`&°}Zâ'o†Z.ém‰¹‘tAalˆ=i¢0ò¡`–-†éêv¸ìË¢ù½ +\…´k‹×æ=²ÃµµE{Cl +w¸ +yåÎ`Ùä²4d—›Â5®BÞËàk[}±ÉÅO­>R]Ûë‰].ƒôjDêö˜\\2»T}pqÈ._ÛîC\ļxÙÃ{.úáږG\v¼y×Ë×÷Ƶµƒ¼X>öõÝ}rí‡ívy¡§ëÇ>¿·o®ÃÀín8,¯.vår¹¼~|ìý+á¡@òëôÕ½|õîûâ棐›ïÞ~wë·wBþôOÙ§ï¥x# +ÈEþó¿þß¾|ùçýò§¯¿‰ìó_þòõŸåŸ·íïÄÍÍ®ýÍÝGñææýÛÛ]û]»7yž½¹y»ÞU{s³Ù~ú›Û‡OþðËo珅/?ÿôë_ÙW¼{ÿöCés~þëo_þôßÿóuÛɏ߽ÙþßÇŸþò‘íþò—mG~ùüåïŸÚ5MäéÿiÁñ½endstream +endobj +78 0 obj +6308 +endobj +79 0 obj<>>>>>endobj +80 0 obj<>stream +xÚ+ä2T0BCc3JÎår +ár á +äHÉHendstream +endobj +81 0 obj +31 +endobj +82 0 obj<>>>>>endobj +83 0 obj<>stream +xڕUKoÚ@¾ó+F9%Rpc Äykµ>ݏÀA”²¥?èA”œûƪċ襶^{ÃÚÞ¾zµ‡çÃ4ÁÂdi “©¢vîï7®~í-3R©Ù@W:3[ÐX*m Ôj%H +þ +¹%öV)”Š(›Ëƒ€X1ê‚ UÌáVå¹*àéÛô§-Î%ý®×±%1²bᖠæ0;?»} +³Ù<£&F ¾wåà×íøuvÁßר×nÞ!ø WßSKYXVåÎGŠ-jGÉÆÎ:×}`åµpFr ȃ©¥ #–sÄ\£äˆæ[¸´…p'u URņÀ(‹!WQ$B'{¤de;èP)kk,¥m_’£º±†XE÷ÜlC¾Ï6ƨW(Ñö-Ïù¡-³K¢NEŒä5Yw*ºtœºN5µ~š½˜ÌƨXInæô.ºoOƒ€Û)j÷¹°ccñs)±°þ޼¨¹£¯V\¸YGt,.W†1hû8;&—ðxëûƒÑìâB¶E"±@K¯Ø-ü:¶V[á¦,C~D7Ó*Wæ6Iê¨$U¥nÚ&3K^îÿH«"¶’çý¤>"IX–Ò«š!cškµ!KÙ¢™0ÖYiöœÜC戝Á„¡Í’áÁ(g·³r+ƒ¸®L@”¥l¶ž *¬‡÷ý}êÂDÅUÎ'ãïÅÞýŸ { ôBÙ/&Àð•TI©6nžÑ©HŸëüq“¿3dBäœuúx €Ï^ûððÅ{`;1NEqRxÄ5ò}¢…vmhF«“§ô?sôv9nˆ—‡¬ÀŠ¿áø/’¯­ÐÛÚ4lLíF±n}ð¯Ð^y#Îl_íﻨõ£õÑòæendstream +endobj +84 0 obj +734 +endobj +85 0 obj<>>>>>endobj +86 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS041T072PIÑp rt QÐUp VÎO+)O,JUNM.-Ê,©TJ-È/*Ñ ÉâÒi҅ê2‰˜˜˜é™)€ù† +ÁÉù© Q×®@.ü7 £endstream +endobj +87 0 obj +118 +endobj +88 0 obj<>>>>>endobj +89 0 obj<>stream +xÚ­•OÚ0Åï|Š9²Ò&K 7 +l…T´) {ââÆp•ØÔ6Úòíkc•V%]å@Æ¿7ö¼?ZtÌÀ „nòªõ)k=½ÄĐæMЃŒ¶CX`yŽê!ûîJžýÈyϑïÊüÆË$…‰ÈwrM4Ü-èAËþ+Ï6…(KñÎøÚ-¤— )µ.…o{ÐóU]3tàü#?<³Wa×Êm«àç‰ø¡Ó ^°õN:½9ád– IIø5ß4tÄßà³Éäžî•Æ +f\£,HŽ0AÅÖÜÞrɶ糹G"Í­„ÿ³…~'aD+ƙÒf/B*»—)ð¯·PÓ?¤õd~ H±–¤ª¬ w.n¡SÌw’é½±ïVH݀›%·¸ª¦I—˜ßRáÿŒímrûf¨ÖÛ¿Mîœ`ÏE§×)áUoPžb¬þ1Â\pï*Æ +l ™áÙt:…  üÞc° ç›Ý ¡×¶ŸU›JRèÕÃ]ç9K’§ÃÌG”2K$%¼nOèdxÆ^‚fì)ϵ=N!“„«» zbͪmyøÕ²ú¼c›qæ‚byh(Ŋ˜#ÌÕ] ÅËØ<âGøÂ8º1X¬ŒM̵ÈÅÑÛÑqÑÑ{aßúŸéE?6²æU×~žf­¯­_Ð&Ùûendstream +endobj +90 0 obj +522 +endobj +91 0 obj<>>>>>endobj +92 0 obj<>stream +xÚ-‹Í1…÷÷)ΒE™[Ͱ5˜5Óë¤n3TE¼½©È9›óó=ˆQb,êâp£FhÞ®À ‰`ÇXÚ +ržl»u+0Ø÷~ˆù}J +¯á•.ùƒNïCÊS¹’)ùS®4Îò¬Æ/Ûñ5iôY¦Ð¾­u"§endstream +endobj +93 0 obj +121 +endobj +94 0 obj<>>>>>endobj +95 0 obj<>stream +xÚ}ÎA +Â0Ð}Nñ—º0mÚ¦I– +7–\ ¤)¤ÚIÁ…2«Ï¼?̓0”iD…º…YÈI“¢S` +zJ›V4Ðã®Fï—ѮÑMÎ Ñùu¯çl9•Y¸¤ÙS†«7ÃGclïzØ +_¨Boí*: Æ>G¹Hòߍ,©J4¾å³&7ò×Ò:ßendstream +endobj +96 0 obj +146 +endobj +97 0 obj<>>>>>endobj +98 0 obj<>stream +xÚ-‹Ë D÷÷+f© ´WLµK_MÜ)à44EŒñïcf6s2çNŒê†¬Kí•Ö†¦íÌ0>>>>>endobj +101 0 obj<>stream +xÚuα +Â0à=Oñ:˜65i’±‚\,y‰¬Æ"×÷Ç«ÁADn:þï?î)jÛ`Û"f± ¢ê=”G¸pÒZp^i Wº¡#JD9=æu‹3Ò¹1N+S<ÝÑÅÈü]¥¥ð… )OsúQUï Ô稱,ÿ} ]-=3Îí²ïƒ8Џý7Ýendstream +endobj +102 0 obj +140 +endobj +103 0 obj<>>>>>endobj +104 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS041T072PIÑp rt QÐUp VÎO+)O,JUNM.-Ê,©TJ-È/*Ñ ÉâÒi҅겉[ë™*€ù& +A™ÅÙ +ŽÅÅ©ÅŹ©y`®!\\g$‘endstream +endobj +105 0 obj +127 +endobj +106 0 obj<>>>>>endobj +107 0 obj<>stream +xڝT]o›0}çWÜÇíZÒ4…Ç %i¤ªc‚J}uÍ õâf;‹òïwZ©ÝŠ¥N „uçžã{ð¯$‡Kºr¸™ÁÕ¸J¾µÉꄼ„vG•ÅÍÚîË6Ò8Çìékûs\gÅI¯‹le9´h•1 Èó€ Þt¶!ÕXšPZ7j8x´ ™î¬Çì=Qú>0ˤD9MØ î„îÁX°ÈQü‹ŽyÊXÿÌ4Ýà…Š7ÆÔé‘‚ uЂ3/ŒvÀ©F O菈üÑÀ`Mo™r±v­`ÿåîžœá{ô1W$÷ìJ“|c÷S‘RžÒ«ò53Xrkô)eSm·)Š6„ÓÈÏtÇl•évä«é©ÎŠèTõñ]=ÔÍt«Š<ÕÃýöj+´[ۜœGá\5ÕE=Mºª›ï÷ˆ?7@ë"Ìë6»¡µL»6ã 72Âv[§›»i¾[­ß¡ˆgÁܽü”ã§Å+uô¼  ÿsJ̋ˬ¤ó +eX¯ÚäGòE8%endstream +endobj +108 0 obj +426 +endobj +109 0 obj<>>>>>endobj +110 0 obj<>stream +xڝ’MSÂ0†ïý{ÔC+ÅRˑv„¡C¤ñÄj¤$˜½IU“œö}v÷Ý}õBè˜Âml?ÝxCìÝd1„!à• ÅI$€—W÷ÈG£Ù5~1ztÖýnDÎÓÚG„®‰ZR\h¦`$…V²‚厔ì“ð]Á¿@˜Ó”˜Ê§ßà')ÎÚá‹LC*J.3ì0©×IE\„~mšµL¤¤–TV.b1ÿ‰H4—‚TPh"–ÆŒæª$‚¿7‚ƒ=CãvöÌL~²uLØÆ‰Ê'yÚÎÊw•æ¶äN&ä„W¾Ñg³-—¥ÎKCfÍ9+äšÉZTñ­>ÏÍê&àö±È‡íԂ©½!嬮m³ÃJÒµƒ…3ì8!¬øž›Ug¼b€õʰ/Ï(ùʋûÐKúAlóƋA†Á‡Ñ#* +} ŠAÁèNq}„ÛJ¥mºF!øwÝŽÍ +;6…IЃ&0º0 JŠã¦¶RнïõG%¿endstream +endobj +111 0 obj +383 +endobj +112 0 obj<>>>/Annots 55 0 R>>endobj +113 0 obj<>stream +xÚ՘ÛnÛ8†ïý¼Ü^T/ÓdS(Ð]Û}W¡wÝFVWr[äí—ä u"RwVm@1äGiÿÐþoCIn¿”ŒpEªzón¿¹yЄj²?ªxƈ*¤½îÿؾ<ÒÉ]s¾˜ó¥{³ÿºùs¿É³ÜR܅ºËö½ÅK»¬&î +÷Odçø/¦·ÿ›I(u;ºev£d? kÂeVNù`EÊ®j¾(9îʤÝÎNÉVÿ¡³žàÊyšI{­‰d™ÄAÄÕ]m㭘òžÎ"¾Ak»’:o·@»}x´Yq:žªÃåԜ_÷º,²bM~OùÖ¿qð­ÌúÖy”2;Ãû”¥|Šä²ÈԔŒf$ힻ‹©#Å0¬·â´èP`GÚ§Ÿ¦ýy2¿^Ž ™^EpQ‘º´/…QA,*Rë 3'¢È4wU1A£Q÷Mõ£¶é>Ï#,PˆLLa¡a6£®|Y°^ðá~‘à˂ƒT³¸à¼tîšðÁŠ”­9šÖœ+ÓÍøQ¯K^ùðDò[ôrƒer/•o–”û°CéDc²˜s÷ù¯]$dÃZ›ü2wA“À¤PK‘¶¡Ôuƒ–ЉC›€AT„9fÉ6ÈenµkBF3’>]þ5m$Ãr×%r§EcÚ2_Cl5Äã‚Dµ}M$¿L˜óŽ}9ž$Äsæœ9æ{k lOÝ·yÐhqM´êŸI`¨%ç+EíÜÕé›L”O®@Û}JûÁBIË }ž5Ü2}¼š‘ô±©O©BB¥Â…z C;Ân+ۈºÈapuYÚæ4Á… ÈsÉ4S”ŒgêúOZh>ô.ÄtRh(ĤJn©_rÑ ¥hêæb"±Õ#µSÚŢȎ–»Ó_a•u D*®ìêq•Q™Jù®S=¸_$³Bpîq™ x/…>X‘²@fûU/Ÿ͈ºí:Z×ÿf~Â:±Yã²HŸä¾Í@IøÁ2•R@I• {xœìf$-QÙÀ œÀЎ°e*Ûã¼ÊNpa‚ÈÄo¡²©@‹|h§0ˆª¬ Ð]DZg‘ J8&£™†_aK”a¨„cÚéÂ.:ôZ;ƅ 4ÝE¯¯¶E\m)‡3|î’Ø–É­Mq¶¿ýcÑ3}ò°éhFÎû§¦ëíóë~äz¥9ùèDå9üÍ$2ƒ…‚™Sl%QÁ°¶¢x¿a¨(0#ioÚz.g]¾¯Ò× ÿò²€†äÞ1âe‰zÕ©æª$·¾™ ÑPUۜŸç<+„m3+ó¬÷éÍC‰Ùf5­ œc–Üooöä-ñÿÍìšãåס5dgªíéòL¶æ{ÓúS ®‘½-˜»zóïÍÿ®@endstream +endobj +114 0 obj +1058 +endobj +115 0 obj<>>>>>endobj +116 0 obj<>stream +xÚ+ä2T0BCc3JÎår +áÒw³P04TIS041T072PIÑp rt QÐUp VÎO+)O,JUNM.-Ê,©TJ-È/*Ñ ÉâÒi҅êÊÌ ¹†pr‡Âµendstream +endobj +117 0 obj +103 +endobj +118 0 obj<>endobj +119 0 obj<>endobj +120 0 obj<>endobj +121 0 obj<>endobj +122 0 obj<>endobj +123 0 obj<>endobj +124 0 obj<>endobj +125 0 obj<>endobj +126 0 obj<>endobj +127 0 obj<>endobj +128 0 obj<>endobj +129 0 obj<>endobj +130 0 obj<>endobj +131 0 obj<>endobj +132 0 obj<>endobj +133 0 obj<>endobj +134 0 obj<>endobj +135 0 obj<>endobj +136 0 obj<>/Outlines 118 0 R/PageMode/UseOutlines/OpenAction[82 0 R/XYZ null null null]>>endobj +xref +0 137 +0000000000 65535 f +0000000015 00000 n +0000000221 00000 n +0000000282 00000 n +0000000360 00000 n +0000000437 00000 n +0000000516 00000 n +0000000592 00000 n +0000000673 00000 n +0000000731 00000 n +0000000832 00000 n +0000000935 00000 n +0000001039 00000 n +0000001143 00000 n +0000001247 00000 n +0000001351 00000 n +0000001455 00000 n +0000001559 00000 n +0000001663 00000 n +0000001767 00000 n +0000001869 00000 n +0000001972 00000 n +0000002076 00000 n +0000002180 00000 n +0000002284 00000 n +0000002388 00000 n +0000002492 00000 n +0000002596 00000 n +0000002698 00000 n +0000002801 00000 n +0000002905 00000 n +0000003009 00000 n +0000003113 00000 n +0000003217 00000 n +0000003321 00000 n +0000003425 00000 n +0000003529 00000 n +0000003633 00000 n +0000003737 00000 n +0000003840 00000 n +0000003944 00000 n +0000004049 00000 n +0000004154 00000 n +0000004259 00000 n +0000004364 00000 n +0000004469 00000 n +0000004574 00000 n +0000004679 00000 n +0000004784 00000 n +0000004889 00000 n +0000004992 00000 n +0000005096 00000 n +0000005201 00000 n +0000005306 00000 n +0000005411 00000 n +0000005516 00000 n +0000005854 00000 n +0000005886 00000 n +0000005918 00000 n +0000006128 00000 n +0000006175 00000 n +0000006222 00000 n +0000006269 00000 n +0000006316 00000 n +0000006363 00000 n +0000006410 00000 n +0000006457 00000 n +0000006504 00000 n +0000006551 00000 n +0000006598 00000 n +0000006646 00000 n +0000006694 00000 n +0000006742 00000 n +0000006790 00000 n +0000006838 00000 n +0000006886 00000 n +0000007058 00000 n +0000007207 00000 n +0000013584 00000 n +0000013605 00000 n +0000013715 00000 n +0000013815 00000 n +0000013834 00000 n +0000013971 00000 n +0000014774 00000 n +0000014794 00000 n +0000014904 00000 n +0000015091 00000 n +0000015111 00000 n +0000015248 00000 n +0000015839 00000 n +0000015859 00000 n +0000015969 00000 n +0000016159 00000 n +0000016179 00000 n +0000016298 00000 n +0000016513 00000 n +0000016533 00000 n +0000016643 00000 n +0000016842 00000 n +0000016862 00000 n +0000016983 00000 n +0000017194 00000 n +0000017215 00000 n +0000017327 00000 n +0000017525 00000 n +0000017546 00000 n +0000017685 00000 n +0000018182 00000 n +0000018203 00000 n +0000018333 00000 n +0000018787 00000 n +0000018808 00000 n +0000018961 00000 n +0000020090 00000 n +0000020112 00000 n +0000020224 00000 n +0000020398 00000 n +0000020419 00000 n +0000020474 00000 n +0000020579 00000 n +0000020722 00000 n +0000020827 00000 n +0000020946 00000 n +0000021054 00000 n +0000021202 00000 n +0000021311 00000 n +0000021417 00000 n +0000021574 00000 n +0000021683 00000 n +0000021793 00000 n +0000021947 00000 n +0000022057 00000 n +0000022168 00000 n +0000022302 00000 n +0000022399 00000 n +0000022499 00000 n +trailer +<> +startxref +22682 +%%EOF diff --git a/doc/ssr.shtml b/doc/ssr.shtml new file mode 100644 index 0000000000..34fe87d359 --- /dev/null +++ b/doc/ssr.shtml @@ -0,0 +1,166 @@ + + + + + + DRAFT - CUPS Software Security Report + + + +

Scope

+ +

Identification

+ +This software security report provides an analysis of possible security +concerns for the Common UNIX Printing System ("CUPS") Version 1.0.

+ +

System Overview

+ +The Common UNIX Printing System provides a portable printing layer for +UNIX® operating systems. It has been developed by Easy Software +Products to promote a standard printing solution for all UNIX vendors +and users. CUPS provides the System V and Berkeley command-line interfaces. + +

CUPS uses the Internet Printing Protocol (IETF-IPP) as the basis +for managing print jobs and queues. The Line Printer Daemon (LPD, +RFC1179), Server Message Block (SMB), and AppSocket protocols are also +supported with reduced functionality. + +

CUPS adds network printer browsing and PostScript Printer +Description ("PPD")-based printing options to support real +world applications under UNIX. + +

Document Overview

+ +

This software security report is organized into the following sections:

+ +
    +
  • 1 - Scope
  • +
  • 2 - References
  • +
  • 3 - Risk Identification
  • +
  • 4 - Risk Assessment
  • +
  • A - Glossary
  • +
+ +

References

+ +

CUPS Documentation

+ +The following CUPS documentation is referenced by this document: + +
    +
  • CUPS-CMP-1.0: CUPS Configuration Management Plan +
  • CUPS-IDD-1.0: CUPS System Interface Design Description +
  • CUPS-SAM-1.0.x: CUPS Software Administrators Manual +
  • CUPS-SDD-1.0: CUPS Software Design Description +
  • CUPS-SPM-1.0: CUPS Software Programming Manual +
  • CUPS-SSR-1.0: CUPS Software Security Report +
  • CUPS-STP-1.0: CUPS Software Test Plan +
  • CUPS-SUM-1.0.x: CUPS Software Users Manual +
  • CUPS-SVD-1.0.x: CUPS Software Version Description +
+ +

Other Documents

+ +The following non-CUPS documents are referenced by this document: + +
    +
  • IEEE 1387.4, System Administration: Printing (draft) +
  • IPP/1.0: Additional Optional Operations - Set 1 +
  • IPP/1.0: Encoding and Transport +
  • IPP/1.0: Implementers Guide +
  • IPP/1.0: Model and Semantics +
  • RFC 1179, Line Printer Daemon Protocol +
+ +

Risk Identification

+ +

Local Access Risks

+ +

Remote Access Risks

+ +

Risk Assessment

+ +

Local Access Risks

+ +

Remote Access Risks

+ +

Glossary

+ +

Terms

+ +
+ +
C +
A computer language. + +
parallel +
Sending or receiving data more than 1 bit at a time. + +
pipe +
A one-way communications channel between two programs. + +
serial +
Sending or receiving data 1 bit at a time. + +
socket +
A two-way network communications channel. + +
+ +

Acronyms

+ +
+ +
ASCII +
American Standard Code for Information Interchange + +
CUPS +
Common UNIX Printing System + +
ESC/P +
EPSON Standard Code for Printers + +
FTP +
File Transfer Protocol + +
HP-GL +
Hewlett-Packard Graphics Language + +
HP-PCL +
Hewlett-Packard Printer Control Language + +
HP-PJL +
Hewlett-Packard Printer Job Language + +
IETF +
Internet Engineering Task Force + +
IPP +
Internet Printing Protocol + +
ISO +
International Standards Organization + +
LPD +
Line Printer Daemon + +
MIME +
Multimedia Internet Mail Exchange + +
PCL +
Page Control Language + +
PPD +
PostScript Printer Description + +
SMB +
Server Message Block + +
TFTP +
Trivial File Transfer Protocol + +
+ + + diff --git a/doc/stp.html b/doc/stp.html new file mode 100644 index 0000000000..dcf8ac388f --- /dev/null +++ b/doc/stp.html @@ -0,0 +1,142 @@ + + +DRAFT - CUPS Software Test Plan + + + + + +

+

DRAFT - CUPS Software Test Plan


+CUPS-STP-1.0
+Easy Software Products
+Copyright 1997-1999, All Rights Reserved
+
+
+

Table of Contents

+
+
1 Scope + +2 References + +3 Local Tests +
+
4 Remote Tests +
+
A Glossary + +
+

1 Scope

+

1.1 Identification

+ This software test plan provides detailed tests that are used to +evaluate the stability of the Common UNIX Printing System ("CUPS") +Version 1.0. +

1.2 System Overview

+ The Common UNIX Printing System provides a portable printing layer for + UNIX® operating systems. It has been developed by Easy Software + Products to promote a standard printing solution for all UNIX vendors + and users. CUPS provides the System V and Berkeley command-line +interfaces. +

CUPS uses the Internet Printing Protocol (IETF-IPP) as the basis for +managing print jobs and queues. The Line Printer Daemon (LPD, RFC1179), +Server Message Block (SMB), and AppSocket protocols are also supported +with reduced functionality.

+

CUPS adds network printer browsing and PostScript Printer +Description ("PPD")-based printing options to support real world +applications under UNIX.

+

1.3 Document Overview

+ This software test plan is organized into the following sections: +
    +
  • 1 - Scope
  • +
  • 2 - References
  • +
  • 3 - Local Tests
  • +
  • 4 - Remote Tests
  • +
  • A - Glossary
  • +
+

2 References

+

2.1 CUPS Documentation

+ The following CUPS documentation is referenced by this document: +
    +
  • CUPS-CMP-1.0: CUPS Configuration Management Plan
  • +
  • CUPS-IDD-1.0: CUPS System Interface Design Description
  • +
  • CUPS-SAM-1.0.x: CUPS Software Administrators Manual
  • +
  • CUPS-SDD-1.0: CUPS Software Design Description
  • +
  • CUPS-SPM-1.0: CUPS Software Programming Manual
  • +
  • CUPS-SSR-1.0: CUPS Software Security Report
  • +
  • CUPS-STP-1.0: CUPS Software Test Plan
  • +
  • CUPS-SUM-1.0.x: CUPS Software Users Manual
  • +
  • CUPS-SVD-1.0.x: CUPS Software Version Description
  • +
+

2.2 Other Documents

+ The following non-CUPS documents are referenced by this document: +
    +
  • IEEE 1387.4, System Administration: Printing (draft)
  • +
  • IPP/1.0: Additional Optional Operations - Set 1
  • +
  • IPP/1.0: Encoding and Transport
  • +
  • IPP/1.0: Implementers Guide
  • +
  • IPP/1.0: Model and Semantics
  • +
  • RFC 1179, Line Printer Daemon Protocol
  • +
+

3 Local Tests

+

4 Remote Tests

+

A Glossary

+

A.1 Terms

+
+
C
+
A computer language.
+
parallel
+
Sending or receiving data more than 1 bit at a time.
+
pipe
+
A one-way communications channel between two programs.
+
serial
+
Sending or receiving data 1 bit at a time.
+
socket
+
A two-way network communications channel.
+
+

A.2 Acronyms

+
+
ASCII
+
American Standard Code for Information Interchange
+
CUPS
+
Common UNIX Printing System
+
ESC/P
+
EPSON Standard Code for Printers
+
FTP
+
File Transfer Protocol
+
HP-GL
+
Hewlett-Packard Graphics Language
+
HP-PCL
+
Hewlett-Packard Printer Control Language
+
HP-PJL
+
Hewlett-Packard Printer Job Language
+
IETF
+
Internet Engineering Task Force
+
IPP
+
Internet Printing Protocol
+
ISO
+
International Standards Organization
+
LPD
+
Line Printer Daemon
+
MIME
+
Multimedia Internet Mail Exchange
+
PCL
+
Page Control Language
+
PPD
+
PostScript Printer Description
+
SMB
+
Server Message Block
+
TFTP
+
Trivial File Transfer Protocol
+
+ + diff --git a/doc/stp.shtml b/doc/stp.shtml new file mode 100644 index 0000000000..57cfe341c5 --- /dev/null +++ b/doc/stp.shtml @@ -0,0 +1,165 @@ + + + + + + + DRAFT - CUPS Software Test Plan + + + +

Scope

+ +

Identification

+ +This software test plan provides detailed tests that are used to evaluate +the stability of the Common UNIX Printing System ("CUPS") Version 1.0. + +

System Overview

+ +The Common UNIX Printing System provides a portable printing layer for +UNIX® operating systems. It has been developed by Easy Software +Products to promote a standard printing solution for all UNIX vendors +and users. CUPS provides the System V and Berkeley command-line interfaces. + +

CUPS uses the Internet Printing Protocol (IETF-IPP) as the basis +for managing print jobs and queues. The Line Printer Daemon (LPD, +RFC1179), Server Message Block (SMB), and AppSocket protocols are also +supported with reduced functionality. + +

CUPS adds network printer browsing and PostScript Printer +Description ("PPD")-based printing options to support real +world applications under UNIX. + +

Document Overview

+ +This software test plan is organized into the following sections: + +
    +
  • 1 - Scope
  • +
  • 2 - References
  • +
  • 3 - Local Tests
  • +
  • 4 - Remote Tests
  • +
  • A - Glossary
  • +
+ +

References

+ +

CUPS Documentation

+ +The following CUPS documentation is referenced by this document: + +
    +
  • CUPS-CMP-1.0: CUPS Configuration Management Plan +
  • CUPS-IDD-1.0: CUPS System Interface Design Description +
  • CUPS-SAM-1.0.x: CUPS Software Administrators Manual +
  • CUPS-SDD-1.0: CUPS Software Design Description +
  • CUPS-SPM-1.0: CUPS Software Programming Manual +
  • CUPS-SSR-1.0: CUPS Software Security Report +
  • CUPS-STP-1.0: CUPS Software Test Plan +
  • CUPS-SUM-1.0.x: CUPS Software Users Manual +
  • CUPS-SVD-1.0.x: CUPS Software Version Description +
+ +

Other Documents

+ +The following non-CUPS documents are referenced by this document: + +
    +
  • IEEE 1387.4, System Administration: Printing (draft) +
  • IPP/1.0: Additional Optional Operations - Set 1 +
  • IPP/1.0: Encoding and Transport +
  • IPP/1.0: Implementers Guide +
  • IPP/1.0: Model and Semantics +
  • RFC 1179, Line Printer Daemon Protocol +
+ +

Local Tests

+ + + + +

Remote Tests

+ + + + +

Glossary

+ +

Terms

+ +
+ +
C +
A computer language. + +
parallel +
Sending or receiving data more than 1 bit at a time. + +
pipe +
A one-way communications channel between two programs. + +
serial +
Sending or receiving data 1 bit at a time. + +
socket +
A two-way network communications channel. + +
+ +

Acronyms

+ +
+ +
ASCII +
American Standard Code for Information Interchange + +
CUPS +
Common UNIX Printing System + +
ESC/P +
EPSON Standard Code for Printers + +
FTP +
File Transfer Protocol + +
HP-GL +
Hewlett-Packard Graphics Language + +
HP-PCL +
Hewlett-Packard Printer Control Language + +
HP-PJL +
Hewlett-Packard Printer Job Language + +
IETF +
Internet Engineering Task Force + +
IPP +
Internet Printing Protocol + +
ISO +
International Standards Organization + +
LPD +
Line Printer Daemon + +
MIME +
Multimedia Internet Mail Exchange + +
PCL +
Page Control Language + +
PPD +
PostScript Printer Description + +
SMB +
Server Message Block + +
TFTP +
Trivial File Transfer Protocol + +
+ + + diff --git a/doc/sum.html b/doc/sum.html new file mode 100644 index 0000000000..31c628dc52 --- /dev/null +++ b/doc/sum.html @@ -0,0 +1,54 @@ + + +DRAFT - CUPS Software Users Manual + + + + + +

+

DRAFT - CUPS Software Users Manual


+CUPS-SUM-1.0.0b1
+Easy Software Products
+Copyright 1997-1999, All Rights Reserved
+
+
+

Table of Contents

+
+
1 Scope + +2 Printing System Overview +
+
3 Using the Printing System + +
+

1 Scope

+

1.1 Identification

+ This software users manual describes how to use the Common UNIX +Printing System ("CUPS") Version 1.0.0. +

1.2 Document Overview

+

This software users manual is organized into the following sections:

+
    +
  • 1 - Scope
  • +
  • 2 - References
  • +
  • 3 - Printing System Overview
  • +
  • 4 - Using the Printing System
  • +
  • A - Glossary
  • +
+

2 Printing System Overview

+

+

3 Using the Printing System

+

3.1 Choosing a Printer

+

3.2 Setting Printer Options

+

3.3 Submitting Files for Printing

+

3.4 Checking the Printer Status

+ + diff --git a/doc/sum.pdf b/doc/sum.pdf new file mode 100644 index 0000000000000000000000000000000000000000..c18ed6875230a6e4dc31f7561a84396264eef3b6 GIT binary patch literal 19057 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 + + + + + + DRAFT - CUPS Software Users Manual + + + +

Scope

+ +

Identification

+ +This software users manual describes how to use the Common UNIX Printing +System ("CUPS") Version 1.0.0. + +

Document Overview

+ +

This software users manual is organized into the following sections:

+ +
    +
  • 1 - Scope
  • +
  • 2 - References
  • +
  • 3 - Printing System Overview
  • +
  • 4 - Using the Printing System
  • +
  • A - Glossary
  • +
+ +

Printing System Overview

+ +

+ +

Using the Printing System

+ +

Choosing a Printer

+ +

Setting Printer Options

+ +

Submitting Files for Printing

+ +

Checking the Printer Status

+ + + diff --git a/doc/svd.html b/doc/svd.html new file mode 100644 index 0000000000..1a83a7c9ae --- /dev/null +++ b/doc/svd.html @@ -0,0 +1,146 @@ + + +CUPS Software Version Description + + + + + +

+

CUPS Software Version Description


+CUPS-SVD-1.0.0
+Easy Software Products
+Copyright 1997-1999, All Rights Reserved
+
+
+

Table of Contents

+
+
1 Scope + +2 References + +3 Additions +
+
4 Changes +
+
A Glossary + +
+

1 Scope

+

1.1 Identification

+ This software version description document provides release +information for the Common UNIX Printing System ("CUPS") Version 1.0. +

1.2 System Overview

+ The Common UNIX Printing System provides a portable printing layer for + UNIX® operating systems. It has been developed by Easy Software + Products to promote a standard printing solution for all UNIX vendors + and users. CUPS provides the System V and Berkeley command-line +interfaces. +

CUPS uses the Internet Printing Protocol (IETF-IPP) as the basis for +managing print jobs and queues. The Line Printer Daemon (LPD, RFC1179), +Server Message Block (SMB), and AppSocket protocols are also supported +with reduced functionality.

+

CUPS adds network printer browsing and PostScript Printer +Description ("PPD")-based printing options to support real world +applications under UNIX.

+

1.3 Document Overview

+

This Something Something Something document is organized into the +following sections:

+
    +
  • 1 - Scope
  • +
  • 2 - References
  • +
  • 3 - Additions
  • +
  • 4 - Changes
  • +
  • A - Glossary
  • +
+

2 References

+

2.1 CUPS Documentation

+ The following CUPS documentation is referenced by this document: +
    +
  • CUPS-CMP-1.0: CUPS Configuration Management Plan
  • +
  • CUPS-IDD-1.0: CUPS System Interface Design Description
  • +
  • CUPS-SAM-1.0.x: CUPS Software Administrators Manual
  • +
  • CUPS-SDD-1.0: CUPS Software Design Description
  • +
  • CUPS-SPM-1.0: CUPS Software Programming Manual
  • +
  • CUPS-SSR-1.0: CUPS Software Security Report
  • +
  • CUPS-STP-1.0: CUPS Software Test Plan
  • +
  • CUPS-SUM-1.0.x: CUPS Software Users Manual
  • +
  • CUPS-SVD-1.0.x: CUPS Software Version Description
  • +
+

2.2 Other Documents

+ The following non-CUPS documents are referenced by this document: +
    +
  • IEEE 1387.4, System Administration: Printing (draft)
  • +
  • IPP/1.0: Additional Optional Operations - Set 1
  • +
  • IPP/1.0: Encoding and Transport
  • +
  • IPP/1.0: Implementers Guide
  • +
  • IPP/1.0: Model and Semantics
  • +
  • RFC 1179, Line Printer Daemon Protocol
  • +
+

3 Additions

+ Since this is the first release of CUPS, there are no additions to +report. +

4 Changes

+ Since this is the first release of CUPS, there are no changes to +report. +

A Glossary

+

A.1 Terms

+
+
C
+
A computer language.
+
parallel
+
Sending or receiving data more than 1 bit at a time.
+
pipe
+
A one-way communications channel between two programs.
+
serial
+
Sending or receiving data 1 bit at a time.
+
socket
+
A two-way network communications channel.
+
+

A.2 Acronyms

+
+
ASCII
+
American Standard Code for Information Interchange
+
CUPS
+
Common UNIX Printing System
+
ESC/P
+
EPSON Standard Code for Printers
+
FTP
+
File Transfer Protocol
+
HP-GL
+
Hewlett-Packard Graphics Language
+
HP-PCL
+
Hewlett-Packard Printer Control Language
+
HP-PJL
+
Hewlett-Packard Printer Job Language
+
IETF
+
Internet Engineering Task Force
+
IPP
+
Internet Printing Protocol
+
ISO
+
International Standards Organization
+
LPD
+
Line Printer Daemon
+
MIME
+
Multimedia Internet Mail Exchange
+
PCL
+
Page Control Language
+
PPD
+
PostScript Printer Description
+
SMB
+
Server Message Block
+
TFTP
+
Trivial File Transfer Protocol
+
+ + diff --git a/doc/svd.pdf b/doc/svd.pdf new file mode 100644 index 0000000000000000000000000000000000000000..81123149f42a47f79aa430c71c80a94fdf9df0dc GIT binary patch literal 21846 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 SraE9W9EM;P7gyKQVE%t-WyrYz literal 0 Hc-jL100001 diff --git a/doc/svd.shtml b/doc/svd.shtml new file mode 100644 index 0000000000..401236eb48 --- /dev/null +++ b/doc/svd.shtml @@ -0,0 +1,163 @@ + + + + + + CUPS Software Version Description + + + +

Scope

+ +

Identification

+ +This software version description document provides release information for the +Common UNIX Printing System ("CUPS") Version 1.0. + +

System Overview

+ +The Common UNIX Printing System provides a portable printing layer for +UNIX® operating systems. It has been developed by Easy Software +Products to promote a standard printing solution for all UNIX vendors +and users. CUPS provides the System V and Berkeley command-line interfaces. + +

CUPS uses the Internet Printing Protocol (IETF-IPP) as the basis +for managing print jobs and queues. The Line Printer Daemon (LPD, +RFC1179), Server Message Block (SMB), and AppSocket protocols are also +supported with reduced functionality. + +

CUPS adds network printer browsing and PostScript Printer +Description ("PPD")-based printing options to support real +world applications under UNIX. + +

Document Overview

+ +

This Something Something Something document is organized into the following +sections:

+ +
    +
  • 1 - Scope
  • +
  • 2 - References
  • +
  • 3 - Additions
  • +
  • 4 - Changes
  • +
  • A - Glossary
  • +
+ +

References

+ +

CUPS Documentation

+ +The following CUPS documentation is referenced by this document: + +
    +
  • CUPS-CMP-1.0: CUPS Configuration Management Plan +
  • CUPS-IDD-1.0: CUPS System Interface Design Description +
  • CUPS-SAM-1.0.x: CUPS Software Administrators Manual +
  • CUPS-SDD-1.0: CUPS Software Design Description +
  • CUPS-SPM-1.0: CUPS Software Programming Manual +
  • CUPS-SSR-1.0: CUPS Software Security Report +
  • CUPS-STP-1.0: CUPS Software Test Plan +
  • CUPS-SUM-1.0.x: CUPS Software Users Manual +
  • CUPS-SVD-1.0.x: CUPS Software Version Description +
+ +

Other Documents

+ +The following non-CUPS documents are referenced by this document: + +
    +
  • IEEE 1387.4, System Administration: Printing (draft) +
  • IPP/1.0: Additional Optional Operations - Set 1 +
  • IPP/1.0: Encoding and Transport +
  • IPP/1.0: Implementers Guide +
  • IPP/1.0: Model and Semantics +
  • RFC 1179, Line Printer Daemon Protocol +
+ +

Additions

+ +Since this is the first release of CUPS, there are no additions to report. + +

Changes

+ +Since this is the first release of CUPS, there are no changes to report. + +

Glossary

+ +

Terms

+ +
+ +
C +
A computer language. + +
parallel +
Sending or receiving data more than 1 bit at a time. + +
pipe +
A one-way communications channel between two programs. + +
serial +
Sending or receiving data 1 bit at a time. + +
socket +
A two-way network communications channel. + +
+ +

Acronyms

+ +
+ +
ASCII +
American Standard Code for Information Interchange + +
CUPS +
Common UNIX Printing System + +
ESC/P +
EPSON Standard Code for Printers + +
FTP +
File Transfer Protocol + +
HP-GL +
Hewlett-Packard Graphics Language + +
HP-PCL +
Hewlett-Packard Printer Control Language + +
HP-PJL +
Hewlett-Packard Printer Job Language + +
IETF +
Internet Engineering Task Force + +
IPP +
Internet Printing Protocol + +
ISO +
International Standards Organization + +
LPD +
Line Printer Daemon + +
MIME +
Multimedia Internet Mail Exchange + +
PCL +
Page Control Language + +
PPD +
PostScript Printer Description + +
SMB +
Server Message Block + +
TFTP +
Trivial File Transfer Protocol + +
+ + + diff --git a/filter/Makefile b/filter/Makefile new file mode 100644 index 0000000000..f1b6c19ddd --- /dev/null +++ b/filter/Makefile @@ -0,0 +1,114 @@ +# +# "$Id$" +# +# Filter makefile for the Common UNIX Printing System (CUPS). +# +# Copyright 1997-1999 by Easy Software Products. +# +# These coded instructions, statements, and computer programs are the +# property of Easy Software Products and are protected by Federal +# copyright law. Distribution and use rights are outlined in the file +# "LICENSE.txt" which should have been included with this file. If this +# file is missing or damaged please contact Easy Software Products +# at: +# +# Attn: CUPS Licensing Information +# Easy Software Products +# 44145 Airport View Drive, Suite 204 +# Hollywood, Maryland 20636-3111 USA +# +# Voice: (301) 373-9603 +# EMail: cups-info@cups.org +# WWW: http://www.cups.org +# + +include ../Makedefs + +TARGETS = hpgltops texttops pstops imagetops imagetoraster + +HPGLOBJS = hpgl-attr.o hpgl-config.o hpgl-main.o hpgl-prolog.o \ + hpgl-char.o hpgl-input.o hpgl-polygon.o hpgl-vector.o +IMAGEOBJS = image-colorspace.o image-photocd.o image-sgilib.o \ + image-tiff.o image-gif.o image-png.o image-sgi.o image-zoom.o \ + image-jpeg.o image-pnm.o image-sun.o image.o +OBJS = $(HPGLOBJS) $(IMAGEOBJS) imagetops.o imagetoraster.o \ + common.o pstops.o texttops.o textcommon.o + +# +# Make all targets... +# + +all: $(TARGETS) + +# +# Clean all object files... +# + +clean: + rm -f $(OBJS) $(TARGETS) image.a + +# +# Install all targets... +# + +install: + -$(MKDIR) $(SERVERROOT)/filter + $(CP) $(TARGETS) $(SERVERROOT)/filter + +# +# hpgltops +# + +hpgltops: $(HPGLOBJS) common.o ../Makedefs ../cups/libcups.a + $(CC) $(LDFLAGS) -o $@ $(HPGLOBJS) common.o $(LIBS) -lm +$(HPGLOBJS): hpgltops.h + +# +# image.a +# + +image.a: $(IMAGEOBJS) ../Makedefs ../cups/libcups.a + $(RM) $@ + $(AR) $(ARFLAGS) $@ $(IMAGEOBJS) + $(RANLIB) $@ +$(IMAGEOBJS): image.h + +# +# imagetops +# + +imagetops: imagetops.o common.o image.a ../Makedefs ../cups/libcups.a + $(CC) $(LDFLAGS) -o $@ imagetops.o common.o image.a $(IMGLIBS) +imagetops: common.h image.h + +# +# imagetoraster +# + +imagetoraster: imagetoraster.o common.o image.a ../Makedefs ../cups/libcups.a + $(CC) $(LDFLAGS) -o $@ imagetoraster.o common.o image.a $(IMGLIBS) +imagetoraster: common.h image.h + +# +# pstops +# + +pstops: pstops.o common.o ../Makedefs ../cups/libcups.a + $(CC) $(LDFLAGS) -o $@ pstops.o common.o $(LIBS) +pstops.o: common.h + +# +# texttops +# + +texttops: texttops.o textcommon.o common.o ../Makedefs ../cups/libcups.a + $(CC) $(LDFLAGS) -o $@ texttops.o textcommon.o common.o $(LIBS) +texttops.o: common.h textcommon.h + +common.o: common.h +textcommon.o: textcommon.h common.h +$(OBJS): ../Makedefs ../cups/cups.h ../cups/ppd.h ../cups/language.h + +# +# End of "$Id$". +# diff --git a/filter/common.c b/filter/common.c new file mode 100644 index 0000000000..c173fdf168 --- /dev/null +++ b/filter/common.c @@ -0,0 +1,250 @@ +/* + * "$Id$" + * + * Common filter routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * SetCommonOptions() - Set common filter options for media size, etc. + */ + +/* + * Include necessary headers... + */ + +#include "common.h" + + +/* + * Globals... + */ + +int Orientation = 0, /* 0 = portrait, 1 = landscape, etc. */ + Duplex = 0, /* Duplexed? */ + LanguageLevel = 1, /* Language level of printer */ + ColorDevice = 1; /* Do color text? */ +float PageLeft = 18.0f, /* Left margin */ + PageRight = 594.0f, /* Right margin */ + PageBottom = 36.0f, /* Bottom margin */ + PageTop = 756.0f, /* Top margin */ + PageWidth = 612.0f, /* Total page width */ + PageLength = 792.0f; /* Total page length */ + + +/* + * 'SetCommonOptions()' - Set common filter options for media size, etc. + */ + +ppd_file_t * /* O - PPD file */ +SetCommonOptions(int num_options, /* I - Number of options */ + cups_option_t *options, /* I - Options */ + int change_size) /* I - Change page size? */ +{ + float temp; /* Swapping variable */ + ppd_file_t *ppd; /* PPD file */ + ppd_size_t *pagesize; /* Current page size */ + char *val; /* Option value */ + + + ppd = ppdOpenFile(getenv("PPD")); + + ppdMarkDefaults(ppd); + cupsMarkOptions(ppd, num_options, options); + + if ((pagesize = ppdPageSize(ppd, NULL)) != NULL) + { + PageWidth = pagesize->width; + PageLength = pagesize->length; + PageTop = pagesize->top; + PageBottom = pagesize->bottom; + PageLeft = pagesize->left; + PageRight = pagesize->right; + } + + if (ppd != NULL) + { + ColorDevice = ppd->color_device; + LanguageLevel = ppd->language_level; + } + + if ((val = cupsGetOption("landscape", num_options, options)) != NULL) + Orientation = 1; + + if ((val = cupsGetOption("orientation-requested", num_options, options)) != NULL) + { + /* + * Map IPP orientation values to 0 to 3: + * + * 3 = 0 degrees = 0 + * 4 = 90 degrees = 1 + * 5 = -90 degrees = 3 + * 6 = 180 degrees = 2 + */ + + Orientation = atoi(val) - 3; + if (Orientation >= 2) + Orientation ^= 1; + } + + if ((val = cupsGetOption("page-left", num_options, options)) != NULL) + { + switch (Orientation) + { + case 0 : + PageLeft = (float)atof(val); + break; + case 1 : + PageBottom = (float)atof(val); + break; + case 2 : + PageRight = PageWidth - (float)atof(val); + break; + case 3 : + PageTop = PageLength - (float)atof(val); + break; + } + } + + if ((val = cupsGetOption("page-right", num_options, options)) != NULL) + { + switch (Orientation) + { + case 0 : + PageRight = PageWidth - (float)atof(val); + break; + case 1 : + PageTop = PageLength - (float)atof(val); + break; + case 2 : + PageLeft = (float)atof(val); + break; + case 3 : + PageBottom = (float)atof(val); + break; + } + } + + if ((val = cupsGetOption("page-bottom", num_options, options)) != NULL) + { + switch (Orientation) + { + case 0 : + PageBottom = (float)atof(val); + break; + case 1 : + PageRight = PageWidth - (float)atof(val); + break; + case 2 : + PageTop = PageLength - (float)atof(val); + break; + case 3 : + PageLeft = (float)atof(val); + break; + } + } + + if ((val = cupsGetOption("page-top", num_options, options)) != NULL) + { + switch (Orientation) + { + case 0 : + PageTop = PageLength - (float)atof(val); + break; + case 1 : + PageLeft = (float)atof(val); + break; + case 2 : + PageBottom = (float)atof(val); + break; + case 3 : + PageRight = PageWidth - (float)atof(val); + break; + } + } + + if (change_size) + switch (Orientation) + { + case 0 : /* Portait */ + break; + + case 1 : /* Landscape */ + temp = PageLeft; + PageLeft = PageBottom; + PageBottom = temp; + + temp = PageRight; + PageRight = PageTop; + PageTop = temp; + + temp = PageWidth; + PageWidth = PageLength; + PageLength = temp; + break; + + case 2 : /* Reverse Portrait */ + temp = PageWidth - PageLeft; + PageLeft = PageWidth - PageRight; + PageRight = temp; + + temp = PageLength - PageBottom; + PageBottom = PageLength - PageTop; + PageTop = temp; + break; + + case 3 : /* Reverse Landscape */ + temp = PageWidth - PageLeft; + PageLeft = PageWidth - PageRight; + PageRight = temp; + + temp = PageLength - PageBottom; + PageBottom = PageLength - PageTop; + PageTop = temp; + + temp = PageLeft; + PageLeft = PageBottom; + PageBottom = temp; + + temp = PageRight; + PageRight = PageTop; + PageTop = temp; + + temp = PageWidth; + PageWidth = PageLength; + PageLength = temp; + break; + } + + if ((val = cupsGetOption("sides", num_options, options)) != NULL && + strncmp(val, "two-", 4) == 0) + Duplex = 1; + + if ((val = cupsGetOption("Duplex", num_options, options)) != NULL && + strcmp(val, "DuplexNoTumble") == 0) + Duplex = 1; + + return (ppd); +} + + +/* + * End of "$Id$". + */ diff --git a/filter/common.h b/filter/common.h new file mode 100644 index 0000000000..16e9ac6cab --- /dev/null +++ b/filter/common.h @@ -0,0 +1,67 @@ +/* + * "$Id$" + * + * Common filter definitions for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + */ + +/* + * Include necessary headers... + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +/* + * Globals... + */ + +extern int Orientation, /* 0 = portrait, 1 = landscape, etc. */ + Duplex, /* Duplexed? */ + LanguageLevel, /* Language level of printer */ + ColorDevice; /* Do color text? */ +extern float PageLeft, /* Left margin */ + PageRight, /* Right margin */ + PageBottom, /* Bottom margin */ + PageTop, /* Top margin */ + PageWidth, /* Total page width */ + PageLength; /* Total page length */ + + +/* + * Prototypes... + */ + +extern ppd_file_t *SetCommonOptions(int num_options, cups_option_t *options, + int change_size); + + +/* + * End of "$Id$". + */ diff --git a/filter/hpgl-attr.c b/filter/hpgl-attr.c new file mode 100644 index 0000000000..99a1b9fa57 --- /dev/null +++ b/filter/hpgl-attr.c @@ -0,0 +1,405 @@ +/* + * "$Id$" + * + * HP-GL/2 attribute processing for the Common UNIX Printing System (CUPS). + * + * Copyright 1993-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * CR_color_range() - Set the range for color values. + * AC_anchor_corner() - Set the anchor corner. + * FT_fill_type() - Set the fill type or pattern. + * LA_line_attributes() - Set the line drawing attributes. + * LT_line_type() - Set the line type (style)... + * NP_number_pens() - Set the number of pens to be used. + * PC_pen_color() - Set the pen color... + * PW_pen_width() - Set the pen width. + * RF_raster_fill() - Set the raster fill pattern. + * SM_symbol_mode() - Set where symbols are drawn. + * SP_select_pen() - Select a pen for drawing. + * UL_user_line_type() - Set a user-defined line type. + * WU_width_units() - Set the units used for pen widths. + */ + +/* + * Include necessary headers... + */ + +#include "hpgltops.h" + + +/* + * 'CR_color_range()' - Set the range for color values. + */ + +void +CR_color_range(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + if (num_params == 0) + { + /* + * Default to 0 to 255 for all color values. + */ + + ColorRange[0][0] = 0.0; + ColorRange[0][1] = 255.0; + ColorRange[1][0] = 0.0; + ColorRange[1][1] = 255.0; + ColorRange[2][0] = 0.0; + ColorRange[2][1] = 255.0; + } + else if (num_params == 6) + { + /* + * Set the range based on the parameters... + */ + ColorRange[0][0] = params[0].value.number; + ColorRange[0][1] = params[1].value.number - params[0].value.number; + ColorRange[1][0] = params[2].value.number; + ColorRange[1][1] = params[3].value.number - params[2].value.number; + ColorRange[2][0] = params[4].value.number; + ColorRange[2][1] = params[5].value.number - params[4].value.number; + } + else + fprintf(stderr, "WARNING: HP-GL/2 \'CR\' command with invalid number of parameters (%d)!\n", + num_params); +} + + +/* + * 'AC_anchor_corner()' - Set the anchor corner. + */ + +void +AC_anchor_corner(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + (void)num_params; + (void)params; +} + + +/* + * 'FT_fill_type()' - Set the fill type or pattern. + * + * Note: + * + * This needs to be updated to support non-solid fill. + */ + +void +FT_fill_type(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + if (num_params == 0 || + params[0].value.number == 1 || + params[0].value.number == 2) + { + /**** SOLID PATTERN ****/ + } +} + + +/* + * 'LA_line_attributes()' - Set the line drawing attributes. + */ + +void +LA_line_attributes(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + int i; /* Looping var */ + + + if (num_params == 0) + { + Outputf("3.0 setmiterlimit\n"); + Outputf("0 setlinecap\n"); + Outputf("0 setlinejoin\n"); + } + else for (i = 0; i < (num_params - 1); i += 2) + switch ((int)params[i].value.number) + { + case 1 : + Outputf("%d setlinecap\n", + params[i + 1].value.number == 1 ? 0 : + params[i + 1].value.number == 4 ? 1 : 2); + break; + case 2 : + switch ((int)params[i + 1].value.number) + { + case 1 : + case 2 : + case 3 : + Outputf("0 setlinejoin\n"); + break; + case 5 : + Outputf("2 setlinejoin\n"); + break; + default : + Outputf("1 setlinejoin\n"); + break; + } + break; + case 3 : + Outputf("%f setmiterlimit\n", + 1.0 + 0.5 * (params[i + 1].value.number - 1.0)); + break; + } +} + + +/* + * 'LT_line_type()' - Set the line type (style)... + * + * Note: + * + * This needs to be updated to support line types. + */ + +void +LT_line_type(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + (void)num_params; + (void)params; +} + + +/* + * 'NP_number_pens()' - Set the number of pens to be used. + */ + +void +NP_number_pens(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + int i; /* Looping var */ + + + if (num_params == 0) + PenCount = 8; + else if (num_params == 1) + PenCount = (int)params[0].value.number; + else + fprintf(stderr, "WARNING: HP-GL/2 \'NP\' command with invalid number of parameters (%d)!\n", + num_params); + + PC_pen_color(0, NULL); + + for (i = 0; i <= PenCount; i ++) + Outputf("/W%d { DefaultPenWidth PenScaling mul setlinewidth } bind def\n", i); +} + + +/* + * 'PC_pen_color()' - Set the pen color... + */ + +void +PC_pen_color(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + int i; /* Looping var */ + static float standard_colors[8][3] = /* Standard colors for first 8 pens */ + { + { 1.0, 1.0, 1.0 }, /* White */ + { 0.0, 0.0, 0.0 }, /* Black */ + { 1.0, 0.0, 0.0 }, /* Red */ + { 0.0, 1.0, 0.0 }, /* Green */ + { 1.0, 1.0, 0.0 }, /* Yellow */ + { 0.0, 0.0, 1.0 }, /* Blue */ + { 1.0, 0.0, 1.0 }, /* Magenta */ + { 0.0, 1.0, 1.0 } /* Cyan */ + }; + + if (num_params == 0) + { + for (i = 0; i <= PenCount; i ++) + if (i < 8) + Outputf("/P%d { %.3f %.3f %.3f setrgbcolor } bind def\n", + i, standard_colors[i][0], + standard_colors[i][1], standard_colors[i][2]); + else + Outputf("/P%d { 0.0 0.0 0.0 setrgbcolor } bind def\n", i); + } + else if (num_params == 1) + { + i = (int)params[0].value.number; + + Outputf("/P%d { %.3f %.3f %.3f setrgbcolor } bind def\n", + i, standard_colors[i & 7][0], standard_colors[i & 7][1], + standard_colors[i & 7][2]); + } + else if (num_params == 4) + Outputf("/P%d { %.3f %.3f %.3f setrgbcolor } bind def\n", + (int)params[0].value.number, + (params[1].value.number - ColorRange[0][0]) / ColorRange[0][1], + (params[2].value.number - ColorRange[1][0]) / ColorRange[1][1], + (params[3].value.number - ColorRange[2][0]) / ColorRange[2][1]); + else + fprintf(stderr, "WARNING: HP-GL/2 \'PC\' command with invalid number of parameters (%d)!\n", + num_params); +} + + +/* + * 'PW_pen_width()' - Set the pen width. + */ + +void +PW_pen_width(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + int pen; /* Pen number */ + float w; /* Width value */ + + + if (WidthUnits == 0) + { + /* + * Metric... + */ + + if (num_params == 0) + w = 0.35f / 25.4f * 72.0f; + else + w = params[0].value.number / 25.4f * 72.0f; + } + else + { + /* + * Relative... + */ + + w = (float)hypot(PlotSize[0], PlotSize[1]) / 1016.0f * 72.0f; + + if (num_params == 0) + w *= 0.01f; + else + w *= params[0].value.number; + } + + if (num_params == 2) + Outputf("/W%d { %.1f PenScaling mul setlinewidth } bind def W%d\n", + (int)params[1].value.number, w, (int)params[1].value.number); + else if (num_params < 2) + { + /* + * Set width for all pens... + */ + + for (pen = 0; pen <= PenCount; pen ++) + Outputf("/W%d { %.1f PenScaling mul setlinewidth } bind def\n", + pen, w); + + Outputf("W%d\n", PenNumber); + } + else + fprintf(stderr, "WARNING: HP-GL/2 \'PW\' command with invalid number of parameters (%d)!\n", + num_params); +} + + +/* + * 'RF_raster_fill()' - Set the raster fill pattern. + * + * Note: + * + * This needs to be implemented. + */ + +void +RF_raster_fill(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + (void)num_params; + (void)params; +} + + +/* + * 'SM_symbol_mode()' - Set where symbols are drawn. + */ + +void +SM_symbol_mode(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + (void)num_params; + (void)params; +} + + +/* + * 'SP_select_pen()' - Select a pen for drawing. + */ + +void +SP_select_pen(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + if (num_params == 0) + PenNumber = 1; + else if (params[0].value.number <= PenCount) + PenNumber = (int)params[0].value.number; + else + fprintf(stderr, "WARNING: HP-GL/2 \'SP\' command with invalid number or value of parameters (%d, %d)!\n", + num_params, (int)params[0].value.number); + + Outputf("P%d W%d\n", PenNumber, PenNumber); +} + + +/* + * 'UL_user_line_type()' - Set a user-defined line type. + */ + +void +UL_user_line_type(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + (void)num_params; + (void)params; +} + + +/* + * 'WU_width_units()' - Set the units used for pen widths. + */ + +void +WU_width_units(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + if (num_params == 0) + WidthUnits = 0; + else if (num_params == 1) + WidthUnits = (int)params[0].value.number; + else + fprintf(stderr, "WARNING: HP-GL/2 \'WU\' command with invalid number of parameters (%d)!\n", + num_params); +} + + +/* + * End of "$Id$". + */ diff --git a/filter/hpgl-char.c b/filter/hpgl-char.c new file mode 100644 index 0000000000..75c72d8995 --- /dev/null +++ b/filter/hpgl-char.c @@ -0,0 +1,433 @@ +/* + * "$Id$" + * + * HP-GL/2 character processing for the Common UNIX Printing System (CUPS). + * + * Copyright 1993-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * AD_define_alternate() - Define the alternate font. + * CF_character_fill() - Set whether or not to fill or outline + * characters. + * CP_character_plot() - Move the current pen position for the given + * number of columns and rows. + * DI_absolute_direction() - Set the direction vector for text. + * DR_relative_direction() - Set the relative direction vector for text. + * DT_define_label_term() - Set the label string terminator. + * DV_define_variable_path() - Define a path for text. + * ES_extra_space() - Set extra spacing (kerning) between characters. + * LB_label() - Display a label string. + * LO_label_origin() - Set the label origin. + * SA_select_alternate() - Select the alternate font. + * SD_define_standard() - Define the standard font... + * SI_absolute_size() - Set the absolute size of text. + * SL_character_slant() - Set the slant of text. + * SR_relative_size() - Set the relative size of text. + * SS_select_standard() - Select the standard font for text. + * TD_transparent_data() - Send transparent print data. + */ + +/* + * Include necessary headers... + */ + +#include "hpgltops.h" + + +/* + * 'AD_define_alternate()' - Define the alternate font. + */ + +void +AD_define_alternate(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + int i; /* Looping var */ + int typeface, /* Typeface number */ + posture, /* Posture number */ + weight; /* Weight number */ + float height; /* Height/size of font */ + + + /* + * Set default font attributes... + */ + + typeface = 48; + posture = 0; + weight = 0; + height = 11.5; + + /* + * Loop through parameter value pairs... + */ + + for (i = 0; i < (num_params - 1); i += 2) + switch ((int)params[i].value.number) + { + case 4 : + height = params[i + 1].value.number; + break; + case 5 : + posture = (int)params[i + 1].value.number; + break; + case 6 : + weight = (int)params[i + 1].value.number; + break; + case 7 : + typeface = (int)params[i + 1].value.number; + break; + } + + /* + * Define the font... + */ + + Outputf("/SA { /%s%s%s%s findfont %.1f scalefont setfont } def\n", + typeface == 48 ? "Courier" : "Helvetica", + (weight != 0 || posture != 0) ? "-" : "", + weight != 0 ? "Bold" : "", + posture != 0 ? "Oblique" : "", + height); + + CharHeight[1] = height; +} + + +/* + * 'CF_character_fill()' - Set whether or not to fill or outline characters. + */ + +void +CF_character_fill(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + if (num_params == 0) + CharFillMode = 0; + else + CharFillMode = (int)params[0].value.number; + + if (num_params == 2) + CharPen = (int)params[1].value.number; +} + + +/* + * 'CP_character_plot()' - Move the current pen position for the given number + * of columns and rows. + */ + +void +CP_character_plot(int num_params, + param_t *params) +{ + if (num_params < 2) + return; + + switch (Rotation) + { + case 0: + PenPosition[0] += params[0].value.number * 1.2f / CharHeight[CharFont]; + PenPosition[1] += params[1].value.number * CharHeight[CharFont]; + break; + case 90: + PenPosition[0] -= params[1].value.number * 1.2f / CharHeight[CharFont]; + PenPosition[1] += params[0].value.number * CharHeight[CharFont]; + break; + case 180: + PenPosition[0] -= params[0].value.number * 1.2f / CharHeight[CharFont]; + PenPosition[1] -= params[1].value.number * CharHeight[CharFont]; + break; + case 270: + PenPosition[0] += params[1].value.number * 1.2f / CharHeight[CharFont]; + PenPosition[1] -= params[0].value.number * CharHeight[CharFont]; + break; + } +} + + +/* + * 'DI_absolute_direction()' - Set the direction vector for text. + */ + +void +DI_absolute_direction(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + Outputf(CharFont == 0 ? "SS\n" : "SA\n"); + + if (num_params == 2) + Outputf("currentfont [ %f %f %f %f 0.0 0.0 ] makefont setfont\n", + params[0].value.number, -params[1].value.number, + params[1].value.number, params[0].value.number); +} + + +/* + * 'DR_relative_direction()' - Set the relative direction vector for text. + */ + +void +DR_relative_direction(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + (void)num_params; + (void)params; +} + + +/* + * 'DT_define_label_term()' - Set the label string terminator. + */ + +void +DT_define_label_term(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + if (num_params == 0) + StringTerminator = '\003'; + else + StringTerminator = params[0].value.string[0]; +} + + +/* + * 'DV_define_variable_path()' - Define a path for text. + */ + +void +DV_define_variable_path(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + (void)num_params; + (void)params; +} + + +/* + * 'ES_extra_space()' - Set extra spacing (kerning) between characters. + */ + +void +ES_extra_space(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + (void)num_params; + (void)params; +} + + +/* + * 'LB_label()' - Display a label string. + */ + +void +LB_label(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + char *s; /* Pointer into string */ + + + if (num_params == 0) + return; + + Outputf("gsave\n"); + Outputf("currentmiterlimit 1.0 setmiterlimit\n"); + Outputf("MP\n"); + Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]); + + Outputf("("); + for (s = params[0].value.string; *s != '\0'; s ++) + if (strchr("()\\", *s) != NULL) + Outputf("\\%c", *s); + else + Outputf("%c", *s); + Outputf(") true charpath\n"); + + if (CharFillMode != 1) + Outputf("FI\n"); + if (CharFillMode == 1 || CharFillMode == 3) + Outputf("P%d ST\n", CharPen); + + Outputf("setmiterlimit\n"); + Outputf("grestore\n"); +} + + +/* + * 'LO_label_origin()' - Set the label origin. + */ + +void +LO_label_origin(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + (void)num_params; + (void)params; +} + + +/* + * 'SA_select_alternate()' - Select the alternate font. + */ + +void +SA_select_alternate(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + (void)num_params; + (void)params; + + Outputf("SA\n"); + CharFont = 1; +} + + +/* + * 'SD_define_standard()' - Define the standard font... + */ + +void +SD_define_standard(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + int i; /* Looping var */ + int typeface, /* Typeface number */ + posture, /* Posture number */ + weight; /* Weight number */ + float height; /* Height/size of font */ + + + /* + * Set default font attributes... + */ + + typeface = 48; + posture = 0; + weight = 0; + height = 11.5; + + /* + * Loop through parameter value pairs... + */ + + for (i = 0; i < (num_params - 1); i += 2) + switch ((int)params[i].value.number) + { + case 4 : + height = params[i + 1].value.number; + break; + case 5 : + posture = (int)params[i + 1].value.number; + break; + case 6 : + weight = (int)params[i + 1].value.number; + break; + case 7 : + typeface = (int)params[i + 1].value.number; + break; + } + + /* + * Define the font... + */ + + Outputf("/SS { /%s%s%s%s findfont %.1f scalefont setfont } def\n", + typeface == 48 ? "Courier" : "Helvetica", + (weight != 0 || posture != 0) ? "-" : "", + weight != 0 ? "Bold" : "", + posture != 0 ? "Oblique" : "", + height); + + CharHeight[0] = height; +} + + +/* + * 'SI_absolute_size()' - Set the absolute size of text. + */ + +void +SI_absolute_size(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + (void)num_params; + (void)params; +} + + +/* + * 'SL_character_slant()' - Set the slant of text. + */ + +void +SL_character_slant(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + (void)num_params; + (void)params; +} + + +/* + * 'SR_relative_size()' - Set the relative size of text. + */ + +void +SR_relative_size(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + (void)num_params; + (void)params; +} + + +/* + * 'SS_select_standard()' - Select the standard font for text. + */ + +void +SS_select_standard(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + (void)num_params; + (void)params; + + Outputf("SS\n"); + CharFont = 0; +} + + +/* + * 'TD_transparent_data()' - Send transparent print data. + */ + +void +TD_transparent_data(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + (void)num_params; + (void)params; +} + + +/* + * End of "$Id$". + */ diff --git a/filter/hpgl-config.c b/filter/hpgl-config.c new file mode 100644 index 0000000000..729a67aa63 --- /dev/null +++ b/filter/hpgl-config.c @@ -0,0 +1,473 @@ +/* + * "$Id$" + * + * HP-GL/2 configuration routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1993-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * update_transform() - Update the page transformation matrix as needed. + * BP_begin_plot() - Start a plot... + * DF_default_values() - Set all state info to the default values. + * IN_initialize() - Initialize the plotter. + * IP_input_absolute() - Set P1 and P2 values for the plot. + * IR_input_relative() - Update P1 and P2. + * IW_input_window() - Setup an input window. + * PG_advance_page() - Eject the current page. + * PS_plot_size() - Set the plot size. + * RO_rotate() - Rotate the plot. + * RP_replot() - Replot the current page. + * SC_scale() - Set user-defined scaling. + */ + +/* + * Include necessary headers... + */ + +#include "hpgltops.h" + + +/* + * 'update_transform()' - Update the page transformation matrix as needed. + */ + +void +update_transform(void) +{ + float width, /* Plot width */ + height; /* Plot height */ + float page_width, /* Actual page width in points */ + page_length; /* Actual page length in points */ + float scaling; /* Scaling factor */ + + + /* + * Get the page and input window sizes... + */ + + width = IW2[0] - IW1[0]; + height = IW2[1] - IW1[1]; + + if (width == 0 || height == 0) + return; + + /* + * Scale the plot as needed... + */ + + if (FitPlot) + { + page_width = PageRight - PageLeft; + page_length = PageTop - PageBottom; + + if (Rotation == 0 || Rotation == 180) + { + scaling = page_width / width; + if (scaling > (page_length / width)) + scaling = page_length / width; + } + else + { + scaling = page_width / height; + if (scaling > (page_length / height)) + scaling = page_length / height; + } + } + else + { + page_width = PlotSize[0]; + page_length = PlotSize[1]; + + if (Rotation == 0 || Rotation == 180) + scaling = page_width / width; + else + scaling = page_width / height; + } + + /* + * Generate a new transformation matrix... + */ + + switch (Rotation) + { + case 0 : + Transform[0][0] = scaling; + Transform[0][1] = 0.0; + Transform[0][2] = -IW1[0] * scaling; + Transform[1][0] = 0.0; + Transform[1][1] = scaling; + Transform[1][2] = -IW1[1] * scaling; + break; + + case 90 : + Transform[0][0] = 0.0; + Transform[0][1] = -scaling; + Transform[0][2] = (height - IW1[0]) * scaling; + Transform[1][0] = scaling; + Transform[1][1] = 0.0; + Transform[1][2] = -IW1[1] * scaling; + break; + + case 180 : + Transform[0][0] = -scaling; + Transform[0][1] = 0.0; + Transform[0][2] = (height - IW1[0]) * scaling; + Transform[1][0] = 0.0; + Transform[1][1] = -scaling; + Transform[1][2] = (width - IW1[1]) * scaling; + break; + + case 270 : + Transform[0][0] = 0.0; + Transform[0][1] = scaling; + Transform[0][2] = -IW1[0] * scaling; + Transform[1][0] = -scaling; + Transform[1][1] = 0.0; + Transform[1][2] = (width - IW1[1]) * scaling; + break; + } + + PenScaling = Transform[0][0] + Transform[0][1]; + + if (PenScaling < 0.0) + PenScaling = -PenScaling; + + if (PageDirty) + printf("/PenScaling %.3f def W%d\n", PenScaling, PenNumber); +} + + +/* + * 'BP_begin_plot()' - Start a plot... + */ + +void +BP_begin_plot(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + (void)num_params; + (void)params; +} + + +/* + * 'DF_default_values()' - Set all state info to the default values. + */ + +void +DF_default_values(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + (void)num_params; + (void)params; + + AC_anchor_corner(0, NULL); + AD_define_alternate(0, NULL); + SD_define_standard(0, NULL); + CF_character_fill(0, NULL); + DI_absolute_direction(0, NULL); + DT_define_label_term(0, NULL); + DV_define_variable_path(0, NULL); + ES_extra_space(0, NULL); + FT_fill_type(0, NULL); + IW_input_window(0, NULL); + LA_line_attributes(0, NULL); + LO_label_origin(0, NULL); + LT_line_type(0, NULL); + PA_plot_absolute(0, NULL); + PolygonMode = 0; + RF_raster_fill(0, NULL); + SC_scale(0, NULL); + SM_symbol_mode(0, NULL); + SS_select_standard(0, NULL); + TD_transparent_data(0, NULL); + UL_user_line_type(0, NULL); +} + + +/* + * 'IN_initialize()' - Initialize the plotter. + */ + +void +IN_initialize(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + (void)num_params; + (void)params; + + DF_default_values(0, NULL); + PU_pen_up(0, NULL); + RO_rotate(0, NULL); + PS_plot_size(0, NULL); + WU_width_units(0, NULL); + PW_pen_width(0, NULL); + SP_select_pen(0, NULL); + + PenPosition[0] = PenPosition[1] = 0.0; +} + + +/* + * 'IP_input_absolute()' - Set P1 and P2 values for the plot. + */ + +void +IP_input_absolute(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + if (num_params == 0) + { + P1[0] = 0.0; + P1[1] = 0.0; + P2[0] = PlotSize[0] / 72.0f * 1016.0f; + P2[1] = PlotSize[1] / 72.0f * 1016.0f; + } + else if (num_params == 2) + { + P2[0] -= P1[0]; + P2[1] -= P1[1]; + P1[0] = params[0].value.number; + P1[1] = params[1].value.number; + P2[0] += P1[0]; + P2[1] += P1[1]; + } + else if (num_params == 4) + { + P1[0] = params[0].value.number; + P1[1] = params[1].value.number; + P2[0] = params[2].value.number; + P2[1] = params[3].value.number; + } + + IW1[0] = P1[0]; + IW1[1] = P1[1]; + IW2[0] = P2[0]; + IW2[1] = P2[1]; + + update_transform(); +} + + +/* + * 'IR_input_relative()' - Update P1 and P2. + */ + +void +IR_input_relative(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + if (num_params == 0) + { + P1[0] = PageLeft / 72.0f * 1016.0f; + P1[1] = PageBottom / 72.0f * 1016.0f; + P2[0] = PageRight / 72.0f * 1016.0f; + P2[1] = PageTop / 72.0f * 1016.0f; + } + else if (num_params == 2) + { + P2[0] -= P1[0]; + P2[1] -= P1[1]; + P1[0] = params[0].value.number * PlotSize[0] / 72.0f * 1016.0f / 100.0f; + P1[1] = params[1].value.number * PlotSize[1] / 72.0f * 1016.0f / 100.0f; + P2[0] += P1[0]; + P2[1] += P1[1]; + } + else if (num_params == 4) + { + P1[0] = params[0].value.number * PlotSize[0] / 72.0f * 1016.0f / 100.0f; + P1[1] = params[1].value.number * PlotSize[1] / 72.0f * 1016.0f / 100.0f; + P2[0] = params[2].value.number * PlotSize[0] / 72.0f * 1016.0f / 100.0f; + P2[1] = params[3].value.number * PlotSize[1] / 72.0f * 1016.0f / 100.0f; + } + + IW1[0] = P1[0]; + IW1[1] = P1[1]; + IW2[0] = P2[0]; + IW2[1] = P2[1]; + + update_transform(); +} + + +/* + * 'IW_input_window()' - Setup an input window. + */ + +void +IW_input_window(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + if (num_params == 0) + { + IW1[0] = P1[0]; + IW1[1] = P1[1]; + IW2[0] = P2[0]; + IW2[1] = P2[1]; + } + else if (num_params == 4) + { + IW1[0] = params[0].value.number; + IW1[1] = params[1].value.number; + IW2[0] = params[2].value.number; + IW2[1] = params[3].value.number; + } + + update_transform(); +} + + +/* + * 'PG_advance_page()' - Eject the current page. + */ + +void +PG_advance_page(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + (void)num_params; + (void)params; + + if (PageDirty) + { + puts("grestore"); + puts("showpage"); + + PageDirty = 0; + } +} + + +/* + * 'PS_plot_size()' - Set the plot size. + */ + +void +PS_plot_size(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + switch (num_params) + { + case 0 : + if (Rotation == 0 || Rotation == 180) + { + PlotSize[0] = PageRight - PageLeft; + PlotSize[1] = PageTop - PageBottom; + } + else + { + PlotSize[0] = PageTop - PageBottom; + PlotSize[1] = PageRight - PageLeft; + } + break; + case 1 : + if (Rotation == 0 || Rotation == 180) + { + PlotSize[1] = 72.0f * params[0].value.number / 1016.0f; + PlotSize[0] = 0.75f * PlotSize[1]; + } + else + { + PlotSize[0] = 72.0f * params[0].value.number / 1016.0f; + PlotSize[1] = 0.75f * PlotSize[0]; + } + break; + case 2 : + if (Rotation == 0 || Rotation == 180) + { + PlotSize[0] = 72.0f * params[1].value.number / 1016.0f; + PlotSize[1] = 72.0f * params[0].value.number / 1016.0f; + } + else + { + PlotSize[0] = 72.0f * params[0].value.number / 1016.0f; + PlotSize[1] = 72.0f * params[1].value.number / 1016.0f; + } + break; + } + + /* + * This is required for buggy files that don't set the input window. + */ + + IP_input_absolute(0, NULL); +} + + +/* + * 'RO_rotate()' - Rotate the plot. + */ + +void +RO_rotate(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + if (num_params == 0) + Rotation = 0; + else + Rotation = (int)params[0].value.number; + + update_transform(); +} + + +/* + * 'RP_replot()' - Replot the current page. + */ + +void +RP_replot(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + (void)num_params; + (void)params; +} + + +/* + * 'SC_scale()' - Set user-defined scaling. + */ + +void +SC_scale(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + if (num_params == 0) + ScalingType = -1; + else if (num_params > 3) + { + Scaling1[0] = params[0].value.number; + Scaling2[0] = params[1].value.number; + Scaling1[1] = params[2].value.number; + Scaling2[1] = params[3].value.number; + + if (num_params > 4) + ScalingType = (int)params[4].value.number; + else + ScalingType = 0; + } + + update_transform(); +} + + +/* + * End of "$Id$". + */ diff --git a/filter/hpgl-input.c b/filter/hpgl-input.c new file mode 100644 index 0000000000..212dabc4ac --- /dev/null +++ b/filter/hpgl-input.c @@ -0,0 +1,232 @@ +/* + * "$Id$" + * + * HP-GL/2 input processing for the Common UNIX Printing System (CUPS). + * + * Copyright 1993-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * ParseCommand() - Parse an HPGL/2 command. + * FreeParameters() - Free all string parameter values. + */ + +/* + * Include necessary headers... + */ + +#include "hpgltops.h" +#include + +#define MAX_PARAMS 16384 + + +/* + * 'ParseCommand()' - Parse an HPGL/2 command. + * + * Returns the number of parameters seen or -1 on EOF. + */ + +int /* O - -1 on EOF, # params otherwise */ +ParseCommand(FILE *fp, /* I - File to read from */ + char *name, /* O - Name of command */ + param_t **params) /* O - Parameter list */ +{ + int num_params, /* Number of parameters seen */ + ch, /* Current char */ + done, /* Non-zero when the current command is read */ + i; /* Looping var */ + char buf[262144]; /* String buffer */ + static param_t p[MAX_PARAMS]; /* Parameter buffer */ + + + num_params = 0; + done = 0; + + do + { + while ((ch = getc(fp)) != EOF) + if (strchr(" \t\r\n,;", ch) == NULL) + break; + + if (ch == EOF) + return (-1); + + if (ch == 0x1b) + switch (getc(fp)) + { + case '.' : /* HP-GL/2 job control */ + i = getc(fp); + + if (strchr(")Z", i) != NULL) + { + /* + * 'Printer Off' command - look for next 'Printer On' command... + */ + + for (;;) + { + while ((i = getc(fp)) != EOF && i != 0x1b); + + if (i == EOF) + return (-1); + + if (getc(fp) != '.') + continue; + + if ((i = getc(fp)) == '(' || + i == 'Y') + break; + } + } + else if (strchr("@HIMNTI\003", i) != NULL) + { + while ((i = getc(fp)) != EOF && i != ':'); + } + break; + + default : /* HP RTL/PCL control */ + while ((i = getc(fp)) != EOF && !isupper(i)); + break; + } + } while (ch == 0x1b); + + name[0] = ch; + name[1] = getc(fp); + name[2] = '\0'; + + if (strcasecmp(name, "LB") == 0) + { + for (i = 0; (ch = getc(fp)) != StringTerminator; i ++) + buf[i] = ch; + buf[i] = '\0'; + p[num_params].type = PARAM_STRING; + p[num_params].value.string = strdup(buf); + num_params ++; + } + else if (strcasecmp(name, "SM") == 0) + { + buf[0] = getc(fp); + buf[1] = '\0'; + p[num_params].type = PARAM_STRING; + p[num_params].value.string = strdup(buf); + num_params ++; + } + else if (strcasecmp(name, "DT") == 0) + { + if ((buf[0] = getc(fp)) != ';') + { + buf[1] = '\0'; + p[num_params].type = PARAM_STRING; + p[num_params].value.string = strdup(buf); + num_params ++; + } + } + else if (strcasecmp(name, "PE") == 0) + { + for (i = 0; i < (sizeof(buf) - 1); i ++) + if ((buf[i] = getc(fp)) == ';') + break; + + buf[i] = '\0'; + p[num_params].type = PARAM_STRING; + p[num_params].value.string = strdup(buf); + num_params ++; + } + + while (!done) + switch (ch = getc(fp)) + { + case ',' : + case ' ' : + case '\n' : + case '\r' : + case '\t' : + break; + + case '\"' : + fscanf(fp, "%[^\"]\"", buf); + if (num_params < MAX_PARAMS) + { + p[num_params].type = PARAM_STRING; + p[num_params].value.string = strdup(buf); + num_params ++; + }; + break; + + case '-' : + case '+' : + ungetc(ch, fp); + fscanf(fp, "%f", &(p[num_params].value.number)); + if (num_params < MAX_PARAMS) + { + p[num_params].type = PARAM_RELATIVE; + num_params ++; + } + break; + case '0' : + case '1' : + case '2' : + case '3' : + case '4' : + case '5' : + case '6' : + case '7' : + case '8' : + case '9' : + case '.' : + ungetc(ch, fp); + fscanf(fp, "%f", &(p[num_params].value.number)); + if (num_params < MAX_PARAMS) + { + p[num_params].type = PARAM_ABSOLUTE; + num_params ++; + } + break; + default : + ungetc(ch, fp); + done = 1; + break; + } + + *params = p; + return (num_params); +} + + +/* + * 'FreeParameters()' - Free all string parameter values. + */ + +void +FreeParameters(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameter values */ +{ + int i; /* Looping var */ + + + for (i = 0; i < num_params; i ++) + if (params[i].type == PARAM_STRING) + free(params[i].value.string); +} + + +/* + * End of "$Id$". + */ diff --git a/filter/hpgl-main.c b/filter/hpgl-main.c new file mode 100644 index 0000000000..329988cd78 --- /dev/null +++ b/filter/hpgl-main.c @@ -0,0 +1,255 @@ +/* + * "$Id$" + * + * HP-GL/2 filter main entry for the Common UNIX Printing System (CUPS). + * + * Copyright 1993-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * main() - Main entry for HP-GL/2 filter. + * compare_names() - Compare two command names. + */ + +/* + * Include necessary headers... + */ + +/*#define DEBUG*/ +#define _HPGL_MAIN_C_ +#include "hpgltops.h" + + +/* + * HP-GL/2 command table... + */ + +typedef struct +{ + char name[4]; /* Name of command */ + void (*func)(int, param_t *); /* Function to call */ +} name_t; + +static name_t commands[] = +{ + { "BP", BP_begin_plot }, + { "DF", DF_default_values }, + { "IN", IN_initialize }, + { "IP", IP_input_absolute }, + { "IR", IR_input_relative }, + { "IW", IW_input_window }, + { "PG", PG_advance_page }, + { "RO", RO_rotate }, + { "RP", RP_replot }, + { "SC", SC_scale }, + { "AA", AA_arc_absolute }, + { "AR", AR_arc_relative }, + { "AT", AT_arc_absolute3 }, + { "CI", CI_circle }, + { "PA", PA_plot_absolute }, + { "PD", PD_pen_down }, + { "PE", PE_polyline_encoded }, + { "PR", PR_plot_relative }, + { "PS", PS_plot_size }, + { "PU", PU_pen_up }, + { "RT", RT_arc_relative3 }, + { "EA", EA_edge_rect_absolute }, + { "EP", EP_edge_polygon }, + { "ER", ER_edge_rect_relative }, + { "EW", EW_edge_wedge }, + { "FP", FP_fill_polygon }, + { "PM", PM_polygon_mode }, + { "RA", RA_fill_rect_absolute }, + { "RR", RR_fill_rect_relative }, + { "WG", WG_fill_wedge }, + { "AD", AD_define_alternate }, + { "CF", CF_character_fill }, + { "CP", CP_character_plot }, + { "DI", DI_absolute_direction }, + { "DR", DR_relative_direction }, + { "DT", DT_define_label_term }, + { "DV", DV_define_variable_path }, + { "ES", ES_extra_space }, + { "LB", LB_label }, + { "LO", LO_label_origin }, + { "SA", SA_select_alternate }, + { "SD", SD_define_standard }, + { "SI", SI_absolute_size }, + { "SL", SL_character_slant }, + { "SR", SR_relative_size }, + { "SS", SS_select_standard }, + { "TD", TD_transparent_data }, + { "AC", AC_anchor_corner }, + { "FT", FT_fill_type }, + { "LA", LA_line_attributes }, + { "LT", LT_line_type }, + { "NP", NP_number_pens }, + { "PC", PC_pen_color }, + { "CR", CR_color_range }, + { "PW", PW_pen_width }, + { "RF", RF_raster_fill }, + { "SM", SM_symbol_mode }, + { "SP", SP_select_pen }, + { "UL", UL_user_line_type }, + { "WU", WU_width_units } +}; +#define NUM_COMMANDS (sizeof(commands) / sizeof(name_t)) + + +/* + * Local functions... + */ + +static int compare_names(const void *p1, const void *p2); + + +/* + * 'main()' - Main entry for HP-GL/2 filter. + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line arguments */ + char *argv[]) /* I - Command-line arguments */ +{ + FILE *fp; /* Input file */ + ppd_file_t *ppd; /* PPD file */ + int num_params; /* Number of parameters */ + param_t *params; /* Command parameters */ + name_t *command, /* Command */ + name; /* Name of command */ + int num_options; /* Number of print options */ + cups_option_t *options; /* Print options */ + char *val; /* Option value */ + int shading; /* -1 = black, 0 = grey, 1 = color */ + float penwidth; /* Default pen width */ + + + if (argc < 6 || argc > 7) + { + fputs("ERROR: hpgltops job-id user title copies options [file]\n", stderr); + return (1); + } + + /* + * If we have 7 arguments, print the file named on the command-line. + * Otherwise, send stdin instead... + */ + + if (argc == 6) + fp = stdin; + else + { + /* + * Try to open the print file... + */ + + if ((fp = fopen(argv[6], "rb")) == NULL) + { + perror("ERROR: unable to open print file - "); + return (1); + } + } + + /* + * Process command-line options and write the prolog... + */ + + options = NULL; + num_options = cupsParseOptions(argv[5], 0, &options); + + if ((ppd = SetCommonOptions(num_options, options, 1)) != NULL) + ppdClose(ppd); + + shading = 1; + penwidth = 1.0; + + if ((val = cupsGetOption("blackplot", num_options, options)) != NULL) + shading = 0; + + if ((val = cupsGetOption("fitplot", num_options, options)) != NULL) + FitPlot = 1; + + if ((val = cupsGetOption("penwidth", num_options, options)) != NULL) + penwidth = (float)atof(val); + + /* + * Write the PostScript prolog and initialize the plotting "engine"... + */ + + OutputProlog(argv[3], argv[2], shading, penwidth); + + IP_input_absolute(0, NULL); + + /* + * Sort the command array... + */ + + qsort(commands, NUM_COMMANDS, sizeof(name_t), + (int (*)(const void *, const void *))compare_names); + + /* + * Read commands until we reach the end of file. + */ + + while ((num_params = ParseCommand(fp, name.name, ¶ms)) >= 0) + { +#ifdef DEBUG + { + int i; + fprintf(stderr, "DEBUG: %s(%d)", name.name, num_params); + for (i = 0; i < num_params; i ++) + if (params[i].type == PARAM_STRING) + fprintf(stderr, " \'%s\'", params[i].value.string); + else + fprintf(stderr, " %f", params[i].value.number); + fputs("\n", stderr); + } +#endif /* DEBUG */ + + if ((command = bsearch(&name, commands, NUM_COMMANDS, sizeof(name_t), + (int (*)(const void *, const void *))compare_names)) != NULL) + (*command->func)(num_params, params); + + FreeParameters(num_params, params); + } + + OutputTrailer(); + + if (fp != stdin) + fclose(fp); + + return (0); +} + + +/* + * 'compare_names()' - Compare two command names. + */ + +static int /* O - Result of strcasecmp() on names */ +compare_names(const void *p1, /* I - First name */ + const void *p2) /* I - Second name */ +{ + return (strcasecmp(((name_t *)p1)->name, ((name_t *)p2)->name)); +} + + +/* + * End of "$Id$". + */ diff --git a/filter/hpgl-polygon.c b/filter/hpgl-polygon.c new file mode 100644 index 0000000000..f16f8649d2 --- /dev/null +++ b/filter/hpgl-polygon.c @@ -0,0 +1,380 @@ +/* + * "$Id$" + * + * HP-GL/2 polygon routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1993-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * EA_edge_rect_absolute() - Draw a rectangle. + * EP_edge_polygon() - Stroke the edges of a polygon. + * ER_edge_rect_relative() - Draw a rectangle relative to the current + * EW_edge_wedge() - Draw a pie wedge. + * FP_fill_polygon() - Fill a polygon. + * PM_polygon_mode() - Set the polygon drawing mode. + * RA_fill_rect_absolute() - Fill a rectangle. + * RR_fill_rect_relative() - Fill a rectangle relative to the current + * WG_fill_wedge() - Fill a pie wedge. + */ + +/* + * Include necessary headers... + */ + +#include "hpgltops.h" + + +/* + * 'EA_edge_rect_absolute()' - Draw a rectangle. + */ + +void +EA_edge_rect_absolute(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + float x, y; /* Transformed coordinates */ + + + if (num_params < 2) + return; + + x = Transform[0][0] * params[0].value.number + + Transform[0][1] * params[1].value.number + + Transform[0][2]; + y = Transform[1][0] * params[0].value.number + + Transform[1][1] * params[1].value.number + + Transform[1][2]; + + if (!PolygonMode) + Outputf("MP\n"); + + Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]); + Outputf("%.3f %.3f LI\n", PenPosition[0], y); + Outputf("%.3f %.3f LI\n", x, y); + Outputf("%.3f %.3f LI\n", x, PenPosition[1]); + + Outputf("CP\n"); + if (!PolygonMode) + Outputf("ST\n"); +} + + +/* + * 'EP_edge_polygon()' - Stroke the edges of a polygon. + */ + +void +EP_edge_polygon(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + (void)num_params; + (void)params; + + Outputf("ST\n"); +} + + +/* + * 'ER_edge_rect_relative()' - Draw a rectangle relative to the current + * pen position. + */ + +void +ER_edge_rect_relative(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + float x, y; /* Transformed coordinates */ + + + if (num_params < 2) + return; + + x = Transform[0][0] * params[0].value.number + + Transform[0][1] * params[1].value.number + + PenPosition[0]; + y = Transform[1][0] * params[0].value.number + + Transform[1][1] * params[1].value.number + + PenPosition[1]; + + if (!PolygonMode) + Outputf("MP\n"); + + Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]); + Outputf("%.3f %.3f LI\n", PenPosition[0], y); + Outputf("%.3f %.3f LI\n", x, y); + Outputf("%.3f %.3f LI\n", x, PenPosition[1]); + + Outputf("CP\n"); + if (!PolygonMode) + Outputf("ST\n"); +} + + +/* + * 'EW_edge_wedge()' - Draw a pie wedge. + */ + +void +EW_edge_wedge(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + float x, y; /* Transformed coordinates */ + float start, end, /* Start and end of arc */ + theta, /* Current angle */ + dt, /* Step between points */ + radius; /* Radius of arc */ + + + if (num_params < 3) + return; + + radius = params[0].value.number; + start = params[1].value.number; + end = start + params[2].value.number; + + if (num_params > 3) + dt = (float)fabs(params[3].value.number); + else + dt = 5.0f; + + if (!PolygonMode) + Outputf("MP\n"); + + Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]); + + if (start < end) + for (theta = start + dt; theta < end; theta += dt) + { + x = (float)(PenPosition[0] + + radius * cos(M_PI * theta / 180.0) * Transform[0][0] + + radius * sin(M_PI * theta / 180.0) * Transform[0][1]); + y = (float)(PenPosition[1] + + radius * cos(M_PI * theta / 180.0) * Transform[1][0] + + radius * sin(M_PI * theta / 180.0) * Transform[1][1]); + + Outputf("%.3f %.3f LI\n", x, y); + } + else + for (theta = start - dt; theta > end; theta -= dt) + { + x = (float)(PenPosition[0] + + radius * cos(M_PI * theta / 180.0) * Transform[0][0] + + radius * sin(M_PI * theta / 180.0) * Transform[0][1]); + y = (float)(PenPosition[1] + + radius * cos(M_PI * theta / 180.0) * Transform[1][0] + + radius * sin(M_PI * theta / 180.0) * Transform[1][1]); + + Outputf("%.3f %.3f LI\n", x, y); + } + + x = (float)(PenPosition[0] + + radius * cos(M_PI * end / 180.0) * Transform[0][0] + + radius * sin(M_PI * end / 180.0) * Transform[0][1]); + y = (float)(PenPosition[1] + + radius * cos(M_PI * end / 180.0) * Transform[1][0] + + radius * sin(M_PI * end / 180.0) * Transform[1][1]); + Outputf("%.3f %.3f LI\n", x, y); + + Outputf("CP\n"); + if (!PolygonMode) + Outputf("ST\n"); +} + + +/* + * 'FP_fill_polygon()' - Fill a polygon. + */ + +void +FP_fill_polygon(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + (void)num_params; + (void)params; + + Outputf("FI\n"); +} + + +/* + * 'PM_polygon_mode()' - Set the polygon drawing mode. + */ + +void +PM_polygon_mode(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + if (num_params == 0 || + params[0].value.number == 0) + { + Outputf("MP\n"); + Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]); + PolygonMode = 1; + } + else if (params[0].value.number == 2) + PolygonMode = 0; +} + + +/* + * 'RA_fill_rect_absolute()' - Fill a rectangle. + */ + +void +RA_fill_rect_absolute(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + float x, y; /* Transformed coordinates */ + + + if (num_params < 2) + return; + + x = Transform[0][0] * params[0].value.number + + Transform[0][1] * params[1].value.number + + Transform[0][2]; + y = Transform[1][0] * params[0].value.number + + Transform[1][1] * params[1].value.number + + Transform[1][2]; + + if (!PolygonMode) + Outputf("MP\n"); + + Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]); + Outputf("%.3f %.3f LI\n", PenPosition[0], y); + Outputf("%.3f %.3f LI\n", x, y); + Outputf("%.3f %.3f LI\n", x, PenPosition[1]); + + Outputf("CP\n"); + if (!PolygonMode) + Outputf("FI\n"); +} + + +/* + * 'RR_fill_rect_relative()' - Fill a rectangle relative to the current + * pen position. + */ + +void +RR_fill_rect_relative(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + float x, y; /* Transformed coordinates */ + + + if (num_params < 2) + return; + + x = Transform[0][0] * params[0].value.number + + Transform[0][1] * params[1].value.number + + PenPosition[0]; + y = Transform[1][0] * params[0].value.number + + Transform[1][1] * params[1].value.number + + PenPosition[1]; + + if (!PolygonMode) + Outputf("MP\n"); + + Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]); + Outputf("%.3f %.3f LI\n", PenPosition[0], y); + Outputf("%.3f %.3f LI\n", x, y); + Outputf("%.3f %.3f LI\n", x, PenPosition[1]); + + Outputf("CP\n"); + if (!PolygonMode) + Outputf("FI\n"); +} + + +/* + * 'WG_fill_wedge()' - Fill a pie wedge. + */ + +void +WG_fill_wedge(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + float x, y; /* Transformed coordinates */ + float start, end, /* Start and end angles */ + theta, /* Current angle */ + dt, /* Step between points */ + radius; /* Radius of arc */ + + + if (num_params < 3) + return; + + radius = params[0].value.number; + start = params[1].value.number; + end = start + params[2].value.number; + + if (num_params > 3) + dt = (float)fabs(params[3].value.number); + else + dt = 5.0; + + if (!PolygonMode) + Outputf("MP\n"); + + Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]); + + if (start < end) + for (theta = start + dt; theta < end; theta += dt) + { + x = (float)(PenPosition[0] + + radius * cos(M_PI * theta / 180.0) * Transform[0][0] + + radius * sin(M_PI * theta / 180.0) * Transform[0][1]); + y = (float)(PenPosition[1] + + radius * cos(M_PI * theta / 180.0) * Transform[1][0] + + radius * sin(M_PI * theta / 180.0) * Transform[1][1]); + + Outputf("%.3f %.3f LI\n", x, y); + } + else + for (theta = start - dt; theta > end; theta -= dt) + { + x = (float)(PenPosition[0] + + radius * cos(M_PI * theta / 180.0) * Transform[0][0] + + radius * sin(M_PI * theta / 180.0) * Transform[0][1]); + y = (float)(PenPosition[1] + + radius * cos(M_PI * theta / 180.0) * Transform[1][0] + + radius * sin(M_PI * theta / 180.0) * Transform[1][1]); + + Outputf("%.3f %.3f LI\n", x, y); + } + + x = (float)(PenPosition[0] + + radius * cos(M_PI * end / 180.0) * Transform[0][0] + + radius * sin(M_PI * end / 180.0) * Transform[0][1]); + y = (float)(PenPosition[1] + + radius * cos(M_PI * end / 180.0) * Transform[1][0] + + radius * sin(M_PI * end / 180.0) * Transform[1][1]); + Outputf("%.3f %.3f LI\n", x, y); + + Outputf("CP\n"); + if (!PolygonMode) + Outputf("FI\n"); +} + + +/* + * End of "$Id$". + */ diff --git a/filter/hpgl-prolog.c b/filter/hpgl-prolog.c new file mode 100644 index 0000000000..1a485fe584 --- /dev/null +++ b/filter/hpgl-prolog.c @@ -0,0 +1,192 @@ +/* + * "$Id$" + * + * HP-GL/2 prolog routines for for the Common UNIX Printing System (CUPS). + * + * Copyright 1993-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * OutputProlog() - Output the PostScript prolog... + * OutputTrailer() - Output the PostScript trailer... + * Outputf() - Write a formatted string to the output file, creating the + * page header as needed... + */ + +/* + * Include necessary headers... + */ + +#include "hpgltops.h" +#include + + +/* + * 'OutputProlog()' - Output the PostScript prolog... + */ + +void +OutputProlog(char *title, /* I - Job title */ + char *user, /* I - Username */ + int shading, /* I - Type of shading */ + float penwidth) /* I - Default pen width */ +{ + FILE *prolog; /* Prolog file */ + char line[255]; /* Line from prolog file */ + time_t curtime; /* Current time */ + struct tm *curtm; /* Current date */ + + + curtime = time(NULL); + curtm = localtime(&curtime); + + puts("%!PS-Adobe-3.0"); + printf("%%%%BoundingBox: %.0f %.0f %.0f %.0f\n", + PageLeft, PageBottom, PageRight, PageTop); + puts("%%Pages: (atend)"); + printf("%%%%LanguageLevel: %d\n", LanguageLevel); + puts("%%DocumentData: Clean7Bit"); + puts("%%DocumentSuppliedResources: procset hpgltops 1.0 0"); + puts("%%DocumentNeededResources: font Courier Helvetica"); + puts("%%Creator: hpgltops/" CUPS_SVERSION); + strftime(line, sizeof(line), "%%%%CreationDate: %c", curtm); + puts(line); + printf("%%%%Title: %s\n", title); + printf("%%%%For: %s\n", user); + if (Orientation & 1) + puts("%%Orientation: Landscape"); + puts("%%EndComments"); + puts("%%BeginProlog"); + printf("/DefaultPenWidth %.2f def\n", penwidth * 72.0 / 25.4); + puts("3.0 setmiterlimit"); + if (!shading) /* Black only */ + puts("/setrgbcolor { pop pop pop } bind def"); + else if (!ColorDevice) /* Greyscale */ + puts("/setrgbcolor { 0.08 mul exch 0.61 mul add exch 0.31 mul add setgray } bind def\n"); + + if ((prolog = fopen(CUPS_DATADIR "/HPGLprolog", "r")) == NULL) + { + perror("ERROR: Unable to open HPGL prolog \"" CUPS_DATADIR "/HPGLprolog\" for reading"); + exit(1); + } + + while (fgets(line, sizeof(line), prolog) != NULL) + fputs(line, stdout); + + fclose(prolog); + + puts("%%EndProlog"); + + IN_initialize(0, NULL); +} + + +/* + * 'OutputTrailer()' - Output the PostScript trailer... + */ + +void +OutputTrailer(void) +{ + if (PageDirty) + PG_advance_page(0, NULL); + + puts("%%BeginTrailer"); + printf("%%%%Pages: %d\n", PageCount); + puts("%%EOF"); +} + + +/* + * 'Outputf()' - Write a formatted string to the output file, creating the + * page header as needed... + */ + +int /* O - Number of bytes written */ +Outputf(const char *format, /* I - Printf-style string */ + ...) /* I - Additional args as needed */ +{ + va_list ap; /* Argument pointer */ + int bytes; /* Number of bytes written */ + + + /* + * Write the page header as needed... + */ + + if (!PageDirty) + { + PageDirty = 1; + PageCount ++; + + printf("%%%%Page: %d %d\n", PageCount, PageCount); + printf("/PenScaling %.3f def\n", PenScaling); + puts("gsave"); + + if (Duplex && (PageCount & 1) == 0) + switch ((PageRotation / 90) & 3) + { + case 0 : + printf("%.1f %.1f translate\n", PageWidth - PageRight, PageBottom); + break; + case 1 : + printf("%.1f %.1f translate\n", PageLength - PageTop, + PageWidth - PageRight); + break; + case 2 : + printf("%.1f %.1f translate\n", PageLeft, PageLength - PageTop); + break; + case 3 : + printf("%.1f %.1f translate\n", PageBottom, PageLeft); + break; + } + else + switch ((PageRotation / 90) & 3) + { + case 0 : + printf("%.1f %.1f translate\n", PageLeft, PageBottom); + break; + case 1 : + printf("%.1f %.1f translate\n", PageBottom, PageWidth - PageRight); + break; + case 2 : + printf("%.1f %.1f translate\n", PageWidth - PageRight, + PageLength - PageTop); + break; + case 3 : + printf("%.1f %.1f translate\n", PageLength - PageTop, PageLeft); + break; + } + } + + /* + * Write the string to the output file... + */ + + va_start(ap, format); + bytes = vprintf(format, ap); + va_end(ap); + + return (bytes); +} + + +/* + * End of "$Id$". + */ diff --git a/filter/hpgl-vector.c b/filter/hpgl-vector.c new file mode 100644 index 0000000000..d900307b2a --- /dev/null +++ b/filter/hpgl-vector.c @@ -0,0 +1,704 @@ +/* + * "$Id$" + * + * HP-GL/2 vector routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1993-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * AA_arc_absolute() - Draw an arc. + * AR_arc_relative() - Draw an arc relative to the current pen + * AT_arc_absolute3() - Draw an arc using 3 points. + * CI_circle() - Draw a circle. + * PA_plot_absolute() - Plot a line using absolute coordinates. + * PD_pen_down() - Start drawing. + * PE_polygon_encoded() - Draw an encoded polyline. + * PR_plot_relative() - Plot a line using relative coordinates. + * PU_pen_up() - Stop drawing. + * RT_arc_relative3() - Draw an arc through 3 points relative to the + * decode_number() - Decode an encoded number. + * plot_points() - Plot the specified points. + */ + +/* + * Include necessary headers... + */ + +#include "hpgltops.h" + + +/* + * Local functions... + */ + +static double decode_number(unsigned char **, int, double); +static void plot_points(int, param_t *); + + +/* + * 'AA_arc_absolute()' - Draw an arc. + */ + +void +AA_arc_absolute(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + float x, y, /* Transformed coordinates */ + dx, dy; /* Distance from current pen */ + float start, end, /* Start and end angles */ + theta, /* Current angle */ + dt, /* Step between points */ + radius; /* Radius of arc */ + + + if (num_params < 3) + return; + + x = Transform[0][0] * params[0].value.number + + Transform[0][1] * params[1].value.number + + Transform[0][2]; + y = Transform[1][0] * params[0].value.number + + Transform[1][1] * params[1].value.number + + Transform[1][2]; + + dx = PenPosition[0] - x; + dy = PenPosition[1] - y; + + start = (float)(180.0 * atan2(dy, dx) / M_PI); + if (start < 0.0) + start += 360.0f; + + end = start + params[2].value.number; + radius = (float)hypot(dx, dy); + + if (PenDown) + { + if (num_params > 3 && params[3].value.number > 0.0) + dt = (float)fabs(params[3].value.number); + else + dt = 5.0; + + if (!PolygonMode) + Outputf("MP\n"); + + Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]); + + if (start < end) + for (theta = start + dt; theta < end; theta += dt) + { + PenPosition[0] = (float)(x + radius * cos(M_PI * theta / 180.0)); + PenPosition[1] = (float)(y + radius * sin(M_PI * theta / 180.0)); + + Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]); + } + else + for (theta = start - dt; theta > end; theta -= dt) + { + PenPosition[0] = (float)(x + radius * cos(M_PI * theta / 180.0)); + PenPosition[1] = (float)(y + radius * sin(M_PI * theta / 180.0)); + + Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]); + } + } + + PenPosition[0] = (float)(x + radius * cos(M_PI * end / 180.0)); + PenPosition[1] = (float)(y + radius * sin(M_PI * end / 180.0)); + + if (PenDown) + { + Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]); + + if (!PolygonMode) + Outputf("ST\n"); + } +} + + +/* + * 'AR_arc_relative()' - Draw an arc relative to the current pen + * position. + */ + +void +AR_arc_relative(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + float x, y, /* Transformed coordinates */ + dx, dy; /* Distance from current pen */ + float start, end, /* Start and end angles */ + theta, /* Current angle */ + dt, /* Step between points */ + radius; /* Radius of arc */ + + + if (num_params < 3) + return; + + x = Transform[0][0] * params[0].value.number + + Transform[0][1] * params[1].value.number + + PenPosition[0]; + y = Transform[1][0] * params[0].value.number + + Transform[1][1] * params[1].value.number + + PenPosition[1]; + + dx = PenPosition[0] - x; + dy = PenPosition[1] - y; + + start = (float)(180.0 * atan2(dy, dx) / M_PI); + if (start < 0.0) + start += 360.0f; + + end = start + params[2].value.number; + radius = (float)hypot(dx, dy); + + if (PenDown) + { + if (num_params > 3 && params[3].value.number > 0.0) + dt = (float)fabs(params[3].value.number); + else + dt = 5.0; + + if (!PolygonMode) + Outputf("MP\n"); + + Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]); + + if (start < end) + for (theta = start + dt; theta < end; theta += dt) + { + PenPosition[0] = (float)(x + radius * cos(M_PI * theta / 180.0)); + PenPosition[1] = (float)(y + radius * sin(M_PI * theta / 180.0)); + + Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]); + } + else + for (theta = start - dt; theta > end; theta -= dt) + { + PenPosition[0] = (float)(x + radius * cos(M_PI * theta / 180.0)); + PenPosition[1] = (float)(y + radius * sin(M_PI * theta / 180.0)); + + Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]); + } + } + + PenPosition[0] = (float)(x + radius * cos(M_PI * end / 180.0)); + PenPosition[1] = (float)(y + radius * sin(M_PI * end / 180.0)); + + if (PenDown) + { + Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]); + + if (!PolygonMode) + Outputf("ST\n"); + } +} + + +/* + * 'AT_arc_absolute3()' - Draw an arc using 3 points. + * + * Note: + * + * Currently this only draws two line segments through the + * specified points. + */ + +void +AT_arc_absolute3(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + if (num_params < 4) + return; + + if (PenDown) + { + if (!PolygonMode) + Outputf("MP\n"); + + Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]); + + PenPosition[0] = Transform[0][0] * params[0].value.number + + Transform[0][1] * params[1].value.number + + Transform[0][2]; + PenPosition[1] = Transform[1][0] * params[0].value.number + + Transform[1][1] * params[1].value.number + + Transform[1][2]; + + Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]); + } + + PenPosition[0] = Transform[0][0] * params[2].value.number + + Transform[0][1] * params[3].value.number + + Transform[0][2]; + PenPosition[1] = Transform[1][0] * params[2].value.number + + Transform[1][1] * params[3].value.number + + Transform[1][2]; + + if (PenDown) + { + Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]); + + if (!PolygonMode) + Outputf("ST\n"); + } +} + + +/* + * 'CI_circle()' - Draw a circle. + */ + +void +CI_circle(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + float x, y; /* Transformed coordinates */ + float theta, /* Current angle */ + dt, /* Step between points */ + radius; /* Radius of circle */ + + + if (num_params < 1) + return; + + if (!PenDown) + return; + + radius = params[0].value.number; + + if (num_params > 1) + dt = (float)fabs(params[1].value.number); + else + dt = 5.0; + + if (!PolygonMode) + Outputf("MP\n"); + + for (theta = 0.0; theta < 360.0; theta += dt) + { + x = (float)(PenPosition[0] + + radius * cos(M_PI * theta / 180.0) * Transform[0][0] + + radius * sin(M_PI * theta / 180.0) * Transform[0][1]); + y = (float)(PenPosition[1] + + radius * cos(M_PI * theta / 180.0) * Transform[1][0] + + radius * sin(M_PI * theta / 180.0) * Transform[1][1]); + + Outputf("%.3f %.3f %s\n", x, y, theta == 0.0 ? "MO" : "LI"); + } + + Outputf("CP\n"); + if (!PolygonMode) + Outputf("ST\n"); +} + + +/* + * 'PA_plot_absolute()' - Plot a line using absolute coordinates. + */ + +void +PA_plot_absolute(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + PenMotion = 0; + + if (num_params > 1) + plot_points(num_params, params); +} + + +/* + * 'PD_pen_down()' - Start drawing. + */ + +void +PD_pen_down(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + PenDown = 1; + + if (num_params > 1) + plot_points(num_params, params); +} + + +/* + * 'PE_polygon_encoded()' - Draw an encoded polyline. + */ + +void +PE_polyline_encoded(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + unsigned char *s; /* Pointer into string */ + int temp, /* Temporary value */ + base_bits, /* Data bits per byte */ + draw, /* Draw or move */ + abscoords; /* Use absolute coordinates */ + double tx, ty, /* Transformed coordinates */ + x, y, /* Raw coordinates */ + frac_bits; /* Multiplier for encoded number */ + + + base_bits = 6; + frac_bits = 1.0; + draw = 1; + abscoords = 0; + + if (num_params == 0) + return; + + if (!PolygonMode) + { + Outputf("MP\n"); + Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]); + } + + for (s = (unsigned char *)params[0].value.string; *s != '\0';) + switch (*s) + { + case '7' : + s ++; + base_bits = 5; + break; + case ':' : /* Select pen */ + s ++; + temp = (int)decode_number(&s, base_bits, 1.0); + Outputf("P%d W%d\n", temp, temp); + break; + case '<' : /* Next coords are a move-to */ + draw = 0; + s ++; + break; + case '>' : /* Set fractional bits */ + s ++; + temp = (int)decode_number(&s, base_bits, 1.0); + frac_bits = 1.0 / (1 << temp); + break; + case '=' : /* Next coords are absolute */ + s ++; + abscoords = 1; + break; + default : + if (*s >= 63) + { + /* + * Coordinate... + */ + + x = decode_number(&s, base_bits, frac_bits); + y = decode_number(&s, base_bits, frac_bits); + + if (abscoords) + { + tx = Transform[0][0] * x + Transform[0][1] * y + + Transform[0][2]; + ty = Transform[1][0] * x + Transform[1][1] * y + + Transform[1][2]; + } + else if (x == 0.0 && y == 0.0) + { + draw = 1; + continue; + } + else + { + tx = Transform[0][0] * x + Transform[0][1] * y + + PenPosition[0]; + ty = Transform[1][0] * x + Transform[1][1] * y + + PenPosition[1]; + } + + if (draw) + Outputf("%.3f %.3f LI\n", tx, ty); + else + Outputf("%.3f %.3f MO\n", tx, ty); + + PenPosition[0] = (float)tx; + PenPosition[1] = (float)ty; + + draw = 1; + abscoords = 0; + } + else + { + /* + * Junk - ignore... + */ + + if (*s != '\n' && *s != '\r') + fprintf(stderr, "WARNING: ignoring illegal PE char \'%c\'...\n", *s); + s ++; + } + break; + } + + if (!PolygonMode) + Outputf("ST\n"); +} + + +/* + * 'PR_plot_relative()' - Plot a line using relative coordinates. + */ + +void +PR_plot_relative(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + PenMotion = 1; + + if (num_params > 1) + plot_points(num_params, params); +} + + +/* + * 'PU_pen_up()' - Stop drawing. + */ + +void +PU_pen_up(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + PenDown = 0; + + if (num_params > 1) + plot_points(num_params, params); +} + + +/* + * 'RT_arc_relative3()' - Draw an arc through 3 points relative to the + * current pen position. + * + * Note: + * + * This currently only draws two line segments through the specified + * points. + */ + +void +RT_arc_relative3(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + if (num_params < 4) + return; + + if (PenDown) + { + if (!PolygonMode) + Outputf("MP\n"); + + Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]); + + PenPosition[0] = Transform[0][0] * params[0].value.number + + Transform[0][1] * params[1].value.number + + PenPosition[0]; + PenPosition[1] = Transform[1][0] * params[0].value.number + + Transform[1][1] * params[1].value.number + + PenPosition[1]; + + Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]); + } + + PenPosition[0] = Transform[0][0] * params[2].value.number + + Transform[0][1] * params[3].value.number + + PenPosition[0]; + PenPosition[1] = Transform[1][0] * params[2].value.number + + Transform[1][1] * params[3].value.number + + PenPosition[1]; + + if (PenDown) + { + Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]); + + if (!PolygonMode) + Outputf("ST\n"); + } +} + + +/* + * 'decode_number()' - Decode an encoded number. + */ + +static double /* O - Value */ +decode_number(unsigned char **s, /* IO - String to decode */ + int base_bits, /* I - Number of data bits per byte */ + double frac_bits) /* I - Multiplier for fractional data */ +{ + double temp, /* Current value */ + shift; /* Multiplier */ + int sign; /* Sign of result */ + + + sign = 0; + + if (base_bits == 5) + { + for (temp = 0.0, shift = frac_bits * 0.5; **s != '\0'; (*s) ++) + if (**s >= 95 && **s < 127) + { + if (sign == 0) + { + if ((**s - 95) & 1) + sign = -1; + else + sign = 1; + + temp += ((**s - 95) & ~1) * shift; + } + else + temp += (**s - 95) * shift; + break; + } + else if (**s < 63) + { + if (**s != '\r' && **s != '\n') + fprintf(stderr, "hpgl2ps: Bad PE character \'%c\'!\n", **s); + + continue; + } + else + { + if (sign == 0) + { + if ((**s - 63) & 1) + sign = -1; + else + sign = 1; + + temp += ((**s - 63) & ~1) * shift; + } + else + temp += (**s - 63) * shift; + + shift *= 32.0; + } + } + else + { + for (temp = 0.0, shift = frac_bits * 0.5; **s != '\0'; (*s) ++) + if (**s >= 191 && **s < 255) + { + if (sign == 0) + { + if ((**s - 191) & 1) + sign = -1; + else + sign = 1; + + temp += ((**s - 191) & ~1) * shift; + } + else + temp += (**s - 191) * shift; + break; + } + else if (**s < 63) + { + if (**s != '\r' && **s != '\n') + fprintf(stderr, "hpgl2ps: Bad PE character \'%c\'!\n", **s); + + continue; + } + else + { + if (sign == 0) + { + if ((**s - 63) & 1) + sign = -1; + else + sign = 1; + + temp += ((**s - 63) & ~1) * shift; + } + else + temp += (**s - 63) * shift; + + shift *= 64.0; + } + } + + (*s) ++; + + return (temp * sign); +} + + +/* + * 'plot_points()' - Plot the specified points. + */ + +static void +plot_points(int num_params, /* I - Number of parameters */ + param_t *params) /* I - Parameters */ +{ + int i; /* Looping var */ + float x, y; /* Transformed coordinates */ + + + if (PenDown) + { + if (!PolygonMode) + Outputf("MP\n"); + + Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]); + } + + for (i = 0; i < num_params; i += 2) + { + if (PenMotion == 0) + { + x = Transform[0][0] * params[i + 0].value.number + + Transform[0][1] * params[i + 1].value.number + + Transform[0][2]; + y = Transform[1][0] * params[i + 0].value.number + + Transform[1][1] * params[i + 1].value.number + + Transform[1][2]; + } + else + { + x = Transform[0][0] * params[i + 0].value.number + + Transform[0][1] * params[i + 1].value.number + + PenPosition[0]; + y = Transform[1][0] * params[i + 0].value.number + + Transform[1][1] * params[i + 1].value.number + + PenPosition[1]; + } + + if (PenDown) + Outputf("%.3f %.3f LI\n", x, y); + + PenPosition[0] = x; + PenPosition[1] = y; + } + + if (PenDown) + { + if (!PolygonMode) + Outputf("ST\n"); + } +} + + +/* + * End of "$Id$". + */ diff --git a/filter/hpgltops.dsp b/filter/hpgltops.dsp new file mode 100644 index 0000000000..3f678523dc --- /dev/null +++ b/filter/hpgltops.dsp @@ -0,0 +1,130 @@ +# Microsoft Developer Studio Project File - Name="hpgltops" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=hpgltops - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "hpgltops.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "hpgltops.mak" CFG="hpgltops - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "hpgltops - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "hpgltops - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "hpgltops - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 ../cups/cups.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"hpgltops.exe" + +!ELSEIF "$(CFG)" == "hpgltops - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "hpgltops___Win32_Debug" +# PROP BASE Intermediate_Dir "hpgltops___Win32_Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 ../cups/cupsd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"hpgltopsd.exe" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "hpgltops - Win32 Release" +# Name "hpgltops - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=".\hpgl-attr.c" +# End Source File +# Begin Source File + +SOURCE=".\hpgl-char.c" +# End Source File +# Begin Source File + +SOURCE=".\hpgl-config.c" +# End Source File +# Begin Source File + +SOURCE=".\hpgl-input.c" +# End Source File +# Begin Source File + +SOURCE=".\hpgl-main.c" +# End Source File +# Begin Source File + +SOURCE=".\hpgl-polygon.c" +# End Source File +# Begin Source File + +SOURCE=".\hpgl-prolog.c" +# End Source File +# Begin Source File + +SOURCE=".\hpgl-vector.c" +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\hpgltops.h +# End Source File +# End Group +# End Target +# End Project diff --git a/filter/hpgltops.h b/filter/hpgltops.h new file mode 100644 index 0000000000..4cd32e0f0a --- /dev/null +++ b/filter/hpgltops.h @@ -0,0 +1,196 @@ +/* + * "$Id$" + * + * HP-GL/2 to PostScript filter for the Common UNIX Printing System (CUPS). + * + * Copyright 1993-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + */ + +/* + * Include necessary headers... + */ + +#include "common.h" +#include + +#ifndef M_PI +# define M_PI 3.14159265358979323846 +#endif /* M_PI */ + +/* + * Parameter value structure... + */ + +typedef struct +{ + int type; + union + { + float number; + char *string; + } value; +} param_t; + +#define PARAM_ABSOLUTE 0 +#define PARAM_RELATIVE 1 +#define PARAM_STRING 2 + + +/* + * Globals... + */ + +#ifdef _HPGL_MAIN_C_ +# define VAR +# define VALUE(x) =x +# define VALUE2(x,y) ={x,y} +#else +# define VAR extern +# define VALUE(x) +# define VALUE2(x,y) +#endif /* _HPGL_MAIN_C_ */ + +VAR float P1[2], /* Lower-lefthand physical limit */ + P2[2], /* Upper-righthand physical limit */ + IW1[2], /* Window lower-lefthand limit */ + IW2[2]; /* Window upper-righthand limit */ +VAR int Rotation VALUE(0); /* Page rotation */ +VAR int ScalingType VALUE(-1); /* Type of scaling (-1 for none) */ +VAR float Scaling1[2], /* Lower-lefthand user limit */ + Scaling2[2]; /* Upper-righthand user limit */ +VAR float Transform[2][3]; /* Transform matrix */ +VAR int PageRotation VALUE(0); /* Page/plot rotation */ + +VAR char StringTerminator VALUE('\003'); /* Terminator for labels */ +VAR float PenPosition[2] VALUE2(0.0f, 0.0f), + /* Current pen position */ + PenScaling VALUE(1.0f); /* Pen width scaling factor */ +VAR int PenMotion VALUE(0), /* 0 = absolute, 1 = relative */ + PenNumber VALUE(1), /* Current pen number */ + PenCount VALUE(8), /* Number of pens */ + PenDown VALUE(0), /* 0 = pen up, 1 = pen down */ + PolygonMode VALUE(0), /* Drawing polygons? */ + PageCount VALUE(1), /* Number of pages in plot */ + PageDirty VALUE(0), /* Current page written on? */ + WidthUnits VALUE(0); /* 0 = mm, 1 = proportionate */ +VAR float PlotSize[2] VALUE2(2592.0f, 3456.0f); + /* Plot size */ +VAR int CharFillMode VALUE(0), /* Where to draw labels */ + CharPen VALUE(0), /* Pen to use for labels */ + CharFont VALUE(0); /* Font to use for labels */ +VAR float CharHeight[2] VALUE2(11.5f,11.5f); + /* Size of font for labels */ +VAR int FitPlot VALUE(0); /* 1 = fit to page */ +VAR float ColorRange[3][2] /* Range of color values */ +#ifdef _HPGL_MAIN_C_ + = { + { 0.0, 255.0 }, + { 0.0, 255.0 }, + { 0.0, 255.0 } + } +#endif /* _HPGL_MAIN_C_ */ +; + +/* + * Prototypes... + */ + +/* hpgl-input.c */ +extern int ParseCommand(FILE *fp, char *name, param_t **params); +extern void FreeParameters(int num_params, param_t *params); + +/* hpgl-config.c */ +extern void update_transform(void); +extern void BP_begin_plot(int num_params, param_t *params); +extern void DF_default_values(int num_params, param_t *params); +extern void IN_initialize(int num_params, param_t *params); +extern void IP_input_absolute(int num_params, param_t *params); +extern void IR_input_relative(int num_params, param_t *params); +extern void IW_input_window(int num_params, param_t *params); +extern void PG_advance_page(int num_params, param_t *params); +extern void PS_plot_size(int num_params, param_t *params); +extern void RO_rotate(int num_params, param_t *params); +extern void RP_replot(int num_params, param_t *params); +extern void SC_scale(int num_params, param_t *params); + +/* hpgl-vector.c */ +extern void AA_arc_absolute(int num_params, param_t *params); +extern void AR_arc_relative(int num_params, param_t *params); +extern void AT_arc_absolute3(int num_params, param_t *params); +extern void CI_circle(int num_params, param_t *params); +extern void PA_plot_absolute(int num_params, param_t *params); +extern void PD_pen_down(int num_params, param_t *params); +extern void PE_polyline_encoded(int num_params, param_t *params); +extern void PR_plot_relative(int num_params, param_t *params); +extern void PU_pen_up(int num_params, param_t *params); +extern void RT_arc_relative3(int num_params, param_t *params); + +/* hpgl-polygon.c */ +extern void EA_edge_rect_absolute(int num_params, param_t *params); +extern void EP_edge_polygon(int num_params, param_t *params); +extern void ER_edge_rect_relative(int num_params, param_t *params); +extern void EW_edge_wedge(int num_params, param_t *params); +extern void FP_fill_polygon(int num_params, param_t *params); +extern void PM_polygon_mode(int num_params, param_t *params); +extern void RA_fill_rect_absolute(int num_params, param_t *params); +extern void RR_fill_rect_relative(int num_params, param_t *params); +extern void WG_fill_wedge(int num_params, param_t *params); + +/* hpgl-char.c */ +extern void AD_define_alternate(int num_params, param_t *params); +extern void CF_character_fill(int num_params, param_t *params); +extern void CP_character_plot(int num_params, param_t *params); +extern void DI_absolute_direction(int num_params, param_t *params); +extern void DR_relative_direction(int num_params, param_t *params); +extern void DT_define_label_term(int num_params, param_t *params); +extern void DV_define_variable_path(int num_params, param_t *params); +extern void ES_extra_space(int num_params, param_t *params); +extern void LB_label(int num_params, param_t *params); +extern void LO_label_origin(int num_params, param_t *params); +extern void SA_select_alternate(int num_params, param_t *params); +extern void SD_define_standard(int num_params, param_t *params); +extern void SI_absolute_size(int num_params, param_t *params); +extern void SL_character_slant(int num_params, param_t *params); +extern void SR_relative_size(int num_params, param_t *params); +extern void SS_select_standard(int num_params, param_t *params); +extern void TD_transparent_data(int num_params, param_t *params); + +/* hpgl-attr.c */ +extern void AC_anchor_corner(int num_params, param_t *params); +extern void CR_color_range(int num_params, param_t *params); +extern void FT_fill_type(int num_params, param_t *params); +extern void LA_line_attributes(int num_params, param_t *params); +extern void LT_line_type(int num_params, param_t *params); +extern void NP_number_pens(int num_params, param_t *params); +extern void PC_pen_color(int num_params, param_t *params); +extern void PW_pen_width(int num_params, param_t *params); +extern void RF_raster_fill(int num_params, param_t *params); +extern void SM_symbol_mode(int num_params, param_t *params); +extern void SP_select_pen(int num_params, param_t *params); +extern void UL_user_line_type(int num_params, param_t *params); +extern void WU_width_units(int num_params, param_t *params); + +/* hpgl-prolog.c */ +extern void OutputProlog(char *title, char *user, int shading, float penwidth); +extern void OutputTrailer(void); +extern int Outputf(const char *format, ...); + +/* + * End of "$Id$". + */ diff --git a/filter/image-colorspace.c b/filter/image-colorspace.c new file mode 100644 index 0000000000..a9518d0909 --- /dev/null +++ b/filter/image-colorspace.c @@ -0,0 +1,910 @@ +/* + * "$Id$" + * + * Colorspace conversions for the Common UNIX Printing System (CUPS). + * + * Copyright 1993-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * ImageWhiteToWhite() - Convert luminance colors to device-dependent + * ImageWhiteToRGB() - Convert luminance data to RGB. + * ImageWhiteToBlack() - Convert luminance colors to black. + * ImageWhiteToCMY() - Convert luminance colors to CMY. + * ImageWhiteToCMYK() - Convert luminance colors to CMYK. + * ImageRGBToBlack() - Convert RGB data to black. + * ImageRGBToCMY() - Convert RGB colors to CMY. + * ImageRGBToCMYK() - Convert RGB colors to CMYK. + * ImageRGBToWhite() - Convert RGB colors to luminance. + * ImageRGBToRGB() - Convert RGB colors to device-dependent RGB. + * ImageLut() - Adjust all pixel values with the given LUT. + * ImageRGBAdjust() - Adjust the hue and saturation of the given RGB + * colors. + * huerotate() - Rotate the hue, maintaining luminance. + * ident() - Make an identity matrix. + * mult() - Multiply two matrices. + * saturate() - Make a saturation matrix. + * xform() - Transform a 3D point using a matrix... + * xrotate() - Rotate about the x (red) axis... + * yrotate() - Rotate about the y (green) axis... + * zrotate() - Rotate about the z (blue) axis... + * zshear() - Shear z using x and y... + */ + +/* + * Include necessary headers... + */ + +#include "image.h" +#include + + +/* + * Globals... + */ + +extern int ImageHaveProfile; +extern int ImageDensity[256]; +extern int ImageMatrix[3][3][256]; + +/* + * Local functions... + */ + +static void huerotate(float [3][3], float); +static void ident(float [3][3]); +static void mult(float [3][3], float [3][3], float [3][3]); +static void saturate(float [3][3], float); +static void xform(float [3][3], float, float, float, float *, float *, float *); +static void xrotate(float [3][3], float, float); +static void yrotate(float [3][3], float, float); +static void zrotate(float [3][3], float, float); +static void zshear(float [3][3], float, float); + + +/* + * 'ImageWhiteToWhite()' - Convert luminance colors to device-dependent + * luminance. + */ + +void +ImageWhiteToWhite(ib_t *in, /* I - Input pixels */ + ib_t *out, /* I - Output pixels */ + int count) /* I - Number of pixels */ +{ + if (ImageHaveProfile) + while (count > 0) + { + *out++ = 255 - ImageDensity[255 - *in++]; + count --; + } + else if (in != out) + memcpy(out, in, count); +} + + +/* + * 'ImageWhiteToRGB()' - Convert luminance data to RGB. + */ + +void +ImageWhiteToRGB(ib_t *in, /* I - Input pixels */ + ib_t *out, /* I - Output pixels */ + int count) /* I - Number of pixels */ +{ + if (ImageHaveProfile) + while (count > 0) + { + out[0] = 255 - ImageDensity[255 - *in++]; + out[1] = out[0]; + out[2] = out[0]; + out += 3; + count --; + } + else + while (count > 0) + { + *out++ = *in; + *out++ = *in; + *out++ = *in++; + count --; + } +} + + +/* + * 'ImageWhiteToBlack()' - Convert luminance colors to black. + */ + +void +ImageWhiteToBlack(ib_t *in, /* I - Input pixels */ + ib_t *out, /* I - Output pixels */ + int count) /* I - Number of pixels */ +{ + if (ImageHaveProfile) + while (count > 0) + { + *out++ = ImageDensity[255 - *in++]; + count --; + } + else + while (count > 0) + { + *out++ = 255 - *in++; + count --; + } +} + + +/* + * 'ImageWhiteToCMY()' - Convert luminance colors to CMY. + */ + +void +ImageWhiteToCMY(ib_t *in, /* I - Input pixels */ + ib_t *out, /* I - Output pixels */ + int count) /* I - Number of pixels */ +{ + if (ImageHaveProfile) + while (count > 0) + { + out[0] = ImageDensity[255 - *in++]; + out[1] = out[0]; + out[2] = out[0]; + out += 3; + count --; + } + else + while (count > 0) + { + *out++ = 255 - *in; + *out++ = 255 - *in; + *out++ = 255 - *in++; + count --; + } +} + + +/* + * 'ImageWhiteToCMYK()' - Convert luminance colors to CMYK. + */ + +void +ImageWhiteToCMYK(ib_t *in, /* I - Input pixels */ + ib_t *out, /* I - Output pixels */ + int count) /* I - Number of pixels */ +{ + if (ImageHaveProfile) + while (count > 0) + { + *out++ = 0; + *out++ = 0; + *out++ = 0; + *out++ = ImageDensity[255 - *in++]; + count --; + } + else + while (count > 0) + { + *out++ = 0; + *out++ = 0; + *out++ = 0; + *out++ = 255 - *in++; + count --; + } +} + + +/* + * 'ImageRGBToBlack()' - Convert RGB data to black. + */ + +void +ImageRGBToBlack(ib_t *in, /* I - Input pixels */ + ib_t *out, /* I - Output pixels */ + int count) /* I - Number of pixels */ +{ + if (ImageHaveProfile) + while (count > 0) + { + *out++ = ImageDensity[255 - (31 * in[0] + 61 * in[1] + 8 * in[2]) / 100]; + in += 3; + count --; + } + else + while (count > 0) + { + *out++ = 255 - (31 * in[0] + 61 * in[1] + 8 * in[2]) / 100; + in += 3; + count --; + } +} + + +/* + * 'ImageRGBToCMY()' - Convert RGB colors to CMY. + */ + +void +ImageRGBToCMY(ib_t *in, /* I - Input pixels */ + ib_t *out, /* I - Output pixels */ + int count) /* I - Number of pixels */ +{ + int c, m, y, k; /* CMYK values */ + int cc, cm, cy; /* Calibrated CMY values */ + + + if (ImageHaveProfile) + while (count > 0) + { + c = 255 - *in++; + m = 255 - *in++; + y = 255 - *in++; + k = min(c, min(m, y)); + c -= k; + m -= k; + y -= k; + + cc = ImageMatrix[0][0][c] + + ImageMatrix[0][1][m] + + ImageMatrix[0][2][y] + k; + cm = ImageMatrix[1][0][c] + + ImageMatrix[1][1][m] + + ImageMatrix[1][2][y] + k; + cy = ImageMatrix[2][0][c] + + ImageMatrix[2][1][m] + + ImageMatrix[2][2][y] + k; + + if (cc < 0) + *out++ = 0; + else if (cc > 255) + *out++ = ImageDensity[255]; + else + *out++ = ImageDensity[cc]; + + if (cm < 0) + *out++ = 0; + else if (cm > 255) + *out++ = ImageDensity[255]; + else + *out++ = ImageDensity[cm]; + + if (cy < 0) + *out++ = 0; + else if (cy > 255) + *out++ = ImageDensity[255]; + else + *out++ = ImageDensity[cy]; + + count --; + } + else + while (count > 0) + { + c = 255 - in[0]; + m = 255 - in[1]; + y = 255 - in[2]; + k = min(c, min(m, y)); + + *out++ = (255 - in[1] / 4) * (c - k) / 255 + k; + *out++ = (255 - in[2] / 4) * (m - k) / 255 + k; + *out++ = (255 - in[0] / 4) * (y - k) / 255 + k; + in += 3; + count --; + } +} + + +/* + * 'ImageRGBToCMYK()' - Convert RGB colors to CMYK. + */ + +void +ImageRGBToCMYK(ib_t *in, /* I - Input pixels */ + ib_t *out, /* I - Output pixels */ + int count) /* I - Number of pixels */ +{ + int c, m, y, k, /* CMYK values */ + diff, /* Color differences */ + divk; /* Color divisor */ + int cc, cm, cy; /* Calibrated CMY values */ + + + if (ImageHaveProfile) + while (count > 0) + { + c = 255 - *in++; + m = 255 - *in++; + y = 255 - *in++; + k = min(c, min(m, y)); + + diff = 255 - (max(c, max(m, y)) - k); + k = k * diff / 255; + + if (k == 255) + c = m = y = 0; + else if (k > 0) + { + divk = 255 - k; + c = 255 * (c - k) / divk; + m = 255 * (m - k) / divk; + y = 255 * (y - k) / divk; + + if (c > 255) + c = 255; + + if (m > 255) + m = 255; + + if (y > 255) + y = 255; + } + + cc = (ImageMatrix[0][0][c] + + ImageMatrix[0][1][m] + + ImageMatrix[0][2][y]); + cm = (ImageMatrix[1][0][c] + + ImageMatrix[1][1][m] + + ImageMatrix[1][2][y]); + cy = (ImageMatrix[2][0][c] + + ImageMatrix[2][1][m] + + ImageMatrix[2][2][y]); + + if (cc < 0) + *out++ = 0; + else if (cc > 255) + *out++ = ImageDensity[255]; + else + *out++ = ImageDensity[cc]; + + if (cm < 0) + *out++ = 0; + else if (cm > 255) + *out++ = ImageDensity[255]; + else + *out++ = ImageDensity[cm]; + + if (cy < 0) + *out++ = 0; + else if (cy > 255) + *out++ = ImageDensity[255]; + else + *out++ = cy; + + *out++ = ImageDensity[k]; + + count --; + } + else + while (count > 0) + { + c = 255 - *in++; + m = 255 - *in++; + y = 255 - *in++; + k = min(c, min(m, y)); + + if (k == 255) + c = m = y = 0; + else if (k > 0) + { + divk = 255 - k; + c = 255 * (c - k) / divk; + m = 255 * (m - k) / divk; + y = 255 * (y - k) / divk; + + if (c > 255) + c = 255; + + if (m > 255) + m = 255; + + if (y > 255) + y = 255; + } + + *out++ = c; + *out++ = m; + *out++ = y; + *out++ = k; + + count --; + } +} + + +/* + * 'ImageRGBToWhite()' - Convert RGB colors to luminance. + */ + +void +ImageRGBToWhite(ib_t *in, /* I - Input pixels */ + ib_t *out, /* I - Output pixels */ + int count) /* I - Number of pixels */ +{ + if (ImageHaveProfile) + while (count > 0) + { + *out++ = 255 - ImageDensity[255 - (31 * in[0] + 61 * in[1] + 8 * in[2]) / 100]; + in += 3; + count --; + } + else + while (count > 0) + { + *out++ = (31 * in[0] + 61 * in[1] + 8 * in[2]) / 100; + in += 3; + count --; + } +} + + +/* + * 'ImageRGBToRGB()' - Convert RGB colors to device-dependent RGB. + */ + +void +ImageRGBToRGB(ib_t *in, /* I - Input pixels */ + ib_t *out, /* I - Output pixels */ + int count) /* I - Number of pixels */ +{ + int c, m, y, k; /* CMYK values */ + int cr, cg, cb; /* Calibrated RGB values */ + + + if (ImageHaveProfile) + while (count > 0) + { + c = 255 - *in++; + m = 255 - *in++; + y = 255 - *in++; + k = min(c, min(m, y)); + c -= k; + m -= k; + y -= k; + + cr = ImageMatrix[0][0][c] + + ImageMatrix[0][1][m] + + ImageMatrix[0][2][y] + k; + cg = ImageMatrix[1][0][c] + + ImageMatrix[1][1][m] + + ImageMatrix[1][2][y] + k; + cb = ImageMatrix[2][0][c] + + ImageMatrix[2][1][m] + + ImageMatrix[2][2][y] + k; + + if (cr < 0) + *out++ = 255; + else if (cr > 255) + *out++ = 255 - ImageDensity[255]; + else + *out++ = 255 - ImageDensity[cr]; + + if (cg < 0) + *out++ = 255; + else if (cg > 255) + *out++ = 255 - ImageDensity[255]; + else + *out++ = 255 - ImageDensity[cg]; + + if (cb < 0) + *out++ = 255; + else if (cb > 255) + *out++ = 255 - ImageDensity[255]; + else + *out++ = 255 - ImageDensity[cb]; + + count --; + } + else if (in != out) + memcpy(out, in, count * 3); +} + + +/* + * 'ImageLut()' - Adjust all pixel values with the given LUT. + */ + +void +ImageLut(ib_t *pixels, /* I - Input/output pixels */ + int count, /* I - Number of pixels/bytes to adjust */ + ib_t *lut) /* I - Lookup table */ +{ + while (count > 0) + { + *pixels = lut[*pixels]; + pixels ++; + count --; + } +} + + +/* + * 'ImageRGBAdjust()' - Adjust the hue and saturation of the given RGB colors. + */ + +void +ImageRGBAdjust(ib_t *pixels, /* I - Input/output pixels */ + int count, /* I - Number of pixels to adjust */ + int saturation, /* I - Color saturation (%) */ + int hue) /* I - Color hue (degrees) */ +{ + int i, j, k; /* Looping vars */ + float mat[3][3]; /* Color adjustment matrix */ + static int last_sat = 100, /* Last saturation used */ + last_hue = 0; /* Last hue used */ + static int lut[3][3][256]; /* Lookup table for matrix */ + + + if (saturation != last_sat || + hue != last_hue) + { + /* + * Build the color adjustment matrix... + */ + + ident(mat); + saturate(mat, saturation * 0.01); + huerotate(mat, (float)hue); + + /* + * Convert the matrix into a 3x3 array of lookup tables... + */ + + for (i = 0; i < 3; i ++) + for (j = 0; j < 3; j ++) + for (k = 0; k < 256; k ++) + lut[i][j][k] = mat[i][j] * k + 0.5; + + /* + * Save the saturation and hue to compare later... + */ + + last_sat = saturation; + last_hue = hue; + } + + /* + * Adjust each pixel in the given buffer. + */ + + while (count > 0) + { + i = lut[0][0][pixels[0]] + + lut[1][0][pixels[1]] + + lut[2][0][pixels[2]]; + if (i < 0) + pixels[0] = 0; + else if (i > 255) + pixels[0] = 255; + else + pixels[0] = i; + + i = lut[0][1][pixels[0]] + + lut[1][1][pixels[1]] + + lut[2][1][pixels[2]]; + if (i < 0) + pixels[1] = 0; + else if (i > 255) + pixels[1] = 255; + else + pixels[1] = i; + + i = lut[0][2][pixels[0]] + + lut[1][2][pixels[1]] + + lut[2][2][pixels[2]]; + if (i < 0) + pixels[2] = 0; + else if (i > 255) + pixels[2] = 255; + else + pixels[2] = i; + + count --; + pixels += 3; + } +} + + +/* + * The color saturation/hue matrix stuff is provided thanks to Mr. Paul + * Haeberli at "http://www.sgi.com/grafica/matrix/index.html". + */ + +/* + * 'huerotate()' - Rotate the hue, maintaining luminance. + */ + +static void +huerotate(float mat[3][3], /* I - Matrix to append to */ + float rot) /* I - Hue rotation in degrees */ +{ + float hmat[3][3]; /* Hue matrix */ + float lx, ly, lz; /* Luminance vector */ + float xrs, xrc; /* X rotation sine/cosine */ + float yrs, yrc; /* Y rotation sine/cosine */ + float zrs, zrc; /* Z rotation sine/cosine */ + float zsx, zsy; /* Z shear x/y */ + + + /* + * Load the identity matrix... + */ + + ident(hmat); + + /* + * Rotate the grey vector into positive Z... + */ + + xrs = M_SQRT1_2; + xrc = M_SQRT1_2; + xrotate(hmat,xrs,xrc); + + yrs = -1.0 / sqrt(3.0); + yrc = -M_SQRT2 * yrs; + yrotate(hmat,yrs,yrc); + + /* + * Shear the space to make the luminance plane horizontal... + */ + + xform(hmat, 0.3086, 0.6094, 0.0820, &lx, &ly, &lz); + zsx = lx / lz; + zsy = ly / lz; + zshear(hmat, zsx, zsy); + + /* + * Rotate the hue... + */ + + zrs = sin(rot * M_PI / 180.0); + zrc = cos(rot * M_PI / 180.0); + + zrotate(hmat, zrs, zrc); + + /* + * Unshear the space to put the luminance plane back... + */ + + zshear(hmat, -zsx, -zsy); + + /* + * Rotate the grey vector back into place... + */ + + yrotate(hmat, -yrs, yrc); + xrotate(hmat, -xrs, xrc); + + /* + * Append it to the current matrix... + */ + + mult(hmat, mat, mat); +} + + +/* + * 'ident()' - Make an identity matrix. + */ + +static void +ident(float mat[3][3]) /* I - Matrix to identify */ +{ + mat[0][0] = 1.0; + mat[0][1] = 0.0; + mat[0][2] = 0.0; + mat[1][0] = 0.0; + mat[1][1] = 1.0; + mat[1][2] = 0.0; + mat[2][0] = 0.0; + mat[2][1] = 0.0; + mat[2][2] = 1.0; +} + + +/* + * 'mult()' - Multiply two matrices. + */ + +static void +mult(float a[3][3], /* I - First matrix */ + float b[3][3], /* I - Second matrix */ + float c[3][3]) /* I - Destination matrix */ +{ + int x, y; /* Looping vars */ + float temp[3][3]; /* Temporary matrix */ + + + /* + * Multiply a and b, putting the result in temp... + */ + + for (y = 0; y < 3; y ++) + for (x = 0; x < 3; x ++) + temp[y][x] = b[y][0] * a[0][x] + + b[y][1] * a[1][x] + + b[y][2] * a[2][x]; + + /* + * Copy temp to c (that way c can be a pointer to a or b). + */ + + memcpy(c, temp, sizeof(temp)); +} + + +/* + * 'saturate()' - Make a saturation matrix. + */ + +static void +saturate(float mat[3][3], /* I - Matrix to append to */ + float sat) /* I - Desired color saturation */ +{ + float smat[3][3]; /* Saturation matrix */ + + + smat[0][0] = (1.0 - sat) * 0.3086 + sat; + smat[0][1] = (1.0 - sat) * 0.3086; + smat[0][2] = (1.0 - sat) * 0.3086; + smat[1][0] = (1.0 - sat) * 0.6094; + smat[1][1] = (1.0 - sat) * 0.6094 + sat; + smat[1][2] = (1.0 - sat) * 0.6094; + smat[2][0] = (1.0 - sat) * 0.0820; + smat[2][1] = (1.0 - sat) * 0.0820; + smat[2][2] = (1.0 - sat) * 0.0820 + sat; + + mult(smat, mat, mat); +} + + +/* + * 'xform()' - Transform a 3D point using a matrix... + */ + +static void +xform(float mat[3][3], /* I - Matrix */ + float x, /* I - Input X coordinate */ + float y, /* I - Input Y coordinate */ + float z, /* I - Input Z coordinate */ + float *tx, /* O - Output X coordinate */ + float *ty, /* O - Output Y coordinate */ + float *tz) /* O - Output Z coordinate */ +{ + *tx = x * mat[0][0] + y * mat[1][0] + z * mat[2][0]; + *ty = x * mat[0][1] + y * mat[1][1] + z * mat[2][1]; + *tz = x * mat[0][2] + y * mat[1][2] + z * mat[2][2]; +} + + +/* + * 'xrotate()' - Rotate about the x (red) axis... + */ + +static void +xrotate(float mat[3][3], /* I - Matrix */ + float rs, /* I - Rotation angle sine */ + float rc) /* I - Rotation angle cosine */ +{ + float rmat[3][3]; /* I - Rotation matrix */ + + + rmat[0][0] = 1.0; + rmat[0][1] = 0.0; + rmat[0][2] = 0.0; + + rmat[1][0] = 0.0; + rmat[1][1] = rc; + rmat[1][2] = rs; + + rmat[2][0] = 0.0; + rmat[2][1] = -rs; + rmat[2][2] = rc; + + mult(rmat, mat, mat); +} + + +/* + * 'yrotate()' - Rotate about the y (green) axis... + */ + +static void +yrotate(float mat[3][3], /* I - Matrix */ + float rs, /* I - Rotation angle sine */ + float rc) /* I - Rotation angle cosine */ +{ + float rmat[3][3]; /* I - Rotation matrix */ + + + rmat[0][0] = rc; + rmat[0][1] = 0.0; + rmat[0][2] = -rs; + + rmat[1][0] = 0.0; + rmat[1][1] = 1.0; + rmat[1][2] = 0.0; + + rmat[2][0] = rs; + rmat[2][1] = 0.0; + rmat[2][2] = rc; + + mult(rmat,mat,mat); +} + + +/* + * 'zrotate()' - Rotate about the z (blue) axis... + */ + +static void +zrotate(float mat[3][3], /* I - Matrix */ + float rs, /* I - Rotation angle sine */ + float rc) /* I - Rotation angle cosine */ +{ + float rmat[3][3]; /* I - Rotation matrix */ + + + rmat[0][0] = rc; + rmat[0][1] = rs; + rmat[0][2] = 0.0; + + rmat[1][0] = -rs; + rmat[1][1] = rc; + rmat[1][2] = 0.0; + + rmat[2][0] = 0.0; + rmat[2][1] = 0.0; + rmat[2][2] = 1.0; + + mult(rmat,mat,mat); +} + + +/* + * 'zshear()' - Shear z using x and y... + */ + +static void +zshear(float mat[3][3], /* I - Matrix */ + float dx, /* I - X shear */ + float dy) /* I - Y shear */ +{ + float smat[3][3]; /* Shear matrix */ + + + smat[0][0] = 1.0; + smat[0][1] = 0.0; + smat[0][2] = dx; + + smat[1][0] = 0.0; + smat[1][1] = 1.0; + smat[1][2] = dy; + + smat[2][0] = 0.0; + smat[2][1] = 0.0; + smat[2][2] = 1.0; + + mult(smat, mat, mat); +} + + +/* + * End of "$Id$". + */ diff --git a/filter/image-gif.c b/filter/image-gif.c new file mode 100644 index 0000000000..5f18ff0852 --- /dev/null +++ b/filter/image-gif.c @@ -0,0 +1,644 @@ +/* + * "$Id$" + * + * GIF image routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1993-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * ImageReadGIF() - Read a GIF image file. + * gif_read_cmap() - Read the colormap from a GIF file... + * gif_get_block() - Read a GIF data block... + * gif_get_code() - Get a LZW code from the file... + * gif_read_lzw() - Read a byte from the LZW stream... + * gif_read_image() - Read a GIF image stream... + */ + +/* + * Include necessary headers... + */ + +#include "image.h" + + +/* + * GIF definitions... + */ + +#define GIF_INTERLACE 0x40 +#define GIF_COLORMAP 0x80 + +typedef ib_t gif_cmap_t[256][4]; + + +/* + * Local globals... + */ + +static int gif_eof = 0; /* Did we hit EOF? */ + + +/* + * Local functions... + */ + +static int gif_read_cmap(FILE *fp, int ncolors, gif_cmap_t cmap, + int *gray); +static int gif_get_block(FILE *fp, unsigned char *buffer); +static int gif_get_code (FILE *fp, int code_size, int first_time); +static int gif_read_lzw(FILE *fp, int first_time, int input_code_size); +static int gif_read_image(FILE *fp, image_t *img, gif_cmap_t cmap, + int interlace); + + +/* + * 'ImageReadGIF()' - Read a GIF image file. + */ + +int /* O - Read status */ +ImageReadGIF(image_t *img, /* IO - Image */ + FILE *fp, /* I - Image file */ + int primary, /* I - Primary choice for colorspace */ + int secondary, /* I - Secondary choice for colorspace */ + int saturation,/* I - Color saturation (%) */ + int hue, /* I - Color hue (degrees) */ + ib_t *lut) /* I - Lookup table for gamma/brightness */ +{ + unsigned char buf[1024]; /* Input buffer */ + gif_cmap_t cmap; /* Colormap */ + int i, /* Looping var */ + bpp, /* Bytes per pixel */ + gray, /* Grayscale image? */ + ncolors, /* Bits per pixel */ + transparent; /* Transparent color index */ + + + /* + * Read the header; we already know it is a GIF file... + */ + + fread(buf, 13, 1, fp); + + img->xsize = (buf[7] << 8) | buf[6]; + img->ysize = (buf[9] << 8) | buf[8]; + ncolors = 2 << (buf[10] & 0x07); + gray = primary == IMAGE_BLACK || primary == IMAGE_WHITE; + + if (buf[10] & GIF_COLORMAP) + if (gif_read_cmap(fp, ncolors, cmap, &gray)) + { + fclose(fp); + return (-1); + } + + transparent = -1; + + for (;;) + { + switch (getc(fp)) + { + case ';' : /* End of image */ + fclose(fp); + return (-1); /* Early end of file */ + + case '!' : /* Extension record */ + buf[0] = getc(fp); + if (buf[0] == 0xf9) /* Graphic Control Extension */ + { + gif_get_block(fp, buf); + if (buf[0] & 1) /* Get transparent color index */ + transparent = buf[3]; + } + + while (gif_get_block(fp, buf) != 0); + break; + + case ',' : /* Image data */ + fread(buf, 9, 1, fp); + + if (buf[8] & GIF_COLORMAP) + { + ncolors = 2 << (buf[8] & 0x07); + gray = primary == IMAGE_BLACK || primary == IMAGE_WHITE; + + if (gif_read_cmap(fp, ncolors, cmap, &gray)) + { + fclose(fp); + return (-1); + } + } + + if (transparent >= 0) + { + /* + * Make transparent color white... + */ + + cmap[transparent][0] = 255; + cmap[transparent][1] = 255; + cmap[transparent][2] = 255; + } + + if (gray) + { + switch (secondary) + { + case IMAGE_CMYK : + for (i = ncolors - 1; i >= 0; i --) + ImageWhiteToCMYK(cmap[i], cmap[i], 1); + break; + case IMAGE_CMY : + for (i = ncolors - 1; i >= 0; i --) + ImageWhiteToCMY(cmap[i], cmap[i], 1); + break; + case IMAGE_BLACK : + for (i = ncolors - 1; i >= 0; i --) + ImageWhiteToBlack(cmap[i], cmap[i], 1); + break; + case IMAGE_WHITE : + break; + case IMAGE_RGB : + for (i = ncolors - 1; i >= 0; i --) + ImageWhiteToRGB(cmap[i], cmap[i], 1); + break; + } + + img->colorspace = secondary; + } + else + { + if (hue != 0 || saturation != 100) + for (i = ncolors - 1; i >= 0; i --) + ImageRGBAdjust(cmap[i], 1, saturation, hue); + + switch (primary) + { + case IMAGE_CMYK : + for (i = ncolors - 1; i >= 0; i --) + ImageRGBToCMYK(cmap[i], cmap[i], 1); + break; + case IMAGE_CMY : + for (i = ncolors - 1; i >= 0; i --) + ImageRGBToCMY(cmap[i], cmap[i], 1); + break; + case IMAGE_BLACK : + for (i = ncolors - 1; i >= 0; i --) + ImageRGBToBlack(cmap[i], cmap[i], 1); + break; + case IMAGE_WHITE : + for (i = ncolors - 1; i >= 0; i --) + ImageRGBToWhite(cmap[i], cmap[i], 1); + break; + case IMAGE_RGB : + break; + } + + img->colorspace = primary; + } + + if (lut) + { + bpp = ImageGetDepth(img); + + for (i = ncolors - 1; i >= 0; i --) + ImageLut(cmap[i], bpp, lut); + } + + img->xsize = (buf[5] << 8) | buf[4]; + img->ysize = (buf[7] << 8) | buf[6]; + + i = gif_read_image(fp, img, cmap, buf[8] & GIF_INTERLACE); + fclose(fp); + return (i); + } + } +} + + +/* + * 'gif_read_cmap()' - Read the colormap from a GIF file... + */ + +static int +gif_read_cmap(FILE *fp, + int ncolors, + gif_cmap_t cmap, + int *gray) +{ + int i; + + + /* + * Read the colormap... + */ + + for (i = 0; i < ncolors; i ++) + if (fread(cmap[i], 3, 1, fp) < 1) + return (-1); + + /* + * Check to see if the colormap is a grayscale ramp... + */ + + for (i = 0; i < ncolors; i ++) + if (cmap[i][0] != cmap[i][1] || cmap[i][1] != cmap[i][2]) + break; + + if (i == ncolors) + { + *gray = 1; + return (0); + } + + /* + * If this needs to be a grayscale image, convert the RGB values to + * luminance values... + */ + + if (*gray) + for (i = 0; i < ncolors; i ++) + cmap[i][0] = (cmap[i][0] * 31 + cmap[i][1] * 61 + cmap[i][2] * 8) / 100; + + return (0); +} + + +/* + * 'gif_get_block()' - Read a GIF data block... + */ + +static int /* O - Number characters read */ +gif_get_block(FILE *fp, /* I - File to read from */ + unsigned char *buf) /* I - Input buffer */ +{ + int count; /* Number of character to read */ + + + /* + * Read the count byte followed by the data from the file... + */ + + if ((count = getc(fp)) == EOF) + { + gif_eof = 1; + return (-1); + } + else if (count == 0) + gif_eof = 1; + else if (fread(buf, 1, count, fp) < count) + { + gif_eof = 1; + return (-1); + } + else + gif_eof = 0; + + return (count); +} + + +/* + * 'gif_get_code()' - Get a LZW code from the file... + */ + +static int /* O - LZW code */ +gif_get_code(FILE *fp, /* I - File to read from */ + int code_size, /* I - Size of code in bits */ + int first_time) /* I - 1 = first time, 0 = not first time */ +{ + unsigned i, j, /* Looping vars */ + ret; /* Return value */ + int count; /* Number of bytes read */ + static unsigned char buf[280]; /* Input buffer */ + static unsigned curbit, /* Current bit */ + lastbit, /* Last bit in buffer */ + done, /* Done with this buffer? */ + last_byte; /* Last byte in buffer */ + static unsigned char bits[8] = /* Bit masks for codes */ + { + 0x01, 0x02, 0x04, 0x08, + 0x10, 0x20, 0x40, 0x80 + }; + + + if (first_time) + { + /* + * Just initialize the input buffer... + */ + + curbit = 0; + lastbit = 0; + done = 0; + + return (0); + } + + + if ((curbit + code_size) >= lastbit) + { + /* + * Don't have enough bits to hold the code... + */ + + if (done) + return (-1); /* Sorry, no more... */ + + /* + * Move last two bytes to front of buffer... + */ + + buf[0] = buf[last_byte - 2]; + buf[1] = buf[last_byte - 1]; + + /* + * Read in another buffer... + */ + + if ((count = gif_get_block (fp, buf + 2)) <= 0) + { + /* + * Whoops, no more data! + */ + + done = 1; + return (-1); + } + + /* + * Update buffer state... + */ + + last_byte = 2 + count; + curbit = (curbit - lastbit) + 16; + lastbit = last_byte * 8; + } + + ret = 0; + for (ret = 0, i = curbit + code_size - 1, j = code_size; + j > 0; + i --, j --) + ret = (ret << 1) | ((buf[i / 8] & bits[i & 7]) != 0); + + curbit += code_size; + + return ret; +} + + +/* + * 'gif_read_lzw()' - Read a byte from the LZW stream... + */ + +static int /* I - Byte from stream */ +gif_read_lzw(FILE *fp, /* I - File to read from */ + int first_time, /* I - 1 = first time, 0 = not first time */ + int input_code_size) /* I - Code size in bits */ +{ + int i, /* Looping var */ + code, /* Current code */ + incode; /* Input code */ + static short fresh = 0, /* 1 = empty buffers */ + code_size, /* Current code size */ + set_code_size, /* Initial code size set */ + max_code, /* Maximum code used */ + max_code_size, /* Maximum code size */ + firstcode, /* First code read */ + oldcode, /* Last code read */ + clear_code, /* Clear code for LZW input */ + end_code, /* End code for LZW input */ + table[2][4096], /* String table */ + stack[8192], /* Output stack */ + *sp; /* Current stack pointer */ + + + if (first_time) + { + /* + * Setup LZW state... + */ + + set_code_size = input_code_size; + code_size = set_code_size + 1; + clear_code = 1 << set_code_size; + end_code = clear_code + 1; + max_code_size = 2 * clear_code; + max_code = clear_code + 2; + + /* + * Initialize input buffers... + */ + + gif_get_code(fp, 0, 1); + + /* + * Wipe the decompressor table... + */ + + fresh = 1; + + for (i = 0; i < clear_code; i ++) + { + table[0][i] = 0; + table[1][i] = i; + } + + for (; i < 4096; i ++) + table[0][i] = table[1][0] = 0; + + sp = stack; + + return (0); + } + else if (fresh) + { + fresh = 0; + + do + firstcode = oldcode = gif_get_code(fp, code_size, 0); + while (firstcode == clear_code); + + return (firstcode); + } + + if (sp > stack) + return (*--sp); + + while ((code = gif_get_code (fp, code_size, 0)) >= 0) + { + if (code == clear_code) + { + for (i = 0; i < clear_code; i ++) + { + table[0][i] = 0; + table[1][i] = i; + } + + for (; i < 4096; i ++) + table[0][i] = table[1][i] = 0; + + code_size = set_code_size + 1; + max_code_size = 2 * clear_code; + max_code = clear_code + 2; + + sp = stack; + + firstcode = oldcode = gif_get_code(fp, code_size, 0); + + return (firstcode); + } + else if (code == end_code) + { + unsigned char buf[260]; + + + if (!gif_eof) + while (gif_get_block(fp, buf) > 0); + + return (-2); + } + + incode = code; + + if (code >= max_code) + { + *sp++ = firstcode; + code = oldcode; + } + + while (code >= clear_code) + { + *sp++ = table[1][code]; + if (code == table[0][code]) + return (255); + + code = table[0][code]; + } + + *sp++ = firstcode = table[1][code]; + code = max_code; + + if (code < 4096) + { + table[0][code] = oldcode; + table[1][code] = firstcode; + max_code ++; + + if (max_code >= max_code_size && max_code_size < 4096) + { + max_code_size *= 2; + code_size ++; + } + } + + oldcode = incode; + + if (sp > stack) + return (*--sp); + } + + return (code); +} + + +/* + * 'gif_read_image()' - Read a GIF image stream... + */ + +static int /* I - 0 = success, -1 = failure */ +gif_read_image(FILE *fp, /* I - Input file */ + image_t *img, /* I - Image pointer */ + gif_cmap_t cmap, /* I - Colormap */ + int interlace) /* I - Non-zero = interlaced image */ +{ + unsigned char code_size; /* Code size */ + ib_t *pixels, /* Pixel buffer */ + *temp; /* Current pixel */ + int xpos, /* Current X position */ + ypos, /* Current Y position */ + pass; /* Current pass */ + int pixel; /* Current pixel */ + int bpp; /* Bytes per pixel */ + static int xpasses[4] = { 8, 8, 4, 2 }, + ypasses[5] = { 0, 4, 2, 1, 999999 }; + + + bpp = ImageGetDepth(img); + pixels = calloc(bpp, img->xsize); + xpos = 0; + ypos = 0; + pass = 0; + code_size = getc(fp); + + if (gif_read_lzw(fp, 1, code_size) < 0) + return (-1); + + temp = pixels; + while ((pixel = gif_read_lzw(fp, 0, code_size)) >= 0) + { + switch (bpp) + { + case 4 : + temp[3] = cmap[pixel][3]; + case 3 : + temp[2] = cmap[pixel][2]; + case 2 : + temp[1] = cmap[pixel][1]; + default : + temp[0] = cmap[pixel][0]; + } + + xpos ++; + temp += bpp; + if (xpos == img->xsize) + { + ImagePutRow(img, 0, ypos, img->xsize, pixels); + + xpos = 0; + temp = pixels; + + if (interlace) + { + ypos += xpasses[pass]; + + if (ypos >= img->ysize) + { + pass ++; + + ypos = ypasses[pass]; + } + } + else + ypos ++; + } + + if (ypos >= img->ysize) + break; + } + + free(pixels); + + return (0); +} + + +/* + * End of "$Id$". + */ diff --git a/filter/image-jpeg.c b/filter/image-jpeg.c new file mode 100644 index 0000000000..a08051b301 --- /dev/null +++ b/filter/image-jpeg.c @@ -0,0 +1,190 @@ +/* + * "$Id$" + * + * JPEG image routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1993-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * ImageReadJPEG() - Read a JPEG image file. + */ + +/* + * Include necessary headers... + */ + +#include "image.h" + +#ifdef HAVE_LIBJPEG +# include /* JPEG/JFIF image definitions */ + + +/* + * 'ImageReadJPEG()' - Read a JPEG image file. + */ + +int /* O - Read status */ +ImageReadJPEG(image_t *img, /* IO - Image */ + FILE *fp, /* I - Image file */ + int primary, /* I - Primary choice for colorspace */ + int secondary, /* I - Secondary choice for colorspace */ + int saturation, /* I - Color saturation (%) */ + int hue, /* I - Color hue (degrees) */ + ib_t *lut) /* I - Lookup table for gamma/brightness */ +{ + struct jpeg_decompress_struct cinfo; /* Decompressor info */ + struct jpeg_error_mgr jerr; /* Error handler info */ + ib_t *in, /* Input pixels */ + *out; /* Output pixels */ + + + (void)secondary; + + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_decompress(&cinfo); + jpeg_stdio_src(&cinfo, fp); + jpeg_read_header(&cinfo, 1); + + cinfo.quantize_colors = 0; + + if (cinfo.num_components == 1) + { + cinfo.out_color_space = JCS_GRAYSCALE; + cinfo.out_color_components = 1; + cinfo.output_components = 1; + } + else + { + cinfo.out_color_space = JCS_RGB; + cinfo.out_color_components = 3; + cinfo.output_components = 3; + } + + jpeg_calc_output_dimensions(&cinfo); + + img->xsize = cinfo.output_width; + img->ysize = cinfo.output_height; + img->colorspace = primary; + + if (cinfo.X_density > 0 && cinfo.Y_density > 0 && cinfo.density_unit > 0) + { + if (cinfo.density_unit == 1) + { + img->xppi = cinfo.X_density; + img->yppi = cinfo.Y_density; + } + else + { + img->xppi = (int)((float)cinfo.X_density * 2.54); + img->yppi = (int)((float)cinfo.Y_density * 2.54); + } + } + + ImageSetMaxTiles(img, 0); + + in = malloc(img->xsize * cinfo.output_components); + if (primary < 0) + out = malloc(-img->xsize * primary); + else + out = malloc(img->xsize * primary); + + jpeg_start_decompress(&cinfo); + + while (cinfo.output_scanline < cinfo.output_height) + { + jpeg_read_scanlines(&cinfo, (JSAMPROW *)&in, (JDIMENSION)1); + + if ((saturation != 100 || hue != 0) && cinfo.output_components > 1) + ImageRGBAdjust(in, img->xsize, saturation, hue); + + if ((primary == IMAGE_WHITE && cinfo.out_color_space == JCS_GRAYSCALE) || + (primary == IMAGE_RGB && cinfo.out_color_space == JCS_RGB)) + { + if (lut) + ImageLut(in, img->xsize * ImageGetDepth(img), lut); + + ImagePutRow(img, 0, cinfo.output_scanline - 1, img->xsize, in); + } + else if (cinfo.out_color_space == JCS_GRAYSCALE) + { + switch (primary) + { + case IMAGE_BLACK : + ImageWhiteToBlack(in, out, img->xsize); + break; + case IMAGE_RGB : + ImageWhiteToRGB(in, out, img->xsize); + break; + case IMAGE_CMY : + ImageWhiteToCMY(in, out, img->xsize); + break; + case IMAGE_CMYK : + ImageWhiteToCMYK(in, out, img->xsize); + break; + } + + if (lut) + ImageLut(out, img->xsize * ImageGetDepth(img), lut); + + ImagePutRow(img, 0, cinfo.output_scanline - 1, img->xsize, out); + } + else + { + switch (primary) + { + case IMAGE_WHITE : + ImageRGBToWhite(in, out, img->xsize); + break; + case IMAGE_BLACK : + ImageRGBToBlack(in, out, img->xsize); + break; + case IMAGE_CMY : + ImageRGBToCMY(in, out, img->xsize); + break; + case IMAGE_CMYK : + ImageRGBToCMYK(in, out, img->xsize); + break; + } + + if (lut) + ImageLut(out, img->xsize * ImageGetDepth(img), lut); + + ImagePutRow(img, 0, cinfo.output_scanline - 1, img->xsize, out); + } + } + + free(in); + free(out); + + jpeg_finish_decompress(&cinfo); + jpeg_destroy_decompress(&cinfo); + + fclose(fp); + + return (0); +} + + +#endif /* HAVE_LIBJPEG */ + + +/* + * End of "$Id$". + */ diff --git a/filter/image-photocd.c b/filter/image-photocd.c new file mode 100644 index 0000000000..e86b5467f1 --- /dev/null +++ b/filter/image-photocd.c @@ -0,0 +1,319 @@ +/* + * "$Id$" + * + * PhotoCD routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1993-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * ImageReadPhotoCD() - Read a PhotoCD image file. + */ + +/* + * Include necessary headers... + */ + +#include "image.h" + + +/* + * PhotoCD support is currently limited to the 768x512 base image, which + * is only YCC encoded. Support for the higher resolution images will + * require a lot of extra code... + */ + +/* + * 'ImageReadPhotoCD()' - Read a PhotoCD image file. + */ + +int /* O - Read status */ +ImageReadPhotoCD(image_t *img, /* IO - Image */ + FILE *fp, /* I - Image file */ + int primary, /* I - Primary choice for colorspace */ + int secondary, /* I - Secondary choice for colorspace */ + int saturation, /* I - Color saturation (%) */ + int hue, /* I - Color hue (degrees) */ + ib_t *lut) /* I - Lookup table for gamma/brightness */ +{ + int x, y; /* Looping vars */ + int xdir, /* X direction */ + xstart; /* X starting point */ + int bpp; /* Bytes per pixel */ + int pass; /* Pass number */ + int rotation; /* 0 for 768x512, 1 for 512x768 */ + int temp, /* Adjusted luminance */ + temp2, /* Red, green, and blue values */ + cb, cr; /* Adjusted chroma values */ + ib_t *in, /* Input (YCC) pixels */ + *iy, /* Luminance */ + *icb, /* Blue chroma */ + *icr, /* Red chroma */ + *rgb, /* RGB */ + *rgbptr, /* Pointer into RGB data */ + *out; /* Output pixels */ + + + (void)secondary; + + /* + * Get the image orientation... + */ + + fseek(fp, 72, SEEK_SET); + rotation = (getc(fp) & 63) != 8; + + /* + * Seek to the start of the base image... + */ + + fseek(fp, 0x30000, SEEK_SET); + + /* + * Allocate and initialize... + */ + + img->colorspace = primary; + img->xppi = 128; + img->yppi = 128; + + if (rotation) + { + img->xsize = 512; + img->ysize = 768; + } + else + { + img->xsize = 768; + img->ysize = 512; + } + + ImageSetMaxTiles(img, 0); + + bpp = ImageGetDepth(img); + in = malloc(768 * 3); + out = malloc(768 * bpp); + + if (bpp > 1) + rgb = malloc(768 * 3); + + if (rotation) + { + xstart = 767 * bpp; + xdir = -2 * bpp; + } + else + { + xstart = 0; + xdir = 0; + } + + /* + * Read the image file... + */ + + for (y = 0; y < 512; y += 2) + { + /* + * Grab the next two scanlines: + * + * YYYYYYYYYYYYYYY... + * YYYYYYYYYYYYYYY... + * CbCbCb...CrCrCr... + */ + + if (fread(in, 1, 768 * 3, fp) < (768 * 3)) + { + /* + * Couldn't read a row of data - return an error! + */ + + free(in); + free(out); + + return (-1); + } + + /* + * Process the two scanlines... + */ + + for (pass = 0, iy = in; pass < 2; pass ++) + { + if (bpp == 1) + { + /* + * Just extract the luminance channel from the line and put it + * in the image... + */ + + if (primary == IMAGE_BLACK) + { + if (rotation) + { + for (rgbptr = out + xstart, x = 0; x < 768; x ++) + *rgbptr-- = 255 - *iy++; + + if (lut) + ImageLut(out, 768, lut); + + ImagePutCol(img, 511 - y - pass, 0, 768, out); + } + else + { + ImageWhiteToBlack(iy, out, 768); + + if (lut) + ImageLut(out, 768, lut); + + ImagePutRow(img, 0, y + pass, 768, out); + iy += 768; + } + } + else if (rotation) + { + for (rgbptr = out + xstart, x = 0; x < 768; x ++) + *rgbptr-- = 255 - *iy++; + + if (lut) + ImageLut(out, 768, lut); + + ImagePutCol(img, 511 - y - pass, 0, 768, out); + } + else + { + if (lut) + ImageLut(iy, 768, lut); + + ImagePutRow(img, 0, y + pass, 768, iy); + iy += 768; + } + } + else + { + /* + * Convert YCbCr to RGB... While every pixel gets a luminance + * value, adjacent pixels share chroma information. + */ + + for (x = 0, rgbptr = rgb + xstart, icb = in + 1536, icr = in + 1920; + x < 768; + x ++, iy ++, rgbptr += xdir) + { + if (!(x & 1)) + { + cb = (float)(*icb - 156); + cr = (float)(*icr - 137); + } + + temp = 92241 * (*iy); + + temp2 = (temp + 86706 * cr) / 65536; + if (temp2 < 0) + *rgbptr++ = 0; + else if (temp2 > 255) + *rgbptr++ = 255; + else + *rgbptr++ = temp2; + + temp2 = (temp - 25914 * cb - 44166 * cr) / 65536; + if (temp2 < 0) + *rgbptr++ = 0; + else if (temp2 > 255) + *rgbptr++ = 255; + else + *rgbptr++ = temp2; + + temp2 = (temp + 133434 * cb) / 65536; + if (temp2 < 0) + *rgbptr++ = 0; + else if (temp2 > 255) + *rgbptr++ = 255; + else + *rgbptr++ = temp2; + + if (x & 1) + { + icb ++; + icr ++; + } + } + + /* + * Adjust the hue and saturation if needed... + */ + + if (saturation != 100 || hue != 0) + ImageRGBAdjust(rgb, 768, saturation, hue); + + /* + * Then convert the RGB data to the appropriate colorspace and + * put it in the image... + */ + + if (img->colorspace == IMAGE_RGB) + { + if (lut) + ImageLut(rgb, 768 * 3, lut); + + if (rotation) + ImagePutCol(img, 511 - y - pass, 0, 768, rgb); + else + ImagePutRow(img, 0, y + pass, 768, rgb); + } + else + { + switch (img->colorspace) + { + case IMAGE_CMY : + ImageRGBToCMY(rgb, out, 768); + break; + case IMAGE_CMYK : + ImageRGBToCMYK(rgb, out, 768); + break; + } + + if (lut) + ImageLut(out, 768 * bpp, lut); + + if (rotation) + ImagePutCol(img, 511 - y - pass, 0, 768, out); + else + ImagePutRow(img, 0, y + pass, 768, out); + } + } + } + } + + /* + * Free memory and return... + */ + + free(in); + free(out); + if (bpp > 1) + free(rgb); + + return (0); +} + + +/* + * End of "$Id$". + */ diff --git a/filter/image-png.c b/filter/image-png.c new file mode 100644 index 0000000000..b745581573 --- /dev/null +++ b/filter/image-png.c @@ -0,0 +1,205 @@ +/* + * "$Id$" + * + * PNG image routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1993-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * ImageReadPNG() - Read a PNG image file. + */ + +/* + * Include necessary headers... + */ + +#include "image.h" + +#if defined(HAVE_LIBPNG) && defined(HAVE_LIBZ) +#include /* Portable Network Graphics (PNG) definitions */ + + +/* + * 'ImageReadPNG()' - Read a PNG image file. + */ + +int /* O - Read status */ +ImageReadPNG(image_t *img, /* IO - Image */ + FILE *fp, /* I - Image file */ + int primary, /* I - Primary choice for colorspace */ + int secondary, /* I - Secondary choice for colorspace */ + int saturation,/* I - Color saturation (%) */ + int hue, /* I - Color hue (degrees) */ + ib_t *lut) /* I - Lookup table for gamma/brightness */ +{ + int y; /* Looping var */ + png_structp pp; /* PNG read pointer */ + png_infop info; /* PNG info pointers */ + int bpp; /* Bytes per pixel */ + ib_t *in, /* Input pixels */ + *out; /* Output pixels */ + + + /* + * Setup the PNG data structures... + */ + + pp = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + info = png_create_info_struct(pp); + + /* + * Initialize the PNG read "engine"... + */ + + png_init_io(pp, fp); + + /* + * Get the image dimensions and load the output image... + */ + + png_read_info(pp, info); + + if (info->color_type == PNG_COLOR_TYPE_PALETTE) + png_set_expand(pp); + + if (info->color_type == PNG_COLOR_TYPE_GRAY || + info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + img->colorspace = secondary; + else + img->colorspace = primary; + + img->xsize = info->width; + img->ysize = info->height; + + if (info->valid & PNG_INFO_pHYs && + info->phys_unit_type == PNG_RESOLUTION_METER) + { + img->xppi = (int)((float)info->x_pixels_per_unit * 0.0254); + img->yppi = (int)((float)info->y_pixels_per_unit * 0.0254); + } + + ImageSetMaxTiles(img, 0); + + if (info->bit_depth < 8) + { + png_set_packing(pp); + + if (info->valid & PNG_INFO_sBIT) + png_set_shift(pp, &(info->sig_bit)); + } + else if (info->bit_depth == 16) + png_set_strip_16(pp); + + if (info->color_type == PNG_COLOR_TYPE_GRAY || + info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + in = malloc(img->xsize); + else + in = malloc(img->xsize * 3); + + bpp = ImageGetDepth(img); + out = malloc(img->xsize * bpp); + + /* + * This doesn't work for interlaced PNG files... :( + */ + + for (y = 0; y < img->ysize; y ++) + { + if (info->color_type == PNG_COLOR_TYPE_GRAY || + info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (img->colorspace == IMAGE_WHITE) + png_read_row(pp, (png_bytep)out, NULL); + else + { + png_read_row(pp, (png_bytep)in, NULL); + + switch (img->colorspace) + { + case IMAGE_RGB : + ImageWhiteToRGB(in, out, img->xsize); + break; + case IMAGE_BLACK : + ImageWhiteToBlack(in, out, img->xsize); + break; + case IMAGE_CMY : + ImageWhiteToCMY(in, out, img->xsize); + break; + case IMAGE_CMYK : + ImageWhiteToCMYK(in, out, img->xsize); + break; + } + } + } + else + { + if (img->colorspace == IMAGE_RGB) + { + png_read_row(pp, (png_bytep)out, NULL); + + if (saturation != 100 || hue != 0) + ImageRGBAdjust(out, img->xsize, saturation, hue); + } + else + { + png_read_row(pp, (png_bytep)in, NULL); + + if ((saturation != 100 || hue != 0) && bpp > 1) + ImageRGBAdjust(in, img->xsize, saturation, hue); + + switch (img->colorspace) + { + case IMAGE_WHITE : + ImageRGBToWhite(in, out, img->xsize); + break; + case IMAGE_BLACK : + ImageRGBToBlack(in, out, img->xsize); + break; + case IMAGE_CMY : + ImageRGBToCMY(in, out, img->xsize); + break; + case IMAGE_CMYK : + ImageRGBToCMYK(in, out, img->xsize); + break; + } + } + } + + if (lut) + ImageLut(out, img->xsize * bpp, lut); + + ImagePutRow(img, 0, y, img->xsize, out); + } + + png_read_end(pp, info); + png_read_destroy(pp, info, NULL); + + fclose(fp); + + return (0); +} + + +#endif /* HAVE_LIBPNG && HAVE_LIBZ */ + + +/* + * End of "$Id$". + */ diff --git a/filter/image-pnm.c b/filter/image-pnm.c new file mode 100644 index 0000000000..d827812fe7 --- /dev/null +++ b/filter/image-pnm.c @@ -0,0 +1,288 @@ +/* + * "$Id$" + * + * Portable Any Map file routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1993-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * ImageReadPNM() - Read a PNM image file. + */ + +/* + * Include necessary headers... + */ + +#include "image.h" +#include + + +/* + * 'ImageReadPNM()' - Read a PNM image file. + */ + +int /* O - Read status */ +ImageReadPNM(image_t *img, /* IO - Image */ + FILE *fp, /* I - Image file */ + int primary, /* I - Primary choice for colorspace */ + int secondary, /* I - Secondary choice for colorspace */ + int saturation,/* I - Color saturation (%) */ + int hue, /* I - Color hue (degrees) */ + ib_t *lut) /* I - Lookup table for gamma/brightness */ +{ + int x, y; /* Looping vars */ + int bpp; /* Bytes per pixel */ + ib_t *in, /* Input pixels */ + *inptr, /* Current input pixel */ + *out, /* Output pixels */ + *outptr, /* Current output pixel */ + bit; /* Bit in input line */ + char line[255], /* Input line */ + *lineptr; /* Pointer in line */ + int format, /* Format of PNM file */ + val, /* Pixel value */ + maxval; /* Maximum pixel value */ + + + /* + * Read the file header in the format: + * + * Pformat + * # comment1 + * # comment2 + * ... + * # commentN + * width + * height + * max sample + */ + + lineptr = fgets(line, sizeof(line), fp); + lineptr ++; + + format = atoi(lineptr); + while (isdigit(*lineptr)) + lineptr ++; + + while (lineptr != NULL && img->xsize == 0) + { + if (*lineptr == '\0' || *lineptr == '#') + lineptr = fgets(line, sizeof(line), fp); + else if (isdigit(*lineptr)) + { + img->xsize = atoi(lineptr); + while (isdigit(*lineptr)) + lineptr ++; + } + else + lineptr ++; + } + + while (lineptr != NULL && img->ysize == 0) + { + if (*lineptr == '\0' || *lineptr == '#') + lineptr = fgets(line, sizeof(line), fp); + else if (isdigit(*lineptr)) + { + img->ysize = atoi(lineptr); + while (isdigit(*lineptr)) + lineptr ++; + } + else + lineptr ++; + } + + if (format != 1 && format != 4) + { + maxval = 0; + + while (lineptr != NULL && maxval == 0) + { + if (*lineptr == '\0' || *lineptr == '#') + lineptr = fgets(line, sizeof(line), fp); + else if (isdigit(*lineptr)) + { + maxval = atoi(lineptr); + while (isdigit(*lineptr)) + lineptr ++; + } + else + lineptr ++; + } + } + else + maxval = 1; + + if (format == 1 || format == 2 || format == 4 || format == 5) + img->colorspace = secondary; + else + img->colorspace = primary; + + ImageSetMaxTiles(img, 0); + + bpp = ImageGetDepth(img); + in = malloc(img->xsize * 3); + out = malloc(img->xsize * bpp); + + /* + * Read the image file... + */ + + for (y = 0; y < img->ysize; y ++) + { + switch (format) + { + case 1 : + case 2 : + for (x = img->xsize, inptr = in; x > 0; x --, inptr ++) + if (fscanf(fp, "%d", &val) == 1) + *inptr = 255 * val / maxval; + break; + + case 3 : + for (x = img->xsize, inptr = in; x > 0; x --, inptr += 3) + { + if (fscanf(fp, "%d", &val) == 1) + inptr[0] = 255 * val / maxval; + if (fscanf(fp, "%d", &val) == 1) + inptr[1] = 255 * val / maxval; + if (fscanf(fp, "%d", &val) == 1) + inptr[2] = 255 * val / maxval; + } + break; + + case 4 : + fread(out, (img->xsize + 7) / 8, 1, fp); + for (x = img->xsize, inptr = in, outptr = out, bit = 128; + x > 0; + x --, inptr ++) + { + if (*outptr & bit) + *inptr = 255; + else + *inptr = 0; + + if (bit > 1) + bit >>= 1; + else + { + bit = 128; + inptr ++; + } + } + break; + + case 5 : + fread(in, img->xsize, 1, fp); + break; + + case 6 : + fread(in, img->xsize, 3, fp); + break; + } + + switch (format) + { + case 1 : + case 2 : + case 4 : + case 5 : + if (img->colorspace == IMAGE_WHITE) + { + if (lut) + ImageLut(in, img->xsize, lut); + + ImagePutRow(img, 0, y, img->xsize, in); + } + else + { + switch (img->colorspace) + { + case IMAGE_RGB : + ImageWhiteToRGB(in, out, img->xsize); + break; + case IMAGE_BLACK : + ImageWhiteToBlack(in, out, img->xsize); + break; + case IMAGE_CMY : + ImageWhiteToCMY(in, out, img->xsize); + break; + case IMAGE_CMYK : + ImageWhiteToCMYK(in, out, img->xsize); + break; + } + + if (lut) + ImageLut(out, img->xsize * bpp, lut); + + ImagePutRow(img, 0, y, img->xsize, out); + } + break; + + default : + if ((saturation != 100 || hue != 0) && bpp > 1) + ImageRGBAdjust(in, img->xsize, saturation, hue); + + if (img->colorspace == IMAGE_RGB) + { + if (lut) + ImageLut(in, img->xsize * 3, lut); + + ImagePutRow(img, 0, y, img->xsize, in); + } + else + { + switch (img->colorspace) + { + case IMAGE_WHITE : + ImageRGBToWhite(in, out, img->xsize); + break; + case IMAGE_BLACK : + ImageRGBToBlack(in, out, img->xsize); + break; + case IMAGE_CMY : + ImageRGBToCMY(in, out, img->xsize); + break; + case IMAGE_CMYK : + ImageRGBToCMYK(in, out, img->xsize); + break; + } + + if (lut) + ImageLut(out, img->xsize * bpp, lut); + + ImagePutRow(img, 0, y, img->xsize, out); + } + break; + } + } + + free(in); + free(out); + + fclose(fp); + + return (0); +} + + +/* + * End of "$Id$". + */ diff --git a/filter/image-sgi.c b/filter/image-sgi.c new file mode 100644 index 0000000000..59661b8720 --- /dev/null +++ b/filter/image-sgi.c @@ -0,0 +1,267 @@ +/* + * "$Id$" + * + * SGI image file routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1993-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * ImageReadSGI() - Read a SGI image file. + */ + +/* + * Include necessary headers... + */ + +#include "image.h" +#include "image-sgi.h" + + +/* + * 'ImageReadSGI()' - Read a SGI image file. + */ + +int /* O - Read status */ +ImageReadSGI(image_t *img, /* IO - Image */ + FILE *fp, /* I - Image file */ + int primary, /* I - Primary choice for colorspace */ + int secondary, /* I - Secondary choice for colorspace */ + int saturation,/* I - Color saturation (%) */ + int hue, /* I - Color hue (degrees) */ + ib_t *lut) /* I - Lookup table for gamma/brightness */ +{ + int i, y; /* Looping vars */ + int bpp; /* Bytes per pixel */ + sgi_t *sgip; /* SGI image file */ + ib_t *in, /* Input pixels */ + *inptr, /* Current input pixel */ + *out; /* Output pixels */ + unsigned short *rows[4], /* Row pointers for image data */ + *red, + *green, + *blue, + *gray, + *alpha; + + + /* + * Setup the SGI file... + */ + + sgip = sgiOpenFile(fp, SGI_READ, 0, 0, 0, 0, 0); + + /* + * Get the image dimensions and load the output image... + */ + + if (sgip->zsize < 3) + img->colorspace = secondary; + else + img->colorspace = primary; + + img->xsize = sgip->xsize; + img->ysize = sgip->ysize; + + ImageSetMaxTiles(img, 0); + + bpp = ImageGetDepth(img); + in = malloc(img->xsize * sgip->zsize); + out = malloc(img->xsize * bpp); + + rows[0] = calloc(img->xsize * sgip->zsize, sizeof(unsigned short)); + for (i = 1; i < sgip->zsize; i ++) + rows[i] = rows[0] + i * img->xsize; + + /* + * Read the SGI image file... + */ + + for (y = 0; y < img->ysize; y ++) + { + for (i = 0; i < sgip->zsize; i ++) + sgiGetRow(sgip, rows[i], img->ysize - 1 - y, i); + + switch (sgip->zsize) + { + case 1 : + if (sgip->bpp == 1) + for (i = img->xsize - 1, gray = rows[0], inptr = in; + i >= 0; + i --) + { + *inptr++ = *gray++; + } + else + for (i = img->xsize - 1, gray = rows[0], inptr = in; + i >= 0; + i --) + { + *inptr++ = (*gray++) / 256 + 128; + } + break; + case 2 : + if (sgip->bpp == 1) + for (i = img->xsize - 1, gray = rows[0], alpha = rows[1], inptr = in; + i >= 0; + i --) + { + *inptr++ = (*gray++) * (*alpha++) / 255; + } + else + for (i = img->xsize - 1, gray = rows[0], alpha = rows[1], inptr = in; + i >= 0; + i --) + { + *inptr++ = ((*gray++) / 256 + 128) * (*alpha++) / 32767; + } + break; + case 3 : + if (sgip->bpp == 1) + for (i = img->xsize - 1, red = rows[0], green = rows[1], + blue = rows[2], inptr = in; + i >= 0; + i --) + { + *inptr++ = *red++; + *inptr++ = *green++; + *inptr++ = *blue++; + } + else + for (i = img->xsize - 1, red = rows[0], green = rows[1], + blue = rows[2], inptr = in; + i >= 0; + i --) + { + *inptr++ = (*red++) / 256 + 128; + *inptr++ = (*green++) / 256 + 128; + *inptr++ = (*blue++) / 256 + 128; + } + break; + case 4 : + if (sgip->bpp == 1) + for (i = img->xsize - 1, red = rows[0], green = rows[1], + blue = rows[2], alpha = rows[3], inptr = in; + i >= 0; + i --) + { + *inptr++ = (*red++) * (*alpha) / 255; + *inptr++ = (*green++) * (*alpha) / 255; + *inptr++ = (*blue++) * (*alpha++) / 255; + } + else + for (i = img->xsize - 1, red = rows[0], green = rows[1], + blue = rows[2], inptr = in; + i >= 0; + i --) + { + *inptr++ = ((*red++) / 256 + 128) * (*alpha) / 32767; + *inptr++ = ((*green++) / 256 + 128) * (*alpha) / 32767; + *inptr++ = ((*blue++) / 256 + 128) * (*alpha++) / 32767; + } + break; + } + + if (sgip->zsize < 3) + { + if (img->colorspace == IMAGE_WHITE) + { + if (lut) + ImageLut(in, img->xsize, lut); + + ImagePutRow(img, 0, y, img->xsize, in); + } + else + { + switch (img->colorspace) + { + case IMAGE_RGB : + ImageWhiteToRGB(in, out, img->xsize); + break; + case IMAGE_BLACK : + ImageWhiteToBlack(in, out, img->xsize); + break; + case IMAGE_CMY : + ImageWhiteToCMY(in, out, img->xsize); + break; + case IMAGE_CMYK : + ImageWhiteToCMYK(in, out, img->xsize); + break; + } + + if (lut) + ImageLut(out, img->xsize * bpp, lut); + + ImagePutRow(img, 0, y, img->xsize, out); + } + } + else + { + if (img->colorspace == IMAGE_RGB) + { + if (saturation != 100 || hue != 0) + ImageRGBAdjust(in, img->xsize, saturation, hue); + + if (lut) + ImageLut(in, img->xsize * 3, lut); + + ImagePutRow(img, 0, y, img->xsize, in); + } + else + { + if ((saturation != 100 || hue != 0) && bpp > 1) + ImageRGBAdjust(in, img->xsize, saturation, hue); + + switch (img->colorspace) + { + case IMAGE_WHITE : + ImageRGBToWhite(in, out, img->xsize); + break; + case IMAGE_BLACK : + ImageRGBToBlack(in, out, img->xsize); + break; + case IMAGE_CMY : + ImageRGBToCMY(in, out, img->xsize); + break; + case IMAGE_CMYK : + ImageRGBToCMYK(in, out, img->xsize); + break; + } + + if (lut) + ImageLut(out, img->xsize * bpp, lut); + + ImagePutRow(img, 0, y, img->xsize, out); + } + } + } + + free(in); + free(out); + free(rows[0]); + + sgiClose(sgip); + + return (0); +} + + +/* + * End of "$Id$". + */ diff --git a/filter/image-sgi.h b/filter/image-sgi.h new file mode 100644 index 0000000000..0b8220d32e --- /dev/null +++ b/filter/image-sgi.h @@ -0,0 +1,94 @@ +/* + * "$Id$" + * + * SGI image file format library definitions for the Common UNIX Printing + * System (CUPS). + * + * Copyright 1993-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + */ + +#ifndef _SGI_H_ +# define _SGI_H_ + +# include +# include +# include + +# ifdef __cplusplus +extern "C" { +# endif + + +/* + * Constants... + */ + +# define SGI_MAGIC 474 /* Magic number in image file */ + +# define SGI_READ 0 /* Read from an SGI image file */ +# define SGI_WRITE 1 /* Write to an SGI image file */ + +# define SGI_COMP_NONE 0 /* No compression */ +# define SGI_COMP_RLE 1 /* Run-length encoding */ +# define SGI_COMP_ARLE 2 /* Agressive run-length encoding */ + + +/* + * Image structure... + */ + +typedef struct +{ + FILE *file; /* Image file */ + int mode, /* File open mode */ + bpp, /* Bytes per pixel/channel */ + comp; /* Compression */ + unsigned short xsize, /* Width in pixels */ + ysize, /* Height in pixels */ + zsize; /* Number of channels */ + long firstrow, /* File offset for first row */ + nextrow, /* File offset for next row */ + **table, /* Offset table for compression */ + **length; /* Length table for compression */ + unsigned short *arle_row; /* Advanced RLE compression buffer */ + long arle_offset, /* Advanced RLE buffer offset */ + arle_length; /* Advanced RLE buffer length */ +} sgi_t; + + +/* + * Prototypes... + */ + +extern int sgiClose(sgi_t *sgip); +extern int sgiGetRow(sgi_t *sgip, unsigned short *row, int y, int z); +extern sgi_t *sgiOpen(char *filename, int mode, int comp, int bpp, + int xsize, int ysize, int zsize); +extern sgi_t *sgiOpenFile(FILE *file, int mode, int comp, int bpp, + int xsize, int ysize, int zsize); +extern int sgiPutRow(sgi_t *sgip, unsigned short *row, int y, int z); + +# ifdef __cplusplus +} +# endif +#endif /* !_SGI_H_ */ + +/* + * End of "$Id$". + */ diff --git a/filter/image-sgilib.c b/filter/image-sgilib.c new file mode 100644 index 0000000000..c9f3d57d48 --- /dev/null +++ b/filter/image-sgilib.c @@ -0,0 +1,857 @@ +/* + * "$Id$" + * + * SGI image file format library routines for the Common UNIX Printing + * System (CUPS). + * + * Copyright 1993-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * sgiClose() - Close an SGI image file. + * sgiGetRow() - Get a row of image data from a file. + * sgiOpen() - Open an SGI image file for reading or writing. + * sgiOpenFile() - Open an SGI image file for reading or writing. + * sgiPutRow() - Put a row of image data to a file. + * getlong() - Get a 32-bit big-endian integer. + * getshort() - Get a 16-bit big-endian integer. + * putlong() - Put a 32-bit big-endian integer. + * putshort() - Put a 16-bit big-endian integer. + * read_rle8() - Read 8-bit RLE data. + * read_rle16() - Read 16-bit RLE data. + * write_rle8() - Write 8-bit RLE data. + * write_rle16() - Write 16-bit RLE data. + */ + +#include "image-sgi.h" + + +/* + * Local functions... + */ + +static int getlong(FILE *); +static int getshort(FILE *); +static int putlong(long, FILE *); +static int putshort(unsigned short, FILE *); +static int read_rle8(FILE *, unsigned short *, int); +static int read_rle16(FILE *, unsigned short *, int); +static int write_rle8(FILE *, unsigned short *, int); +static int write_rle16(FILE *, unsigned short *, int); + + +/* + * 'sgiClose()' - Close an SGI image file. + */ + +int +sgiClose(sgi_t *sgip) /* I - SGI image */ +{ + int i; /* Return status */ + long *offset; /* Looping var for offset table */ + + + if (sgip == NULL) + return (-1); + + if (sgip->mode == SGI_WRITE && sgip->comp != SGI_COMP_NONE) + { + /* + * Write the scanline offset table to the file... + */ + + fseek(sgip->file, 512, SEEK_SET); + + for (i = sgip->ysize * sgip->zsize, offset = sgip->table[0]; + i > 0; + i --, offset ++) + if (putlong(offset[0], sgip->file) < 0) + return (-1); + + for (i = sgip->ysize * sgip->zsize, offset = sgip->length[0]; + i > 0; + i --, offset ++) + if (putlong(offset[0], sgip->file) < 0) + return (-1); + } + + if (sgip->table != NULL) + { + free(sgip->table[0]); + free(sgip->table); + } + + if (sgip->length != NULL) + { + free(sgip->length[0]); + free(sgip->length); + } + + if (sgip->comp == SGI_COMP_ARLE) + free(sgip->arle_row); + + i = fclose(sgip->file); + free(sgip); + + return (i); +} + + +/* + * 'sgiGetRow()' - Get a row of image data from a file. + */ + +int +sgiGetRow(sgi_t *sgip, /* I - SGI image */ + unsigned short *row, /* O - Row to read */ + int y, /* I - Line to read */ + int z) /* I - Channel to read */ +{ + int x; /* X coordinate */ + long offset; /* File offset */ + + + if (sgip == NULL || + row == NULL || + y < 0 || y >= sgip->ysize || + z < 0 || z >= sgip->zsize) + return (-1); + + switch (sgip->comp) + { + case SGI_COMP_NONE : + /* + * Seek to the image row - optimize buffering by only seeking if + * necessary... + */ + + offset = 512 + (y + z * sgip->ysize) * sgip->xsize * sgip->bpp; + if (offset != ftell(sgip->file)) + fseek(sgip->file, offset, SEEK_SET); + + if (sgip->bpp == 1) + { + for (x = sgip->xsize; x > 0; x --, row ++) + *row = getc(sgip->file); + } + else + { + for (x = sgip->xsize; x > 0; x --, row ++) + *row = getshort(sgip->file); + } + break; + + case SGI_COMP_RLE : + offset = sgip->table[z][y]; + if (offset != ftell(sgip->file)) + fseek(sgip->file, offset, SEEK_SET); + + if (sgip->bpp == 1) + return (read_rle8(sgip->file, row, sgip->xsize)); + else + return (read_rle16(sgip->file, row, sgip->xsize)); + } + + return (0); +} + + +/* + * 'sgiOpen()' - Open an SGI image file for reading or writing. + */ + +sgi_t * +sgiOpen(char *filename, /* I - File to open */ + int mode, /* I - Open mode (SGI_READ or SGI_WRITE) */ + int comp, /* I - Type of compression */ + int bpp, /* I - Bytes per pixel */ + int xsize, /* I - Width of image in pixels */ + int ysize, /* I - Height of image in pixels */ + int zsize) /* I - Number of channels */ +{ + sgi_t *sgip; /* New SGI image file */ + FILE *file; /* Image file pointer */ + + + if (mode == SGI_READ) + file = fopen(filename, "rb"); + else + file = fopen(filename, "wb+"); + + if (file == NULL) + return (NULL); + + if ((sgip = sgiOpenFile(file, mode, comp, bpp, xsize, ysize, zsize)) == NULL) + fclose(file); + + return (sgip); +} + + +/* + * 'sgiOpenFile()' - Open an SGI image file for reading or writing. + */ + +sgi_t * +sgiOpenFile(FILE *file, /* I - File to open */ + int mode, /* I - Open mode (SGI_READ or SGI_WRITE) */ + int comp, /* I - Type of compression */ + int bpp, /* I - Bytes per pixel */ + int xsize, /* I - Width of image in pixels */ + int ysize, /* I - Height of image in pixels */ + int zsize) /* I - Number of channels */ +{ + int i, j; /* Looping var */ + char name[80]; /* Name of file in image header */ + short magic; /* Magic number */ + sgi_t *sgip; /* New image pointer */ + + + if ((sgip = calloc(sizeof(sgi_t), 1)) == NULL) + return (NULL); + + sgip->file = file; + + switch (mode) + { + case SGI_READ : + sgip->mode = SGI_READ; + + magic = getshort(sgip->file); + if (magic != SGI_MAGIC) + { + free(sgip); + return (NULL); + } + + sgip->comp = getc(sgip->file); + sgip->bpp = getc(sgip->file); + getshort(sgip->file); /* Dimensions */ + sgip->xsize = getshort(sgip->file); + sgip->ysize = getshort(sgip->file); + sgip->zsize = getshort(sgip->file); + getlong(sgip->file); /* Minimum pixel */ + getlong(sgip->file); /* Maximum pixel */ + + if (sgip->comp) + { + /* + * This file is compressed; read the scanline tables... + */ + + fseek(sgip->file, 512, SEEK_SET); + + sgip->table = calloc(sgip->zsize, sizeof(long *)); + sgip->table[0] = calloc(sgip->ysize * sgip->zsize, sizeof(long)); + for (i = 1; i < sgip->zsize; i ++) + sgip->table[i] = sgip->table[0] + i * sgip->ysize; + + for (i = 0; i < sgip->zsize; i ++) + for (j = 0; j < sgip->ysize; j ++) + sgip->table[i][j] = getlong(sgip->file); + } + break; + + case SGI_WRITE : + if (xsize < 1 || + ysize < 1 || + zsize < 1 || + bpp < 1 || bpp > 2 || + comp < SGI_COMP_NONE || comp > SGI_COMP_ARLE) + { + free(sgip); + return (NULL); + } + + sgip->mode = SGI_WRITE; + + putshort(SGI_MAGIC, sgip->file); + putc((sgip->comp = comp) != 0, sgip->file); + putc(sgip->bpp = bpp, sgip->file); + putshort(3, sgip->file); /* Dimensions */ + putshort(sgip->xsize = xsize, sgip->file); + putshort(sgip->ysize = ysize, sgip->file); + putshort(sgip->zsize = zsize, sgip->file); + if (bpp == 1) + { + putlong(0, sgip->file); /* Minimum pixel */ + putlong(255, sgip->file); /* Maximum pixel */ + } + else + { + putlong(-32768, sgip->file); /* Minimum pixel */ + putlong(32767, sgip->file); /* Maximum pixel */ + } + putlong(0, sgip->file); /* Reserved */ + + memset(name, 0, sizeof(name)); + fwrite(name, sizeof(name), 1, sgip->file); + + for (i = 0; i < 102; i ++) + putlong(0, sgip->file); + + switch (comp) + { + case SGI_COMP_NONE : /* No compression */ + /* + * This file is uncompressed. To avoid problems with sparse files, + * we need to write blank pixels for the entire image... + */ + + if (bpp == 1) + { + for (i = xsize * ysize * zsize; i > 0; i --) + putc(0, sgip->file); + } + else + { + for (i = xsize * ysize * zsize; i > 0; i --) + putshort(0, sgip->file); + } + break; + + case SGI_COMP_ARLE : /* Aggressive RLE */ + sgip->arle_row = calloc(xsize, sizeof(unsigned short)); + sgip->arle_offset = 0; + + case SGI_COMP_RLE : /* Run-Length Encoding */ + /* + * This file is compressed; write the (blank) scanline tables... + */ + + for (i = 2 * ysize * zsize; i > 0; i --) + putlong(0, sgip->file); + + sgip->firstrow = ftell(sgip->file); + sgip->nextrow = ftell(sgip->file); + sgip->table = calloc(sgip->zsize, sizeof(long *)); + sgip->table[0] = calloc(sgip->ysize * sgip->zsize, sizeof(long)); + for (i = 1; i < sgip->zsize; i ++) + sgip->table[i] = sgip->table[0] + i * sgip->ysize; + sgip->length = calloc(sgip->zsize, sizeof(long *)); + sgip->length[0] = calloc(sgip->ysize * sgip->zsize, sizeof(long)); + for (i = 1; i < sgip->zsize; i ++) + sgip->length[i] = sgip->length[0] + i * sgip->ysize; + break; + } + break; + + default : + free(sgip); + return (NULL); + } + + return (sgip); +} + + +/* + * 'sgiPutRow()' - Put a row of image data to a file. + */ + +int +sgiPutRow(sgi_t *sgip, /* I - SGI image */ + unsigned short *row, /* I - Row to write */ + int y, /* I - Line to write */ + int z) /* I - Channel to write */ +{ + int x; /* X coordinate */ + long offset; /* File offset */ + + + if (sgip == NULL || + row == NULL || + y < 0 || y >= sgip->ysize || + z < 0 || z >= sgip->zsize) + return (-1); + + switch (sgip->comp) + { + case SGI_COMP_NONE : + /* + * Seek to the image row - optimize buffering by only seeking if + * necessary... + */ + + offset = 512 + (y + z * sgip->ysize) * sgip->xsize * sgip->bpp; + if (offset != ftell(sgip->file)) + fseek(sgip->file, offset, SEEK_SET); + + if (sgip->bpp == 1) + { + for (x = sgip->xsize; x > 0; x --, row ++) + putc(*row, sgip->file); + } + else + { + for (x = sgip->xsize; x > 0; x --, row ++) + putshort(*row, sgip->file); + } + break; + + case SGI_COMP_ARLE : + if (sgip->table[z][y] != 0) + return (-1); + + /* + * First check the last row written... + */ + + if (sgip->arle_offset > 0) + { + for (x = 0; x < sgip->xsize; x ++) + if (row[x] != sgip->arle_row[x]) + break; + + if (x == sgip->xsize) + { + sgip->table[z][y] = sgip->arle_offset; + sgip->length[z][y] = sgip->arle_length; + return (0); + } + } + + /* + * If that didn't match, search all the previous rows... + */ + + fseek(sgip->file, sgip->firstrow, SEEK_SET); + + if (sgip->bpp == 1) + { + for (;;) + { + sgip->arle_offset = ftell(sgip->file); + if ((sgip->arle_length = read_rle8(sgip->file, sgip->arle_row, sgip->xsize)) < 0) + { + x = 0; + break; + } + + if (memcmp(row, sgip->arle_row, sgip->xsize * sizeof(unsigned short)) == 0) + { + x = sgip->xsize; + break; + } + } + } + else + { + for (;;) + { + sgip->arle_offset = ftell(sgip->file); + if ((sgip->arle_length = read_rle16(sgip->file, sgip->arle_row, sgip->xsize)) < 0) + { + x = 0; + break; + } + + if (memcmp(row, sgip->arle_row, sgip->xsize * sizeof(unsigned short)) == 0) + { + x = sgip->xsize; + break; + } + } + } + + if (x == sgip->xsize) + { + sgip->table[z][y] = sgip->arle_offset; + sgip->length[z][y] = sgip->arle_length; + return (0); + } + else + fseek(sgip->file, 0, SEEK_END); /* Clear EOF */ + + case SGI_COMP_RLE : + if (sgip->table[z][y] != 0) + return (-1); + + offset = sgip->table[z][y] = sgip->nextrow; + + if (offset != ftell(sgip->file)) + fseek(sgip->file, offset, SEEK_SET); + + if (sgip->bpp == 1) + x = write_rle8(sgip->file, row, sgip->xsize); + else + x = write_rle16(sgip->file, row, sgip->xsize); + + if (sgip->comp == SGI_COMP_ARLE) + { + sgip->arle_offset = offset; + sgip->arle_length = x; + memcpy(sgip->arle_row, row, sgip->xsize * sizeof(unsigned short)); + } + + sgip->nextrow = ftell(sgip->file); + sgip->length[z][y] = x; + + return (x); + } + + return (0); +} + + +/* + * 'getlong()' - Get a 32-bit big-endian integer. + */ + +static int +getlong(FILE *fp) /* I - File to read from */ +{ + unsigned char b[4]; + + + fread(b, 4, 1, fp); + return ((b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]); +} + + +/* + * 'getshort()' - Get a 16-bit big-endian integer. + */ + +static int +getshort(FILE *fp) /* I - File to read from */ +{ + unsigned char b[2]; + + + fread(b, 2, 1, fp); + return ((b[0] << 8) | b[1]); +} + + +/* + * 'putlong()' - Put a 32-bit big-endian integer. + */ + +static int +putlong(long n, /* I - Long to write */ + FILE *fp) /* I - File to write to */ +{ + if (putc(n >> 24, fp) == EOF) + return (EOF); + if (putc(n >> 16, fp) == EOF) + return (EOF); + if (putc(n >> 8, fp) == EOF) + return (EOF); + if (putc(n, fp) == EOF) + return (EOF); + else + return (0); +} + + +/* + * 'putshort()' - Put a 16-bit big-endian integer. + */ + +static int +putshort(unsigned short n, /* I - Short to write */ + FILE *fp) /* I - File to write to */ +{ + if (putc(n >> 8, fp) == EOF) + return (EOF); + if (putc(n, fp) == EOF) + return (EOF); + else + return (0); +} + + +/* + * 'read_rle8()' - Read 8-bit RLE data. + */ + +static int +read_rle8(FILE *fp, /* I - File to read from */ + unsigned short *row, /* O - Data */ + int xsize) /* I - Width of data in pixels */ +{ + int i, /* Looping var */ + ch, /* Current character */ + count, /* RLE count */ + length; /* Number of bytes read... */ + + + length = 0; + + while (xsize > 0) + { + if ((ch = getc(fp)) == EOF) + return (-1); + length ++; + + count = ch & 127; + if (count == 0) + break; + + if (ch & 128) + { + for (i = 0; i < count; i ++, row ++, xsize --, length ++) + *row = getc(fp); + } + else + { + ch = getc(fp); + length ++; + for (i = 0; i < count; i ++, row ++, xsize --) + *row = ch; + } + } + + return (xsize > 0 ? -1 : length); +} + + +/* + * 'read_rle16()' - Read 16-bit RLE data. + */ + +static int +read_rle16(FILE *fp, /* I - File to read from */ + unsigned short *row, /* O - Data */ + int xsize)/* I - Width of data in pixels */ +{ + int i, /* Looping var */ + ch, /* Current character */ + count, /* RLE count */ + length; /* Number of bytes read... */ + + + length = 0; + + while (xsize > 0) + { + if ((ch = getshort(fp)) == EOF) + return (-1); + length ++; + + count = ch & 127; + if (count == 0) + break; + + if (ch & 128) + { + for (i = 0; i < count; i ++, row ++, xsize --, length ++) + *row = getshort(fp); + } + else + { + ch = getshort(fp); + length ++; + for (i = 0; i < count; i ++, row ++, xsize --) + *row = ch; + } + } + + return (xsize > 0 ? -1 : length * 2); +} + + +/* + * 'write_rle8()' - Write 8-bit RLE data. + */ + +static int +write_rle8(FILE *fp, /* I - File to write to */ + unsigned short *row, /* I - Data */ + int xsize)/* I - Width of data in pixels */ +{ + int length, + count, + i, + x; + unsigned short *start, + repeat; + + + for (x = xsize, length = 0; x > 0;) + { + start = row; + row += 2; + x -= 2; + + while (x > 0 && (row[-2] != row[-1] || row[-1] != row[0])) + { + row ++; + x --; + } + + row -= 2; + x += 2; + + count = row - start; + while (count > 0) + { + i = count > 126 ? 126 : count; + count -= i; + + if (putc(128 | i, fp) == EOF) + return (-1); + length ++; + + while (i > 0) + { + if (putc(*start, fp) == EOF) + return (-1); + start ++; + i --; + length ++; + } + } + + if (x <= 0) + break; + + start = row; + repeat = row[0]; + + row ++; + x --; + + while (x > 0 && *row == repeat) + { + row ++; + x --; + } + + count = row - start; + while (count > 0) + { + i = count > 126 ? 126 : count; + count -= i; + + if (putc(i, fp) == EOF) + return (-1); + length ++; + + if (putc(repeat, fp) == EOF) + return (-1); + length ++; + } + } + + length ++; + + if (putc(0, fp) == EOF) + return (-1); + else + return (length); +} + + +/* + * 'write_rle16()' - Write 16-bit RLE data. + */ + +static int +write_rle16(FILE *fp, /* I - File to write to */ + unsigned short *row, /* I - Data */ + int xsize)/* I - Width of data in pixels */ +{ + int length, + count, + i, + x; + unsigned short *start, + repeat; + + + for (x = xsize, length = 0; x > 0;) + { + start = row; + row += 2; + x -= 2; + + while (x > 0 && (row[-2] != row[-1] || row[-1] != row[0])) + { + row ++; + x --; + } + + row -= 2; + x += 2; + + count = row - start; + while (count > 0) + { + i = count > 126 ? 126 : count; + count -= i; + + if (putshort(128 | i, fp) == EOF) + return (-1); + length ++; + + while (i > 0) + { + if (putshort(*start, fp) == EOF) + return (-1); + start ++; + i --; + length ++; + } + } + + if (x <= 0) + break; + + start = row; + repeat = row[0]; + + row ++; + x --; + + while (x > 0 && *row == repeat) + { + row ++; + x --; + } + + count = row - start; + while (count > 0) + { + i = count > 126 ? 126 : count; + count -= i; + + if (putshort(i, fp) == EOF) + return (-1); + length ++; + + if (putshort(repeat, fp) == EOF) + return (-1); + length ++; + } + } + + length ++; + + if (putshort(0, fp) == EOF) + return (-1); + else + return (2 * length); +} + + +/* + * End of "$Id$". + */ diff --git a/filter/image-sun.c b/filter/image-sun.c new file mode 100644 index 0000000000..f155dff266 --- /dev/null +++ b/filter/image-sun.c @@ -0,0 +1,376 @@ +/* + * "$Id$" + * + * Sun Raster image file routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1993-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * ImageReadSunRaster() - Read a SunRaster image file. + * read_unsigned() - Read a 32-bit unsigned integer. + */ + +/* + * Include necessary headers... + */ + +#include "image.h" + + +#define RAS_MAGIC 0x59a66a95 + + /* Sun supported ras_type's */ +#define RT_OLD 0 /* Raw pixrect image in 68000 byte order */ +#define RT_STANDARD 1 /* Raw pixrect image in 68000 byte order */ +#define RT_BYTE_ENCODED 2 /* Run-length compression of bytes */ +#define RT_FORMAT_RGB 3 /* XRGB or RGB instead of XBGR or BGR */ +#define RT_EXPERIMENTAL 0xffff /* Reserved for testing */ + + /* Sun registered ras_maptype's */ +#define RMT_RAW 2 + /* Sun supported ras_maptype's */ +#define RMT_NONE 0 /* ras_maplength is expected to be 0 */ +#define RMT_EQUAL_RGB 1 /* red[ras_maplength/3],green[],blue[] */ + +#define RAS_RLE 0x80 + +/* + * NOTES: + * Each line of the image is rounded out to a multiple of 16 bits. + * This corresponds to the rounding convention used by the memory pixrect + * package (/usr/include/pixrect/memvar.h) of the SunWindows system. + * The ras_encoding field (always set to 0 by Sun's supported software) + * was renamed to ras_length in release 2.0. As a result, rasterfiles + * of type 0 generated by the old software claim to have 0 length; for + * compatibility, code reading rasterfiles must be prepared to compute the + * true length from the width, height, and depth fields. + */ + +/* + * Local functions... + */ + +static unsigned read_unsigned(FILE *fp); + + +/* + * 'ImageReadSunRaster()' - Read a SunRaster image file. + */ + +int /* O - Read status */ +ImageReadSunRaster(image_t *img, /* IO - Image */ + FILE *fp, /* I - Image file */ + int primary, /* I - Primary choice for colorspace */ + int secondary, /* I - Secondary choice for colorspace */ + int saturation, /* I - Color saturation (%) */ + int hue, /* I - Color hue (degrees) */ + ib_t *lut) /* I - Lookup table for gamma/brightness */ +{ + int i, x, y, + bpp, /* Bytes per pixel */ + scanwidth, + run_count, + run_value; + ib_t *in, + *out, + *scanline, + *scanptr, + *p, + bit; + unsigned ras_depth, /* depth (1, 8, or 24 bits) of pixel */ + ras_type, /* type of file; see RT_* below */ + ras_maplength; /* length (bytes) of following map */ + unsigned char cmap[3][256]; /* colormap */ + + + /* + * Read the header; we already know that this is a raster file (ImageOpen + * checks this) so we don't need to check the magic number again. + */ + + read_unsigned(fp); /* Skip magic */ + img->xsize = read_unsigned(fp); + img->ysize = read_unsigned(fp); + ras_depth = read_unsigned(fp); + /* ras_length */read_unsigned(fp); + ras_type = read_unsigned(fp); + /* ras_maptype*/read_unsigned(fp); + ras_maplength = read_unsigned(fp); + + if (ras_maplength > 0) + { + fread(cmap[0], 1, ras_maplength / 3, fp); + fread(cmap[1], 1, ras_maplength / 3, fp); + fread(cmap[2], 1, ras_maplength / 3, fp); + } + + /* + * Compute the width of each line and allocate memory as needed... + */ + + scanwidth = (img->xsize * ras_depth + 7) / 8; + if (scanwidth & 1) + scanwidth ++; + + if (ras_depth < 24 && ras_maplength == 0) + { + img->colorspace = secondary; + in = malloc(img->xsize + 1); + } + else + { + img->colorspace = primary; + in = malloc(img->xsize * 3 + 1); + } + + bpp = ImageGetDepth(img); + out = malloc(img->xsize * bpp); + scanline = malloc(scanwidth); + run_count = 0; + + for (y = 0; y < img->ysize; y ++) + { + if (ras_depth != 8 || ras_maplength > 0) + p = scanline; + else + p = in; + + if (ras_type != RT_BYTE_ENCODED) + fread(p, scanwidth, 1, fp); + else + { + for (i = scanwidth; i > 0; i --, p ++) + { + if (run_count > 0) + { + *p = run_value; + run_count --; + } + else + { + run_value = getc(fp); + + if (run_value == RAS_RLE) + { + run_count = getc(fp); + if (run_count == 0) + *p = RAS_RLE; + else + run_value = *p = getc(fp); + } + else + *p = run_value; + } + } + } + + if (ras_depth == 1 && ras_maplength == 0) + { + /* + * 1-bit B&W image... + */ + + for (x = img->xsize, bit = 128, scanptr = scanline, p = in; + x > 0; + x --, p ++) + { + if (*scanptr & bit) + *p = 255; + else + *p = 0; + + if (bit > 1) + { + bit = 128; + scanptr ++; + } + else + bit >>= 1; + } + } + else if (ras_depth == 1) + { + /* + * 1-bit colormapped image... + */ + + for (x = img->xsize, bit = 128, scanptr = scanline, p = in; + x > 0; + x --) + { + if (*scanptr & bit) + { + *p++ = cmap[0][1]; + *p++ = cmap[1][1]; + *p++ = cmap[2][1]; + } + else + { + *p++ = cmap[0][0]; + *p++ = cmap[1][0]; + *p++ = cmap[2][0]; + } + + if (bit > 1) + { + bit = 128; + scanptr ++; + } + else + bit >>= 1; + } + } + else if (ras_depth == 8 && ras_maplength > 0) + { + /* + * 8-bit colormapped image. + */ + + for (x = img->xsize, scanptr = scanline, p = in; + x > 0; + x --) + { + *p++ = cmap[0][*scanptr]; + *p++ = cmap[1][*scanptr]; + *p++ = cmap[2][*scanptr++]; + } + } + else if (ras_depth == 24 && ras_type != RT_FORMAT_RGB) + { + /* + * Convert BGR to RGB... + */ + + for (x = img->xsize, scanptr = scanline, p = in; + x > 0; + x --, scanptr += 3) + { + *p++ = scanptr[2]; + *p++ = scanptr[1]; + *p++ = scanptr[0]; + } + } + + if (bpp == 1) + { + if (img->colorspace == IMAGE_WHITE) + { + if (lut) + ImageLut(in, img->xsize, lut); + + ImagePutRow(img, 0, y, img->xsize, in); + } + else + { + switch (img->colorspace) + { + case IMAGE_RGB : + ImageWhiteToRGB(in, out, img->xsize); + break; + case IMAGE_BLACK : + ImageWhiteToBlack(in, out, img->xsize); + break; + case IMAGE_CMY : + ImageWhiteToCMY(in, out, img->xsize); + break; + case IMAGE_CMYK : + ImageWhiteToCMYK(in, out, img->xsize); + break; + } + + if (lut) + ImageLut(out, img->xsize * bpp, lut); + + ImagePutRow(img, 0, y, img->xsize, out); + } + } + else + { + if (img->colorspace == IMAGE_RGB) + { + if (saturation != 100 || hue != 0) + ImageRGBAdjust(in, img->xsize, saturation, hue); + + if (lut) + ImageLut(in, img->xsize * 3, lut); + + ImagePutRow(img, 0, y, img->xsize, in); + } + else + { + if ((saturation != 100 || hue != 0) && bpp > 1) + ImageRGBAdjust(in, img->xsize, saturation, hue); + + switch (img->colorspace) + { + case IMAGE_WHITE : + ImageRGBToWhite(in, out, img->xsize); + break; + case IMAGE_BLACK : + ImageRGBToBlack(in, out, img->xsize); + break; + case IMAGE_CMY : + ImageRGBToCMY(in, out, img->xsize); + break; + case IMAGE_CMYK : + ImageRGBToCMYK(in, out, img->xsize); + break; + } + + if (lut) + ImageLut(out, img->xsize * bpp, lut); + + ImagePutRow(img, 0, y, img->xsize, out); + } + } + } + + free(scanline); + free(in); + free(out); + + fclose(fp); + + return (0); +} + + +/* + * 'read_unsigned()' - Read a 32-bit unsigned integer. + */ + +static unsigned /* O - Integer from file */ +read_unsigned(FILE *fp) /* I - File to read from */ +{ + unsigned v; /* Integer from file */ + + + v = getc(fp); + v = (v << 8) | getc(fp); + v = (v << 8) | getc(fp); + v = (v << 8) | getc(fp); + + return (v); +} + + +/* + * End of "$Id$". + */ diff --git a/filter/image-tiff.c b/filter/image-tiff.c new file mode 100644 index 0000000000..36455a71ff --- /dev/null +++ b/filter/image-tiff.c @@ -0,0 +1,1622 @@ +/* + * "$Id$" + * + * TIFF file routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1993-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * ImageReadTIFF() - Read a TIFF image file. + */ + +/* + * Include necessary headers... + */ + +#include "image.h" + +#ifdef HAVE_LIBTIFF +# include /* TIFF image definitions */ +# include + + +/* + * 'ImageReadTIFF()' - Read a TIFF image file. + */ + +int /* O - Read status */ +ImageReadTIFF(image_t *img, /* IO - Image */ + FILE *fp, /* I - Image file */ + int primary, /* I - Primary choice for colorspace */ + int secondary, /* I - Secondary choice for colorspace */ + int saturation, /* I - Color saturation (%) */ + int hue, /* I - Color hue (degrees) */ + ib_t *lut) /* I - Lookup table for gamma/brightness */ +{ + TIFF *tif; /* TIFF file */ + uint32 width, height; /* Size of image */ + uint16 photometric, /* Colorspace */ + orientation, /* Orientation */ + resunit, /* Units for resolution */ + samples, /* Number of samples/pixel */ + bits, /* Number of bits/pixel */ + inkset; /* Ink set for color separations */ + float xres, /* Horizontal resolution */ + yres; /* Vertical resolution */ + uint16 *redcmap, /* Red colormap information */ + *greencmap, /* Green colormap information */ + *bluecmap; /* Blue colormap information */ + int c, /* Color index */ + num_colors, /* Number of colors */ + bpp, /* Bytes per pixel */ + x, y, /* Current x & y */ + xstart, ystart, /* Starting x & y */ + xdir, ydir, /* X & y direction */ + xcount, ycount, /* X & Y counters */ + pstep, /* Pixel step (= bpp or -2 * bpp) */ + scanwidth, /* Width of scanline */ + r, g, b, k, /* Red, green, blue, and black values */ + alpha; /* Image includes alpha? */ + ib_t *in, /* Input buffer */ + *out, /* Output buffer */ + *p, /* Pointer into buffer */ + *scanline, /* Scanline buffer */ + *scanptr, /* Pointer into scanline buffer */ + bit, /* Current bit */ + pixel, /* Current pixel */ + zero, /* Zero value (bitmaps) */ + one; /* One value (bitmaps) */ + + + /* + * Open the TIFF file and get the required parameters... + */ + +#ifdef __hpux + lseek(fileno(fp), 0, SEEK_SET); /* Work around "feature" in HP-UX stdio */ +#endif /* __hpux */ + + if ((tif = TIFFFdOpen(fileno(fp), "", "r")) == NULL) + { + fclose(fp); + return (-1); + } + + if (!TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width) || + !TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height) || + !TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric) || + !TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &samples) || + !TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bits)) + { + TIFFClose(tif); + fclose(fp); + return (-1); + } + + /* + * Get the image orientation... + */ + + if (!TIFFGetField(tif, TIFFTAG_ORIENTATION, &orientation)) + orientation = 0; + + /* + * Get the image resolution... + */ + + if (TIFFGetField(tif, TIFFTAG_XRESOLUTION, &xres) && + TIFFGetField(tif, TIFFTAG_YRESOLUTION, &yres) && + TIFFGetField(tif, TIFFTAG_RESOLUTIONUNIT, &resunit)) + { + if (resunit == RESUNIT_INCH) + { + img->xppi = xres; + img->yppi = yres; + } + else if (resunit == RESUNIT_CENTIMETER) + { + img->xppi = xres * 2.54; + img->yppi = yres * 2.54; + } + else + { + img->xppi = xres * 0.0254; + img->yppi = yres * 0.0254; + } + } + + /* + * See if the image has an alpha channel... + */ + + if (samples == 2 || (samples == 4 && photometric == PHOTOMETRIC_RGB)) + alpha = 1; + else + alpha = 0; + + /* + * Setup the image size and colorspace... + */ + + img->xsize = width; + img->ysize = height; + if (photometric == PHOTOMETRIC_MINISBLACK || + photometric == PHOTOMETRIC_MINISWHITE) + img->colorspace = secondary; + else + img->colorspace = primary; + + bpp = ImageGetDepth(img); + + ImageSetMaxTiles(img, 0); + + /* + * Set the X & Y start and direction according to the image orientation... + */ + + switch (orientation) + { + case ORIENTATION_TOPRIGHT : + case ORIENTATION_RIGHTTOP : + xstart = img->xsize - 1; + xdir = -1; + ystart = 0; + ydir = 1; + break; + default : + case ORIENTATION_TOPLEFT : + case ORIENTATION_LEFTTOP : + xstart = 0; + xdir = 1; + ystart = 0; + ydir = 1; + break; + case ORIENTATION_BOTLEFT : + case ORIENTATION_LEFTBOT : + xstart = 0; + xdir = 1; + ystart = img->ysize - 1; + ydir = -1; + break; + case ORIENTATION_BOTRIGHT : + case ORIENTATION_RIGHTBOT : + xstart = img->xsize - 1; + xdir = -1; + ystart = img->ysize - 1; + ydir = -1; + break; + } + + /* + * Allocate a scanline buffer... + */ + + scanwidth = TIFFScanlineSize(tif); + scanline = _TIFFmalloc(scanwidth); + + /* + * Allocate input and output buffers... + */ + + if (orientation < ORIENTATION_LEFTTOP) + { + if (samples > 1 || photometric == PHOTOMETRIC_PALETTE) + pstep = xdir * 3; + else + pstep = xdir; + + in = malloc(img->xsize * 3 + 3); + out = malloc(img->xsize * bpp); + } + else + { + if (samples > 1 || photometric == PHOTOMETRIC_PALETTE) + pstep = ydir * 3; + else + pstep = ydir; + + in = malloc(img->ysize * 3 + 3); + out = malloc(img->ysize * bpp); + } + + /* + * Read the image. This is greatly complicated by the fact that TIFF + * supports literally hundreds of different colorspaces and orientations, + * each which must be handled separately... + */ + + switch (photometric) + { + case PHOTOMETRIC_MINISWHITE : + case PHOTOMETRIC_MINISBLACK : + if (photometric == PHOTOMETRIC_MINISBLACK) + { + zero = 0; + one = 255; + } + else + { + zero = 255; + one = 0; + } + + if (orientation < ORIENTATION_LEFTTOP) + { + /* + * Row major order... + */ + + for (y = ystart, ycount = img->ysize; + ycount > 0; + ycount --, y += ydir) + { + if (bits == 1) + { + TIFFReadScanline(tif, scanline, y, 0); + for (xcount = img->xsize, scanptr = scanline, p = in + xstart, bit = 128; + xcount > 0; + xcount --, p += pstep) + { + if (*scanptr & bit) + *p = one; + else + *p = zero; + + if (bit > 1) + bit >>= 1; + else + { + bit = 128; + scanptr ++; + } + } + } + else if (bits == 2) + { + TIFFReadScanline(tif, scanline, y, 0); + for (xcount = img->xsize, scanptr = scanline, p = in + xstart, bit = 0xc0; + xcount > 0; + xcount --, p += pstep) + { + pixel = *scanptr & bit; + while (pixel > 3) + pixel >>= 2; + *p = (255 * pixel / 3) ^ zero; + + if (bit > 3) + bit >>= 2; + else + { + bit = 0xc0; + scanptr ++; + } + } + } + else if (bits == 4) + { + TIFFReadScanline(tif, scanline, y, 0); + for (xcount = img->xsize, scanptr = scanline, p = in + xstart, bit = 0xf0; + xcount > 0; + xcount --, p += pstep) + { + if (bit == 0xf0) + { + *p = (255 * ((*scanptr & 0xf0) >> 4) / 15) ^ zero; + bit = 0x0f; + } + else + { + *p = (255 * (*scanptr & 0x0f) / 15) ^ zero; + bit = 0xf0; + scanptr ++; + } + } + } + else if (xdir < 0 || zero || alpha) + { + TIFFReadScanline(tif, scanline, y, 0); + + if (alpha) + { + if (zero) + { + for (xcount = img->xsize, p = in + xstart, scanptr = scanline; + xcount > 0; + xcount --, p += pstep, scanptr += 2) + *p = (scanptr[1] * (255 - scanptr[0]) + + (255 - scanptr[1]) * 255) / 255; + } + else + { + for (xcount = img->xsize, p = in + xstart, scanptr = scanline; + xcount > 0; + xcount --, p += pstep, scanptr += 2) + *p = (scanptr[1] * scanptr[0] + + (255 - scanptr[1]) * 255) / 255; + } + } + else + { + if (zero) + { + for (xcount = img->xsize, p = in + xstart, scanptr = scanline; + xcount > 0; + xcount --, p += pstep, scanptr ++) + *p = 255 - *scanptr; + } + else + { + for (xcount = img->xsize, p = in + xstart, scanptr = scanline; + xcount > 0; + xcount --, p += pstep, scanptr ++) + *p = *scanptr; + } + } + } + else + TIFFReadScanline(tif, in, y, 0); + + if (img->colorspace == IMAGE_WHITE) + { + if (lut) + ImageLut(in, img->xsize, lut); + + ImagePutRow(img, 0, y, img->xsize, in); + } + else + { + switch (img->colorspace) + { + case IMAGE_RGB : + ImageWhiteToRGB(in, out, img->xsize); + break; + case IMAGE_BLACK : + ImageWhiteToBlack(in, out, img->xsize); + break; + case IMAGE_CMY : + ImageWhiteToCMY(in, out, img->xsize); + break; + case IMAGE_CMYK : + ImageWhiteToCMYK(in, out, img->xsize); + break; + } + + if (lut) + ImageLut(out, img->xsize * bpp, lut); + + ImagePutRow(img, 0, y, img->xsize, out); + } + } + } + else + { + /* + * Column major order... + */ + + for (x = xstart, xcount = img->xsize; + xcount > 0; + xcount --, x += xdir) + { + if (bits == 1) + { + TIFFReadScanline(tif, scanline, x, 0); + for (ycount = img->ysize, scanptr = scanline, p = in + ystart, bit = 128; + ycount > 0; + ycount --, p += ydir) + { + if (*scanptr & bit) + *p = one; + else + *p = zero; + + if (bit > 1) + bit >>= 1; + else + { + bit = 128; + scanptr ++; + } + } + } + else if (bits == 2) + { + TIFFReadScanline(tif, scanline, x, 0); + for (ycount = img->ysize, scanptr = scanline, p = in + ystart, bit = 0xc0; + ycount > 0; + ycount --, p += ydir) + { + pixel = *scanptr & 0xc0; + while (pixel > 3) + pixel >>= 2; + + *p = (255 * pixel / 3) ^ zero; + + if (bit > 3) + bit >>= 2; + else + { + bit = 0xc0; + scanptr ++; + } + } + } + else if (bits == 4) + { + TIFFReadScanline(tif, scanline, x, 0); + for (ycount = img->ysize, scanptr = scanline, p = in + ystart, bit = 0xf0; + ycount > 0; + ycount --, p += ydir) + { + if (bit == 0xf0) + { + *p = (255 * ((*scanptr & 0xf0) >> 4) / 15) ^ zero; + bit = 0x0f; + } + else + { + *p = (255 * (*scanptr & 0x0f) / 15) ^ zero; + bit = 0xf0; + scanptr ++; + } + } + } + else if (ydir < 0 || zero || alpha) + { + TIFFReadScanline(tif, scanline, x, 0); + + if (alpha) + { + if (zero) + { + for (ycount = img->ysize, p = in + ystart, scanptr = scanline; + ycount > 0; + ycount --, p += ydir, scanptr += 2) + *p = (scanptr[1] * (255 - scanptr[0]) + + (255 - scanptr[1]) * 255) / 255; + } + else + { + for (ycount = img->ysize, p = in + ystart, scanptr = scanline; + ycount > 0; + ycount --, p += ydir, scanptr += 2) + *p = (scanptr[1] * scanptr[0] + + (255 - scanptr[1]) * 255) / 255; + } + } + else + { + if (zero) + { + for (ycount = img->ysize, p = in + ystart, scanptr = scanline; + ycount > 0; + ycount --, p += ydir, scanptr ++) + *p = 255 - *scanptr; + } + else + { + for (ycount = img->ysize, p = in + ystart, scanptr = scanline; + ycount > 0; + ycount --, p += ydir, scanptr ++) + *p = *scanptr; + } + } + } + else + TIFFReadScanline(tif, in, x, 0); + + if (img->colorspace == IMAGE_WHITE) + { + if (lut) + ImageLut(in, img->ysize, lut); + + ImagePutCol(img, x, 0, img->ysize, in); + } + else + { + switch (img->colorspace) + { + case IMAGE_RGB : + ImageWhiteToRGB(in, out, img->ysize); + break; + case IMAGE_BLACK : + ImageWhiteToBlack(in, out, img->ysize); + break; + case IMAGE_CMY : + ImageWhiteToCMY(in, out, img->ysize); + break; + case IMAGE_CMYK : + ImageWhiteToCMYK(in, out, img->ysize); + break; + } + + if (lut) + ImageLut(out, img->ysize * bpp, lut); + + ImagePutCol(img, x, 0, img->ysize, out); + } + } + } + break; + + case PHOTOMETRIC_PALETTE : + if (!TIFFGetField(tif, TIFFTAG_COLORMAP, &redcmap, &greencmap, &bluecmap)) + { + fclose(fp); + return (-1); + } + + num_colors = 1 << bits; + + for (c = 0; c < num_colors; c ++) + { + redcmap[c] >>= 8; + greencmap[c] >>= 8; + bluecmap[c] >>= 8; + } + + if (orientation < ORIENTATION_LEFTTOP) + { + /* + * Row major order... + */ + + for (y = ystart, ycount = img->ysize; + ycount > 0; + ycount --, y += ydir) + { + if (bits == 1) + { + TIFFReadScanline(tif, scanline, y, 0); + for (xcount = img->xsize, scanptr = scanline, + p = in + xstart * 3, bit = 128; + xcount > 0; + xcount --, p += pstep) + { + if (*scanptr & bit) + { + p[0] = redcmap[1]; + p[1] = greencmap[1]; + p[2] = bluecmap[1]; + } + else + { + p[0] = redcmap[0]; + p[1] = greencmap[0]; + p[2] = bluecmap[0]; + } + + if (bit > 1) + bit >>= 1; + else + { + bit = 128; + scanptr ++; + } + } + } + else if (bits == 2) + { + TIFFReadScanline(tif, scanline, y, 0); + for (xcount = img->xsize, scanptr = scanline, + p = in + xstart * 3, bit = 0xc0; + xcount > 0; + xcount --, p += pstep) + { + pixel = *scanptr & bit; + while (pixel > 3) + pixel >>= 2; + + p[0] = redcmap[pixel]; + p[1] = greencmap[pixel]; + p[2] = bluecmap[pixel]; + + if (bit > 3) + bit >>= 2; + else + { + bit = 0xc0; + scanptr ++; + } + } + } + else if (bits == 4) + { + TIFFReadScanline(tif, scanline, y, 0); + for (xcount = img->xsize, scanptr = scanline, + p = in + 3 * xstart, bit = 0xf0; + xcount > 0; + xcount --, p += pstep) + { + if (bit == 0xf0) + { + pixel = (*scanptr & 0xf0) >> 4; + p[0] = redcmap[pixel]; + p[1] = greencmap[pixel]; + p[2] = bluecmap[pixel]; + bit = 0x0f; + } + else + { + pixel = *scanptr++ & 0x0f; + p[0] = redcmap[pixel]; + p[1] = greencmap[pixel]; + p[2] = bluecmap[pixel]; + bit = 0xf0; + } + } + } + else + { + TIFFReadScanline(tif, scanline, y, 0); + + for (xcount = img->xsize, p = in + 3 * xstart, scanptr = scanline; + xcount > 0; + xcount --, p += pstep) + { + p[0] = redcmap[*scanptr]; + p[1] = greencmap[*scanptr]; + p[2] = bluecmap[*scanptr++]; + } + } + + if (img->colorspace == IMAGE_RGB) + { + if (lut) + ImageLut(in, img->xsize * 3, lut); + + ImagePutRow(img, 0, y, img->xsize, in); + } + else + { + switch (img->colorspace) + { + case IMAGE_WHITE : + ImageRGBToWhite(in, out, img->xsize); + break; + case IMAGE_BLACK : + ImageRGBToBlack(in, out, img->xsize); + break; + case IMAGE_CMY : + ImageRGBToCMY(in, out, img->xsize); + break; + case IMAGE_CMYK : + ImageRGBToCMYK(in, out, img->xsize); + break; + } + + if (lut) + ImageLut(out, img->xsize * bpp, lut); + + ImagePutRow(img, 0, y, img->xsize, out); + } + } + } + else + { + /* + * Column major order... + */ + + for (x = xstart, xcount = img->xsize; + xcount > 0; + xcount --, x += xdir) + { + if (bits == 1) + { + TIFFReadScanline(tif, scanline, x, 0); + for (ycount = img->ysize, scanptr = scanline, + p = in + 3 * ystart, bit = 128; + ycount > 0; + ycount --, p += ydir) + { + if (*scanptr & bit) + { + p[0] = redcmap[1]; + p[1] = greencmap[1]; + p[2] = bluecmap[1]; + } + else + { + p[0] = redcmap[0]; + p[1] = greencmap[0]; + p[2] = bluecmap[0]; + } + + if (bit > 1) + bit >>= 1; + else + { + bit = 128; + scanptr ++; + } + } + } + else if (bits == 2) + { + TIFFReadScanline(tif, scanline, x, 0); + for (ycount = img->ysize, scanptr = scanline, + p = in + 3 * ystart, bit = 0xc0; + ycount > 0; + ycount --, p += ydir) + { + pixel = *scanptr & 0xc0; + while (pixel > 3) + pixel >>= 2; + + p[0] = redcmap[pixel]; + p[1] = greencmap[pixel]; + p[2] = bluecmap[pixel]; + + if (bit > 3) + bit >>= 2; + else + { + bit = 0xc0; + scanptr ++; + } + } + } + else if (bits == 4) + { + TIFFReadScanline(tif, scanline, x, 0); + for (ycount = img->ysize, scanptr = scanline, + p = in + 3 * ystart, bit = 0xf0; + ycount > 0; + ycount --, p += ydir) + { + if (bit == 0xf0) + { + pixel = (*scanptr & 0xf0) >> 4; + p[0] = redcmap[pixel]; + p[1] = greencmap[pixel]; + p[2] = bluecmap[pixel]; + bit = 0x0f; + } + else + { + pixel = *scanptr++ & 0x0f; + p[0] = redcmap[pixel]; + p[1] = greencmap[pixel]; + p[2] = bluecmap[pixel]; + bit = 0xf0; + } + } + } + else + { + TIFFReadScanline(tif, scanline, x, 0); + + for (ycount = img->ysize, p = in + 3 * ystart, scanptr = scanline; + ycount > 0; + ycount --, p += ydir) + { + p[0] = redcmap[*scanptr]; + p[1] = greencmap[*scanptr]; + p[2] = bluecmap[*scanptr++]; + } + } + + if (img->colorspace == IMAGE_RGB) + { + if (lut) + ImageLut(in, img->ysize * 3, lut); + + ImagePutCol(img, x, 0, img->ysize, in); + } + else + { + switch (img->colorspace) + { + case IMAGE_WHITE : + ImageRGBToWhite(in, out, img->ysize); + break; + case IMAGE_BLACK : + ImageRGBToBlack(in, out, img->ysize); + break; + case IMAGE_CMY : + ImageRGBToCMY(in, out, img->ysize); + break; + case IMAGE_CMYK : + ImageRGBToCMYK(in, out, img->ysize); + break; + } + + if (lut) + ImageLut(out, img->ysize * bpp, lut); + + ImagePutCol(img, x, 0, img->ysize, out); + } + } + } + break; + + case PHOTOMETRIC_RGB : + if (orientation < ORIENTATION_LEFTTOP) + { + /* + * Row major order... + */ + + for (y = ystart, ycount = img->ysize; + ycount > 0; + ycount --, y += ydir) + { + if (bits == 1) + { + TIFFReadScanline(tif, scanline, y, 0); + for (xcount = img->xsize, scanptr = scanline, p = in + xstart * 3, bit = 0xf0; + xcount > 0; + xcount --, p += pstep) + { + if (*scanptr & bit & 0x88) + p[0] = 255; + else + p[0] = 0; + + if (*scanptr & bit & 0x44) + p[1] = 255; + else + p[1] = 0; + + if (*scanptr & bit & 0x22) + p[2] = 255; + else + p[2] = 0; + + if (bit == 0xf0) + bit = 0x0f; + else + { + bit = 0xf0; + scanptr ++; + } + } + } + else if (bits == 2) + { + TIFFReadScanline(tif, scanline, y, 0); + for (xcount = img->xsize, scanptr = scanline, p = in + xstart * 3; + xcount > 0; + xcount --, p += pstep, scanptr ++) + { + pixel = *scanptr >> 2; + p[0] = 255 * (pixel & 3) / 3; + pixel >>= 2; + p[1] = 255 * (pixel & 3) / 3; + pixel >>= 2; + p[2] = 255 * (pixel & 3) / 3; + } + } + else if (bits == 4) + { + TIFFReadScanline(tif, scanline, y, 0); + for (xcount = img->xsize, scanptr = scanline, p = in + xstart * 3; + xcount > 0; + xcount -= 2, p += 2 * pstep, scanptr += 3) + { + pixel = scanptr[0]; + p[1] = 255 * (pixel & 15) / 15; + pixel >>= 4; + p[0] = 255 * (pixel & 15) / 15; + pixel = scanptr[1]; + p[2] = 255 * ((pixel >> 4) & 15) / 15; + + if (xcount > 1) + { + p[pstep + 0] = 255 * (pixel & 15) / 15; + pixel = scanptr[2]; + p[pstep + 2] = 255 * (pixel & 15) / 15; + pixel >>= 4; + p[pstep + 1] = 255 * (pixel & 15) / 15; + } + } + } + else if (xdir < 0 || alpha) + { + TIFFReadScanline(tif, scanline, y, 0); + + if (alpha) + { + for (xcount = img->xsize, p = in + xstart * 3, scanptr = scanline; + xcount > 0; + xcount --, p += pstep, scanptr += 4) + { + p[0] = (scanptr[0] * scanptr[3] + 255 * (255 - scanptr[3])) / 255; + p[1] = (scanptr[1] * scanptr[3] + 255 * (255 - scanptr[3])) / 255; + p[2] = (scanptr[2] * scanptr[3] + 255 * (255 - scanptr[3])) / 255; + } + } + else + { + for (xcount = img->xsize, p = in + xstart * 3, scanptr = scanline; + xcount > 0; + xcount --, p += pstep, scanptr += 3) + { + p[0] = scanptr[0]; + p[1] = scanptr[1]; + p[2] = scanptr[2]; + } + } + } + else + TIFFReadScanline(tif, in, y, 0); + + if ((saturation != 100 || hue != 0) && bpp > 1) + ImageRGBAdjust(in, img->xsize, saturation, hue); + + if (img->colorspace == IMAGE_RGB) + { + if (lut) + ImageLut(in, img->xsize * 3, lut); + + ImagePutRow(img, 0, y, img->xsize, in); + } + else + { + switch (img->colorspace) + { + case IMAGE_WHITE : + ImageRGBToWhite(in, out, img->xsize); + break; + case IMAGE_BLACK : + ImageRGBToBlack(in, out, img->xsize); + break; + case IMAGE_CMY : + ImageRGBToCMY(in, out, img->xsize); + break; + case IMAGE_CMYK : + ImageRGBToCMYK(in, out, img->xsize); + break; + } + + if (lut) + ImageLut(out, img->xsize * bpp, lut); + + ImagePutRow(img, 0, y, img->xsize, out); + } + } + } + else + { + /* + * Column major order... + */ + + for (x = xstart, xcount = img->xsize; + xcount > 0; + xcount --, x += xdir) + { + if (bits == 1) + { + TIFFReadScanline(tif, scanline, x, 0); + for (ycount = img->ysize, scanptr = scanline, p = in + ystart * 3, bit = 0xf0; + ycount > 0; + ycount --, p += pstep) + { + if (*scanptr & bit & 0x88) + p[0] = one; + else + p[0] = zero; + + if (*scanptr & bit & 0x44) + p[1] = one; + else + p[1] = zero; + + if (*scanptr & bit & 0x22) + p[2] = one; + else + p[2] = zero; + + if (bit == 0xf0) + bit = 0x0f; + else + { + bit = 0xf0; + scanptr ++; + } + } + } + else if (bits == 2) + { + TIFFReadScanline(tif, scanline, x, 0); + for (ycount = img->ysize, scanptr = scanline, p = in + ystart * 3; + ycount > 0; + ycount --, p += pstep, scanptr ++) + { + pixel = *scanptr >> 2; + p[0] = 255 * (pixel & 3) / 3; + pixel >>= 2; + p[1] = 255 * (pixel & 3) / 3; + pixel >>= 2; + p[2] = 255 * (pixel & 3) / 3; + } + } + else if (bits == 4) + { + TIFFReadScanline(tif, scanline, x, 0); + for (ycount = img->ysize, scanptr = scanline, p = in + ystart * 3; + ycount > 0; + ycount -= 2, p += 2 * pstep, scanptr += 3) + { + pixel = scanptr[0]; + p[1] = 255 * (pixel & 15) / 15; + pixel >>= 4; + p[0] = 255 * (pixel & 15) / 15; + pixel = scanptr[1]; + p[2] = 255 * ((pixel >> 4) & 15) / 15; + + if (ycount > 1) + { + p[pstep + 0] = 255 * (pixel & 15) / 15; + pixel = scanptr[2]; + p[pstep + 2] = 255 * (pixel & 15) / 15; + pixel >>= 4; + p[pstep + 1] = 255 * (pixel & 15) / 15; + } + } + } + else if (ydir < 0 || alpha) + { + TIFFReadScanline(tif, scanline, x, 0); + + if (alpha) + { + for (ycount = img->ysize, p = in + ystart * 3, scanptr = scanline; + ycount > 0; + ycount --, p += pstep, scanptr += 4) + { + p[0] = (scanptr[0] * scanptr[3] + 255 * (255 - scanptr[3])) / 255; + p[1] = (scanptr[1] * scanptr[3] + 255 * (255 - scanptr[3])) / 255; + p[2] = (scanptr[2] * scanptr[3] + 255 * (255 - scanptr[3])) / 255; + } + } + else + { + for (ycount = img->ysize, p = in + ystart * 3, scanptr = scanline; + ycount > 0; + ycount --, p += pstep, scanptr += 3) + { + p[0] = scanptr[0]; + p[1] = scanptr[1]; + p[2] = scanptr[2]; + } + } + } + else + TIFFReadScanline(tif, in, x, 0); + + if ((saturation != 100 || hue != 0) && bpp > 1) + ImageRGBAdjust(in, img->ysize, saturation, hue); + + if (img->colorspace == IMAGE_RGB) + { + if (lut) + ImageLut(in, img->ysize * 3, lut); + + ImagePutCol(img, x, 0, img->ysize, in); + } + else + { + switch (img->colorspace) + { + case IMAGE_WHITE : + ImageRGBToWhite(in, out, img->ysize); + break; + case IMAGE_BLACK : + ImageRGBToBlack(in, out, img->ysize); + break; + case IMAGE_CMY : + ImageRGBToCMY(in, out, img->ysize); + break; + case IMAGE_CMYK : + ImageRGBToCMYK(in, out, img->ysize); + break; + } + + if (lut) + ImageLut(out, img->ysize * bpp, lut); + + ImagePutCol(img, x, 0, img->ysize, out); + } + } + } + break; + + case PHOTOMETRIC_SEPARATED : + TIFFGetField(tif, TIFFTAG_INKSET, &inkset); + + if (inkset == INKSET_CMYK) + { + if (orientation < ORIENTATION_LEFTTOP) + { + /* + * Row major order... + */ + + for (y = ystart, ycount = img->ysize; + ycount > 0; + ycount --, y += ydir) + { + if (bits == 1) + { + TIFFReadScanline(tif, scanline, y, 0); + for (xcount = img->xsize, scanptr = scanline, p = in + xstart * 3, bit = 0xf0; + xcount > 0; + xcount --, p += pstep) + { + if (*scanptr & bit & 0x11) + { + p[0] = 0; + p[1] = 0; + p[2] = 0; + } + else + { + if (*scanptr & bit & 0x88) + p[0] = 0; + else + p[0] = 255; + + if (*scanptr & bit & 0x44) + p[1] = 0; + else + p[1] = 255; + + if (*scanptr & bit & 0x22) + p[2] = 0; + else + p[2] = 255; + } + + if (bit == 0xf0) + bit = 0x0f; + else + { + bit = 0xf0; + scanptr ++; + } + } + } + else if (bits == 2) + { + TIFFReadScanline(tif, scanline, y, 0); + for (xcount = img->xsize, scanptr = scanline, p = in + xstart * 3; + xcount > 0; + xcount --, p += pstep, scanptr ++) + { + pixel = *scanptr; + k = 255 * (pixel & 3) / 3; + if (k == 255) + { + p[0] = 0; + p[1] = 0; + p[2] = 0; + } + else + { + pixel >>= 2; + b = 255 - 255 * (pixel & 3) / 3 - k; + if (b < 0) + p[2] = 0; + else if (b < 256) + p[2] = b; + else + p[2] = 255; + + pixel >>= 2; + g = 255 - 255 * (pixel & 3) / 3 - k; + if (g < 0) + p[1] = 0; + else if (g < 256) + p[1] = g; + else + p[1] = 255; + + pixel >>= 2; + r = 255 - 255 * (pixel & 3) / 3 - k; + if (r < 0) + p[0] = 0; + else if (r < 256) + p[0] = r; + else + p[0] = 255; + } + } + } + else if (bits == 4) + { + TIFFReadScanline(tif, scanline, y, 0); + for (xcount = img->xsize, scanptr = scanline, p = in + xstart * 3; + xcount > 0; + xcount --, p += pstep, scanptr += 2) + { + pixel = scanptr[1]; + k = 255 * (pixel & 15) / 15; + if (k == 255) + { + p[0] = 0; + p[1] = 0; + p[2] = 0; + } + else + { + pixel >>= 4; + b = 255 - 255 * (pixel & 15) / 15 - k; + if (b < 0) + p[2] = 0; + else if (b < 256) + p[2] = b; + else + p[2] = 255; + + pixel = scanptr[0]; + g = 255 - 255 * (pixel & 15) / 15 - k; + if (g < 0) + p[1] = 0; + else if (g < 256) + p[1] = g; + else + p[1] = 255; + + pixel >>= 4; + r = 255 - 255 * (pixel & 15) / 15 - k; + if (r < 0) + p[0] = 0; + else if (r < 256) + p[0] = r; + else + p[0] = 255; + } + } + } + else + { + TIFFReadScanline(tif, scanline, y, 0); + + for (xcount = img->xsize, p = in + xstart * 3, scanptr = scanline; + xcount > 0; + xcount --, p += pstep, scanptr += 4) + { + k = scanptr[3]; + if (k == 255) + { + p[0] = 0; + p[1] = 0; + p[2] = 0; + } + else + { + r = 255 - scanptr[0] - k; + if (r < 0) + p[0] = 0; + else if (r < 256) + p[0] = r; + else + p[0] = 255; + + g = 255 - scanptr[1] - k; + if (g < 0) + p[1] = 0; + else if (g < 256) + p[1] = g; + else + p[1] = 255; + + b = 255 - scanptr[2] - k; + if (b < 0) + p[2] = 0; + else if (b < 256) + p[2] = b; + else + p[2] = 255; + } + } + } + + if ((saturation != 100 || hue != 0) && bpp > 1) + ImageRGBAdjust(in, img->xsize, saturation, hue); + + if (img->colorspace == IMAGE_RGB) + { + if (lut) + ImageLut(in, img->xsize * 3, lut); + + ImagePutRow(img, 0, y, img->xsize, in); + } + else + { + switch (img->colorspace) + { + case IMAGE_WHITE : + ImageRGBToWhite(in, out, img->xsize); + break; + case IMAGE_BLACK : + ImageRGBToBlack(in, out, img->xsize); + break; + case IMAGE_CMY : + ImageRGBToCMY(in, out, img->xsize); + break; + case IMAGE_CMYK : + ImageRGBToCMYK(in, out, img->xsize); + break; + } + + if (lut) + ImageLut(out, img->xsize * 3, lut); + + ImagePutRow(img, 0, y, img->xsize, out); + } + } + } + else + { + /* + * Column major order... + */ + + for (x = xstart, xcount = img->xsize; + xcount > 0; + xcount --, x += xdir) + { + if (bits == 1) + { + TIFFReadScanline(tif, scanline, x, 0); + for (ycount = img->ysize, scanptr = scanline, p = in + xstart * 3, bit = 0xf0; + ycount > 0; + ycount --, p += pstep) + { + if (*scanptr & bit & 0x11) + { + p[0] = 0; + p[1] = 0; + p[2] = 0; + } + else + { + if (*scanptr & bit & 0x88) + p[0] = 0; + else + p[0] = 255; + + if (*scanptr & bit & 0x44) + p[1] = 0; + else + p[1] = 255; + + if (*scanptr & bit & 0x22) + p[2] = 0; + else + p[2] = 255; + } + + if (bit == 0xf0) + bit = 0x0f; + else + { + bit = 0xf0; + scanptr ++; + } + } + } + else if (bits == 2) + { + TIFFReadScanline(tif, scanline, x, 0); + for (ycount = img->ysize, scanptr = scanline, p = in + xstart * 3; + ycount > 0; + ycount --, p += pstep, scanptr ++) + { + pixel = *scanptr; + k = 255 * (pixel & 3) / 3; + if (k == 255) + { + p[0] = 0; + p[1] = 0; + p[2] = 0; + } + else + { + pixel >>= 2; + b = 255 - 255 * (pixel & 3) / 3 - k; + if (b < 0) + p[2] = 0; + else if (b < 256) + p[2] = b; + else + p[2] = 255; + + pixel >>= 2; + g = 255 - 255 * (pixel & 3) / 3 - k; + if (g < 0) + p[1] = 0; + else if (g < 256) + p[1] = g; + else + p[1] = 255; + + pixel >>= 2; + r = 255 - 255 * (pixel & 3) / 3 - k; + if (r < 0) + p[0] = 0; + else if (r < 256) + p[0] = r; + else + p[0] = 255; + } + } + } + else if (bits == 4) + { + TIFFReadScanline(tif, scanline, x, 0); + for (ycount = img->ysize, scanptr = scanline, p = in + xstart * 3; + ycount > 0; + ycount --, p += pstep, scanptr += 2) + { + pixel = scanptr[1]; + k = 255 * (pixel & 15) / 15; + if (k == 255) + { + p[0] = 0; + p[1] = 0; + p[2] = 0; + } + else + { + pixel >>= 4; + b = 255 - 255 * (pixel & 15) / 15 - k; + if (b < 0) + p[2] = 0; + else if (b < 256) + p[2] = b; + else + p[2] = 255; + + pixel = scanptr[0]; + g = 255 - 255 * (pixel & 15) / 15 - k; + if (g < 0) + p[1] = 0; + else if (g < 256) + p[1] = g; + else + p[1] = 255; + + pixel >>= 4; + r = 255 - 255 * (pixel & 15) / 15 - k; + if (r < 0) + p[0] = 0; + else if (r < 256) + p[0] = r; + else + p[0] = 255; + } + } + } + else + { + TIFFReadScanline(tif, scanline, x, 0); + + for (ycount = img->ysize, p = in + xstart * 3, scanptr = scanline; + ycount > 0; + ycount --, p += pstep, scanptr += 4) + { + k = scanptr[3]; + if (k == 255) + { + p[0] = 0; + p[1] = 0; + p[2] = 0; + } + else + { + r = 255 - scanptr[0] - k; + if (r < 0) + p[0] = 0; + else if (r < 256) + p[0] = r; + else + p[0] = 255; + + g = 255 - scanptr[1] - k; + if (g < 0) + p[1] = 0; + else if (g < 256) + p[1] = g; + else + p[1] = 255; + + b = 255 - scanptr[2] - k; + if (b < 0) + p[2] = 0; + else if (b < 256) + p[2] = b; + else + p[2] = 255; + } + } + } + + if ((saturation != 100 || hue != 0) && bpp > 1) + ImageRGBAdjust(in, img->ysize, saturation, hue); + + if (img->colorspace == IMAGE_RGB) + { + if (lut) + ImageLut(in, img->ysize * 3, lut); + + ImagePutCol(img, x, 0, img->ysize, in); + } + else + { + switch (img->colorspace) + { + case IMAGE_WHITE : + ImageRGBToWhite(in, out, img->ysize); + break; + case IMAGE_BLACK : + ImageRGBToBlack(in, out, img->ysize); + break; + case IMAGE_CMY : + ImageRGBToCMY(in, out, img->ysize); + break; + case IMAGE_CMYK : + ImageRGBToCMYK(in, out, img->ysize); + break; + } + + if (lut) + ImageLut(out, img->ysize * bpp, lut); + + ImagePutCol(img, x, 0, img->ysize, out); + } + } + } + + break; + } + + default : + _TIFFfree(scanline); + free(in); + free(out); + + TIFFClose(tif); + return (-1); + } + + /* + * Free temporary buffers, close the TIFF file, and return. + */ + + _TIFFfree(scanline); + free(in); + free(out); + + TIFFClose(tif); + return (0); +} + + +#endif /* HAVE_LIBTIFF */ + + +/* + * End of "$Id$". + */ diff --git a/filter/image-zoom.c b/filter/image-zoom.c new file mode 100644 index 0000000000..455dd52263 --- /dev/null +++ b/filter/image-zoom.c @@ -0,0 +1,310 @@ +/* + * "$Id$" + * + * Image zoom routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1993-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * ImageZoomAlloc() - Allocate a pixel zoom record... + * ImageZoomFill() - Fill a zoom record with image data utilizing bilinear + * interpolation. + * ImageZoomQFill() - Fill a zoom record quickly using nearest-neighbor + * sampling. + * ImageZoomFree() - Free a zoom record... + */ + +/* + * Include necessary headers... + */ + +#include "image.h" + + +/* + * 'ZoomAlloc()' - Allocate a pixel zoom record... + */ + +izoom_t * +ImageZoomAlloc(image_t *img, /* I - Image to zoom */ + int x0, /* I - Upper-lefthand corner */ + int y0, /* I - ... */ + int x1, /* I - Lower-righthand corner */ + int y1, /* I - ... */ + int xsize, /* I - Final width of image */ + int ysize, /* I - Final height of image */ + int rotated) /* I - Non-zero if image is rotated 90 degs */ +{ + izoom_t *z; /* New zoom record */ + + + if ((z = (izoom_t *)calloc(1, sizeof(izoom_t))) == NULL) + return (NULL); + + z->img = img; + z->row = 0; + z->depth = ImageGetDepth(img); + z->rotated = rotated; + + if (rotated) + { + z->xorig = x1; + z->yorig = y0; + z->width = y1 - y0 + 1; + z->height = x1 - x0 + 1; + z->xsize = xsize; + z->ysize = ysize; + z->xmod = z->width % z->xsize; + z->xstep = z->width / z->xsize; + z->xincr = 1; + z->ymod = z->height % z->ysize; + z->ystep = z->height / z->ysize; + z->yincr = 1; + z->instep = z->xstep * z->depth; + z->inincr = z->xincr * z->depth; + + if (z->width < img->ysize) + z->xmax = z->width; + else + z->xmax = z->width - 1; + + if (z->height < img->xsize) + z->ymax = z->height; + else + z->ymax = z->height - 1; + } + else + { + z->xorig = x0; + z->yorig = y0; + z->width = x1 - x0 + 1; + z->height = y1 - y0 + 1; + z->xsize = xsize; + z->ysize = ysize; + z->xmod = z->width % z->xsize; + z->xstep = z->width / z->xsize; + z->xincr = 1; + z->ymod = z->height % z->ysize; + z->ystep = z->height / z->ysize; + z->yincr = 1; + z->instep = z->xstep * z->depth; + z->inincr = z->xincr * z->depth; + + if (z->width < img->xsize) + z->xmax = z->width; + else + z->xmax = z->width - 1; + + if (z->height < img->ysize) + z->ymax = z->height; + else + z->ymax = z->height - 1; + } + + if ((z->rows[0] = (ib_t *)malloc(z->xsize * z->depth)) == NULL) + { + free(z); + return (NULL); + } + + if ((z->rows[1] = (ib_t *)malloc(z->xsize * z->depth)) == NULL) + { + free(z->rows[0]); + free(z); + return (NULL); + } + + if ((z->in = (ib_t *)malloc(z->width * z->depth)) == NULL) + { + free(z->rows[0]); + free(z->rows[1]); + free(z); + return (NULL); + } + + return (z); +} + + +/* + * 'ImageZoomFill()' - Fill a zoom record with image data utilizing bilinear + * interpolation. + */ + +void +ImageZoomFill(izoom_t *z, /* I - Zoom record to fill */ + int iy) /* I - Zoom image row */ +{ + ib_t *r, /* Row pointer */ + *inptr; /* Pixel pointer */ + int xerr0, /* X error counter */ + xerr1; /* ... */ + int ix, + x, + count, + z_depth, + z_xstep, + z_xincr, + z_instep, + z_inincr, + z_xmax, + z_xmod, + z_xsize; + + + if (iy > z->ymax) + iy = z->ymax; + + z->row ^= 1; + + z_depth = z->depth; + z_xsize = z->xsize; + z_xmax = z->xmax; + z_xmod = z->xmod; + z_xstep = z->xstep; + z_xincr = z->xincr; + z_instep = z->instep; + z_inincr = z->inincr; + + if (z->rotated) + ImageGetCol(z->img, z->xorig - iy, z->yorig, z->width, z->in); + else + ImageGetRow(z->img, z->xorig, z->yorig + iy, z->width, z->in); + + if (z_inincr < 0) + inptr = z->in + (z->width - 1) * z_depth; + else + inptr = z->in; + + for (x = z_xsize, xerr0 = z_xsize, xerr1 = 0, ix = 0, r = z->rows[z->row]; + x > 0; + x --) + { + if (ix < z_xmax) + { + for (count = 0; count < z_depth; count ++) + *r++ = (inptr[count] * xerr0 + inptr[z_depth + count] * xerr1) / z_xsize; + } + else + { + for (count = 0; count < z_depth; count ++) + *r++ = inptr[count]; + } + + ix += z_xstep; + inptr += z_instep; + xerr0 -= z_xmod; + xerr1 += z_xmod; + + if (xerr0 <= 0) + { + xerr0 += z_xsize; + xerr1 -= z_xsize; + ix += z_xincr; + inptr += z_inincr; + } + } +} + + +/* + * 'ImageZoomQFill()' - Fill a zoom record quickly using nearest-neighbor sampling. + */ + +void +ImageZoomQFill(izoom_t *z, /* I - Zoom record to fill */ + int iy) /* I - Zoom image row */ +{ + ib_t *r, /* Row pointer */ + *inptr; /* Pixel pointer */ + int xerr0; /* X error counter */ + int ix, + x, + count, + z_depth, + z_xstep, + z_xincr, + z_instep, + z_inincr, + z_xmod, + z_xsize; + + + if (iy > z->ymax) + iy = z->ymax; + + z->row ^= 1; + + z_depth = z->depth; + z_xsize = z->xsize; + z_xmod = z->xmod; + z_xstep = z->xstep; + z_xincr = z->xincr; + z_instep = z->instep; + z_inincr = z->inincr; + + if (z->rotated) + ImageGetCol(z->img, z->xorig - iy, z->yorig, z->width, z->in); + else + ImageGetRow(z->img, z->xorig, z->yorig + iy, z->width, z->in); + + if (z_inincr < 0) + inptr = z->in + (z->width - 1) * z_depth; + else + inptr = z->in; + + for (x = z_xsize, xerr0 = z_xsize, ix = 0, r = z->rows[z->row]; + x > 0; + x --) + { + for (count = 0; count < z_depth; count ++) + *r++ = inptr[count]; + + ix += z_xstep; + inptr += z_instep; + xerr0 -= z_xmod; + + if (xerr0 <= 0) + { + xerr0 += z_xsize; + ix += z_xincr; + inptr += z_inincr; + } + } +} + + +/* + * 'ImageZoomFree()' - Free a zoom record... + */ + +void +ImageZoomFree(izoom_t *z) /* I - Zoom record to free */ +{ + free(z->rows[0]); + free(z->rows[1]); + free(z->in); + free(z); +} + + +/* + * End of "$Id$". + */ diff --git a/filter/image.c b/filter/image.c new file mode 100644 index 0000000000..c850cad46e --- /dev/null +++ b/filter/image.c @@ -0,0 +1,745 @@ +/* + * "$Id$" + * + * Base image support for the Common UNIX Printing System (CUPS). + * + * Copyright 1993-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * ImageOpen() - Open an image file and read it into memory. + * ImageClose() - Close an image file. + * ImageSetMaxTiles() - Set the maximum number of tiles to cache. + * ImageSetProfile() - Set the device color profile. + * ImageGetCol() - Get a column of pixels from an image. + * ImageGetRow() - Get a row of pixels from an image. + * ImagePutCol() - Put a column of pixels to an image. + * ImagePutRow() - Put a row of pixels to an image. + * get_tile() - Get a cached tile. + * flush_tile() - Flush the least-recently-used tile in the cache. + */ + +/* + * Include necessary headers... + */ + +#include "image.h" +#include +#include +#include + + +/* + * Globals... + */ + +int ImageHaveProfile = 0; /* Do we have a color profile? */ +int ImageDensity[256]; /* Ink/marker density LUT */ +int ImageMatrix[3][3][256]; /* Color transform matrix LUT */ + + +/* + * Local functions... + */ + +static ib_t *get_tile(image_t *img, int x, int y); +static void flush_tile(image_t *img); + + +/* + * 'ImageOpen()' - Open an image file and read it into memory. + */ + +image_t * /* O - New image */ +ImageOpen(char *filename, /* I - Filename of image */ + int primary, /* I - Primary colorspace needed */ + int secondary, /* I - Secondary colorspace if primary no good */ + int saturation, /* I - Color saturation level */ + int hue, /* I - Color hue adjustment */ + ib_t *lut) /* I - RGB gamma/brightness LUT */ +{ + FILE *fp; /* File pointer */ + unsigned char header[16], /* First 16 bytes of file */ + header2[16]; /* Bytes 2048-2064 (PhotoCD) */ + image_t *img; /* New image buffer */ + int status; /* Status of load... */ + + + /* + * Range check... + */ + + if (filename == NULL) + return (NULL); + + /* + * Figure out the file type... + */ + + if ((fp = fopen(filename, "r")) == NULL) + return (NULL); + + if (fread(header, 1, sizeof(header), fp) == 0) + { + fclose(fp); + return (NULL); + } + + fseek(fp, 2048, SEEK_SET); + memset(header2, 0, sizeof(header2)); + fread(header2, 1, sizeof(header2), fp); + fseek(fp, 0, SEEK_SET); + + /* + * Allocate memory... + */ + + img = calloc(sizeof(image_t), 1); + + if (img == NULL) + { + fclose(fp); + return (NULL); + } + + /* + * Load the image as appropriate... + */ + + img->max_ics = TILE_MINIMUM; + img->xppi = 128; + img->yppi = 128; + + if (memcmp(header, "GIF87a", 6) == 0 || + memcmp(header, "GIF89a", 6) == 0) + status = ImageReadGIF(img, fp, primary, secondary, saturation, hue, lut); + else if (header[0] == 0x01 && header[1] == 0xda) + status = ImageReadSGI(img, fp, primary, secondary, saturation, hue, lut); + else if (header[0] == 0x59 && header[1] == 0xa6 && + header[2] == 0x6a && header[3] == 0x95) + status = ImageReadSunRaster(img, fp, primary, secondary, saturation, hue, lut); + else if (header[0] == 'P' && header[1] >= '1' && header[1] <= '6') + status = ImageReadPNM(img, fp, primary, secondary, saturation, hue, lut); + else if (memcmp(header2, "PCD_IPI", 7) == 0) + status = ImageReadPhotoCD(img, fp, primary, secondary, saturation, hue, lut); +#if defined(HAVE_LIBPNG) && defined(HAVE_LIBZ) + else if (memcmp(header, "\211PNG", 4) == 0) + status = ImageReadPNG(img, fp, primary, secondary, saturation, hue, lut); +#endif /* HAVE_LIBPNG && HAVE_LIBZ */ +#ifdef HAVE_LIBJPEG + else if (memcmp(header + 6, "JFIF", 4) == 0) + status = ImageReadJPEG(img, fp, primary, secondary, saturation, hue, lut); +#endif /* HAVE_LIBJPEG */ +#ifdef HAVE_LIBTIFF + else if (memcmp(header, "MM", 2) == 0 || + memcmp(header, "II", 2) == 0) + status = ImageReadTIFF(img, fp, primary, secondary, saturation, hue, lut); +#endif /* HAVE_LIBTIFF */ + else + { + fclose(fp); + status = -1; + } + + if (status) + { + free(img); + return (NULL); + } + else + return (img); +} + + +/* + * 'ImageClose()' - Close an image file. + */ + +void +ImageClose(image_t *img) /* I - Image to close */ +{ + ic_t *current, /* Current cached tile */ + *next; /* Next cached tile */ + + + /* + * Free the image cache... + */ + + for (current = img->first; current != NULL; current = next) + { + next = current->next; + free(current); + } + + /* + * Wipe the tile cache file (if any)... + */ + + if (img->cachefile != NULL) + { + fclose(img->cachefile); + unlink(img->cachename); + } + + /* + * Free the rest of memory... + */ + + if (img->tiles != NULL) + { + free(img->tiles[0]); + free(img->tiles); + } + + free(img); +} + + +/* + * 'ImageSetMaxTiles()' - Set the maximum number of tiles to cache. + * + * If the "max_tiles" argument is 0 then the maximum number of tiles is + * computed from the image size. + */ + +void +ImageSetMaxTiles(image_t *img, /* I - Image to set */ + int max_tiles) /* I - Number of tiles to cache */ +{ + int cache_size, /* Size of tile cache in bytes */ + min_tiles, /* Minimum number of tiles to cache */ + max_size; /* Maximum cache size in bytes */ + char *cache_env, /* Cache size environment variable */ + cache_units[255]; /* Cache size units */ + + + min_tiles = max(TILE_MINIMUM, + 1 + max((img->xsize + TILE_SIZE - 1) / TILE_SIZE, + (img->ysize + TILE_SIZE - 1) / TILE_SIZE)); + + if (max_tiles == 0) + max_tiles = ((img->xsize + TILE_SIZE - 1) / TILE_SIZE) * + ((img->ysize + TILE_SIZE - 1) / TILE_SIZE); + + cache_size = max_tiles * TILE_SIZE * TILE_SIZE * ImageGetDepth(img); + + if ((cache_env = getenv("RIP_MAX_CACHE")) != NULL) + { + switch (sscanf(cache_env, "%d%s", &max_size, cache_units)) + { + case 0 : + max_size = 32 * 1024 * 1024; + break; + case 1 : + max_size *= 4 * TILE_SIZE * TILE_SIZE; + break; + case 2 : + if (tolower(cache_units[0]) == 'g') + max_size *= 1024 * 1024 * 1024; + else if (tolower(cache_units[0]) == 'm') + max_size *= 1024 * 1024; + else if (tolower(cache_units[0]) == 'k') + max_size *= 1024; + else if (tolower(cache_units[0]) == 't') + max_size *= 4 * TILE_SIZE * TILE_SIZE; + break; + } + } + else + max_size = 32 * 1024 * 1024; + + if (cache_size > max_size) + max_tiles = max_size / TILE_SIZE / TILE_SIZE / ImageGetDepth(img); + + if (max_tiles < min_tiles) + max_tiles = min_tiles; + + img->max_ics = max_tiles; + +#ifdef DEBUG + fprintf(stderr, "ImageSetMaxTiles: max_ics=%d...\n", img->max_ics); +#endif /* DEBUG */ +} + + +/* + * 'ImageSetProfile()' - Set the device color profile. + */ + +void +ImageSetProfile(float density, /* I - Ink/marker density */ + float matrix[3][3]) /* I - Color transform matrix */ +{ + int i, j, k; /* Looping vars */ + float g; /* Gamma correction */ + + + ImageHaveProfile = 1; + + for (i = 0; i < 3; i ++) + for (j = 0; j < 3; j ++) + for (k = 0; k < 256; k ++) + ImageMatrix[i][j][k] = (int)(k * matrix[i][j] + 0.5); + + g = 1.0 / density; + + for (k = 0; k < 256; k ++) + ImageDensity[k] = 255.0 * density * pow((float)k / 255.0, g) + 0.5; +} + + +/* + * 'ImageGetCol()' - Get a column of pixels from an image. + */ + +int +ImageGetCol(image_t *img, + int x, + int y, + int height, + ib_t *pixels) +{ + int bpp, + twidth, + count; + ib_t *ib; + + + if (img == NULL || x < 0 || x >= img->xsize || y >= img->ysize) + return (-1); + + if (y < 0) + { + height += y; + y = 0; + } + + if ((y + height) > img->ysize) + height = img->ysize - y; + + if (height < 1) + return (-1); + + bpp = ImageGetDepth(img); + twidth = bpp * (TILE_SIZE - 1); + + while (height > 0) + { + ib = get_tile(img, x, y); + + if (ib == NULL) + return (-1); + + count = TILE_SIZE - (y & (TILE_SIZE - 1)); + if (count > height) + count = height; + + y += count; + height -= count; + + for (; count > 0; count --, ib += twidth) + switch (bpp) + { + case 4 : + *pixels++ = *ib++; + case 3 : + *pixels++ = *ib++; + *pixels++ = *ib++; + case 1 : + *pixels++ = *ib++; + break; + } + } + + return (0); +} + + +/* + * 'ImageGetRow()' - Get a row of pixels from an image. + */ + +int +ImageGetRow(image_t *img, + int x, + int y, + int width, + ib_t *pixels) +{ + int bpp, + count; + ib_t *ib; + + + if (img == NULL || y < 0 || y >= img->ysize || x >= img->xsize) + return (-1); + + if (x < 0) + { + width += x; + x = 0; + } + + if ((x + width) > img->xsize) + width = img->xsize - x; + + if (width < 1) + return (-1); + + bpp = img->colorspace < 0 ? -img->colorspace : img->colorspace; + + while (width > 0) + { + ib = get_tile(img, x, y); + + if (ib == NULL) + return (-1); + + count = TILE_SIZE - (x & (TILE_SIZE - 1)); + if (count > width) + count = width; + memcpy(pixels, ib, count * bpp); + pixels += count * bpp; + x += count; + width -= count; + } + + return (0); +} + + +/* + * 'ImagePutCol()' - Put a column of pixels to an image. + */ + +int +ImagePutCol(image_t *img, + int x, + int y, + int height, + ib_t *pixels) +{ + int bpp, + twidth, + count; + int tilex, + tiley; + ib_t *ib; + + + if (img == NULL || x < 0 || x >= img->xsize || y >= img->ysize) + return (-1); + + if (y < 0) + { + height += y; + y = 0; + } + + if ((y + height) > img->ysize) + height = img->ysize - y; + + if (height < 1) + return (-1); + + bpp = ImageGetDepth(img); + twidth = bpp * (TILE_SIZE - 1); + tilex = x / TILE_SIZE; + tiley = y / TILE_SIZE; + + while (height > 0) + { + ib = get_tile(img, x, y); + + if (ib == NULL) + return (-1); + + img->tiles[tiley][tilex].dirty = 1; + tiley ++; + + count = TILE_SIZE - (y & (TILE_SIZE - 1)); + if (count > height) + count = height; + + y += count; + height -= count; + + for (; count > 0; count --, ib += twidth) + switch (bpp) + { + case 4 : + *ib++ = *pixels++; + case 3 : + *ib++ = *pixels++; + *ib++ = *pixels++; + case 1 : + *ib++ = *pixels++; + break; + } + } + + return (0); +} + + +/* + * 'ImagePutRow()' - Put a row of pixels to an image. + */ + +int +ImagePutRow(image_t *img, + int x, + int y, + int width, + ib_t *pixels) +{ + int bpp, + count; + int tilex, + tiley; + ib_t *ib; + + + if (img == NULL || y < 0 || y >= img->ysize || x >= img->xsize) + return (-1); + + if (x < 0) + { + width += x; + x = 0; + } + + if ((x + width) > img->xsize) + width = img->xsize - x; + + if (width < 1) + return (-1); + + bpp = img->colorspace < 0 ? -img->colorspace : img->colorspace; + tilex = x / TILE_SIZE; + tiley = y / TILE_SIZE; + + while (width > 0) + { + ib = get_tile(img, x, y); + + if (ib == NULL) + return (-1); + + img->tiles[tiley][tilex].dirty = 1; + + count = TILE_SIZE - (x & (TILE_SIZE - 1)); + if (count > width) + count = width; + memcpy(ib, pixels, count * bpp); + pixels += count * bpp; + x += count; + width -= count; + tilex ++; + } + + return (0); +} + + +/* + * 'get_tile()' - Get a cached tile. + */ + +static ib_t * +get_tile(image_t *img, + int x, + int y) +{ + int bpp, + tilex, + tiley, + xtiles, + ytiles; + ic_t *ic; + itile_t *tile; + + + if (img->tiles == NULL) + { + xtiles = (img->xsize + TILE_SIZE - 1) / TILE_SIZE; + ytiles = (img->ysize + TILE_SIZE - 1) / TILE_SIZE; + +#ifdef DEBUG + fprintf(stderr, "get_tile: Creating tile array (%dx%d)\n", xtiles, ytiles); +#endif /* DEBUG */ + + img->tiles = calloc(sizeof(itile_t *), ytiles); + tile = calloc(sizeof(itile_t), xtiles * ytiles); + + for (tiley = 0; tiley < ytiles; tiley ++) + { + img->tiles[tiley] = tile; + for (tilex = xtiles; tilex > 0; tilex --, tile ++) + tile->pos = -1; + } + } + + bpp = ImageGetDepth(img); + tilex = x / TILE_SIZE; + tiley = y / TILE_SIZE; + x &= (TILE_SIZE - 1); + y &= (TILE_SIZE - 1); + + tile = img->tiles[tiley] + tilex; + + if ((ic = tile->ic) == NULL) + { + if (img->num_ics < img->max_ics) + { +#ifdef DEBUG + fputs("get_tile: Allocating new cache tile...\n", stderr); +#endif /* DEBUG */ + + ic = calloc(sizeof(ic_t) + bpp * TILE_SIZE * TILE_SIZE, 1); + ic->pixels = ((ib_t *)ic) + sizeof(ic_t); + + img->num_ics ++; + } + else + { +#ifdef DEBUG + fputs("get_tile: Flushing old cache tile...\n", stderr); +#endif /* DEBUG */ + + flush_tile(img); + ic = img->first; + } + + ic->tile = tile; + tile->ic = ic; + + if (tile->pos >= 0) + { +#ifdef DEBUG + fprintf(stderr, "get_tile: loading cache tile from file position %d...\n", + tile->pos); +#endif /* DEBUG */ + + if (ftell(img->cachefile) != tile->pos) + if (fseek(img->cachefile, tile->pos, SEEK_SET)) + perror("get_tile:"); + + fread(ic->pixels, bpp, TILE_SIZE * TILE_SIZE, img->cachefile); + } + else + { +#ifdef DEBUG + fputs("get_tile: Clearing cache tile...\n", stderr); +#endif /* DEBUG */ + + memset(ic->pixels, 0, bpp * TILE_SIZE * TILE_SIZE); + } + } + + if (ic == img->first) + img->first = ic->next; + else if (img->first == NULL) + img->first = ic; + + if (ic != img->last) + { + if (img->last != NULL) + img->last->next = ic; + + ic->prev = img->last; + img->last = ic; + } + + ic->next = NULL; + + return (ic->pixels + bpp * (y * TILE_SIZE + x)); +} + + +/* + * 'flush_tile()' - Flush the least-recently-used tile in the cache. + */ + +static void +flush_tile(image_t *img) +{ + int bpp; + itile_t *tile; + + + +#ifdef DEBUG + fprintf(stderr, "flush_tile(%08x)...\n", img); +#endif /* DEBUG */ + + bpp = ImageGetDepth(img); + tile = img->first->tile; + + if (!tile->dirty) + { + tile->ic = NULL; + return; + } + + if (img->cachefile == NULL) + { + tmpnam(img->cachename); + +#ifdef DEBUG + fprintf(stderr, "flush_tile: Creating cache file %s...\n", img->cachename); +#endif /* DEBUG */ + + if ((img->cachefile = fopen(img->cachename, "wb+")) == NULL) + { + fprintf(stderr, "flush_tile: Unable to create swap file - %s\n", + strerror(errno)); + return; + } + } + + if (tile->pos >= 0) + { + if (ftell(img->cachefile) != tile->pos) + if (fseek(img->cachefile, tile->pos, SEEK_SET)) + perror("flush_tile:"); + } + else + { + if (fseek(img->cachefile, 0, SEEK_END)) + perror("flush_tile:"); + + tile->pos = ftell(img->cachefile); + } + +#ifdef DEBUG + fprintf(stderr, "flush_tile: Wrote tile cache at position %d...\n", + tile->pos); +#endif /* DEBUG */ + + fwrite(tile->ic->pixels, bpp, TILE_SIZE * TILE_SIZE, img->cachefile); + tile->ic = NULL; + tile->dirty = 0; +} + + +/* + * End of "$Id$". + */ diff --git a/filter/image.h b/filter/image.h new file mode 100644 index 0000000000..7793454552 --- /dev/null +++ b/filter/image.h @@ -0,0 +1,223 @@ +/* + * "$Id$" + * + * Image library definitions for the Common UNIX Printing System (CUPS). + * + * Copyright 1993-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + */ + +#ifndef _IMAGE_H_ +# define _IMAGE_H_ + +/* + * Include necessary headers... + */ + +# include +# include +# include +# include +# include + + +/* + * Colorspaces... + */ + +# define IMAGE_CMYK -4 /* Cyan, magenta, yellow, and black */ +# define IMAGE_CMY -3 /* Cyan, magenta, and yellow */ +# define IMAGE_BLACK -1 /* Black */ +# define IMAGE_WHITE 1 /* White (luminance) */ +# define IMAGE_RGB 3 /* Red, green, and blue */ + +/* + * Tile definitions... + */ + +# define TILE_SIZE 256 /* 256x256 pixel tiles */ +# define TILE_MINIMUM 10 /* Minimum number of tiles */ + +/* + * min/max/abs macros... + */ + +#ifndef max +# define max(a,b) ((a) > (b) ? (a) : (b)) +#endif /* !max */ +#ifndef min +# define min(a,b) ((a) < (b) ? (a) : (b)) +#endif /* !min */ +#ifndef abs +# define abs(a) ((a) < 0 ? -(a) : (a)) +#endif /* !abs */ + + +/* + * Image byte type... + */ + +typedef unsigned char ib_t; + +/* + * Tile cache structure... + */ + +typedef struct ic_str +{ + struct ic_str *prev, /* Previous tile in cache */ + *next; /* Next tile in cache */ + void *tile; /* Tile this is attached to */ + ib_t *pixels; /* Pixel data */ +} ic_t; + +/* + * Tile structure... + */ + +typedef struct +{ + int dirty; /* True if tile is dirty */ + long pos; /* Position of tile on disk (-1 if not written) */ + ic_t *ic; /* Pixel data */ +} itile_t; + +/* + * Image structure... + */ + +typedef struct +{ + int colorspace; /* Colorspace of image */ + unsigned xsize, /* Width of image in pixels */ + ysize, /* Height of image in pixels */ + xppi, /* X resolution in pixels-per-inch */ + yppi, /* Y resolution in pixels-per-inch */ + num_ics, /* Number of cached tiles */ + max_ics; /* Maximum number of cached tiles */ + itile_t **tiles; /* Tiles in image */ + ic_t *first, /* First cached tile in image */ + *last; /* Last cached tile in image */ + FILE *cachefile; /* Tile cache file */ + char cachename[256]; /* Tile cache filename */ +} image_t; + +/* + * Image row zooming structure... + */ + +typedef struct +{ + image_t *img; /* Image to zoom */ + unsigned xorig, + yorig, + width, /* Width of input area */ + height, /* Height of input area */ + depth, /* Number of bytes per pixel */ + rotated, /* Non-zero if image needs to be rotated */ + xsize, /* Width of output image */ + ysize, /* Height of output image */ + xmax, /* Maximum input image X position */ + ymax, /* Maximum input image Y position */ + xmod, /* Threshold for Bresenheim rounding */ + ymod; /* ... */ + int xstep, /* Amount to step for each pixel along X */ + xincr, + instep, /* Amount to step pixel pointer along X */ + inincr, + ystep, /* Amount to step for each pixel along Y */ + yincr, + row; /* Current row */ + ib_t *rows[2], /* Horizontally scaled pixel data */ + *in; /* Unscaled input pixel data */ +} izoom_t; + + +/* + * Basic image functions... + */ + +extern image_t *ImageOpen(char *filename, int primary, int secondary, + int saturation, int hue, ib_t *lut); +extern void ImageClose(image_t *img); +extern void ImageSetMaxTiles(image_t *img, int max_tiles); +extern void ImageSetProfile(float density, float matrix[3][3]); + +#define ImageGetDepth(img) ((img)->colorspace < 0 ? -(img)->colorspace : (img)->colorspace) +extern int ImageGetCol(image_t *img, int x, int y, int height, ib_t *pixels); +extern int ImageGetRow(image_t *img, int x, int y, int width, ib_t *pixels); +extern int ImagePutCol(image_t *img, int x, int y, int height, ib_t *pixels); +extern int ImagePutRow(image_t *img, int x, int y, int width, ib_t *pixels); + +/* + * File formats... + */ + +extern int ImageReadGIF(image_t *img, FILE *fp, int primary, int secondary, + int saturation, int hue, ib_t *lut); +extern int ImageReadJPEG(image_t *img, FILE *fp, int primary, int secondary, + int saturation, int hue, ib_t *lut); +extern int ImageReadPNG(image_t *img, FILE *fp, int primary, int secondary, + int saturation, int hue, ib_t *lut); +extern int ImageReadPNM(image_t *img, FILE *fp, int primary, int secondary, + int saturation, int hue, ib_t *lut); +extern int ImageReadPhotoCD(image_t *img, FILE *fp, int primary, + int secondary, int saturation, int hue, ib_t *lut); +extern int ImageReadSGI(image_t *img, FILE *fp, int primary, int secondary, + int saturation, int hue, ib_t *lut); +extern int ImageReadSunRaster(image_t *img, FILE *fp, int primary, + int secondary, int saturation, int hue, ib_t *lut); +extern int ImageReadTIFF(image_t *img, FILE *fp, int primary, int secondary, + int saturation, int hue, ib_t *lut); + +/* + * Colorspace conversions... + */ + +extern void ImageWhiteToWhite(ib_t *in, ib_t *out, int count); +extern void ImageWhiteToRGB(ib_t *in, ib_t *out, int count); +extern void ImageWhiteToBlack(ib_t *in, ib_t *out, int count); +extern void ImageWhiteToCMY(ib_t *in, ib_t *out, int count); +extern void ImageWhiteToCMYK(ib_t *in, ib_t *out, int count); + +extern void ImageRGBToWhite(ib_t *in, ib_t *out, int count); +extern void ImageRGBToRGB(ib_t *in, ib_t *out, int count); +extern void ImageRGBToBlack(ib_t *in, ib_t *out, int count); +extern void ImageRGBToCMY(ib_t *in, ib_t *out, int count); +extern void ImageRGBToCMYK(ib_t *in, ib_t *out, int count); + +extern void ImageRGBAdjust(ib_t *pixels, int count, int saturation, int hue); + +extern void ImageLut(ib_t *pixels, int count, ib_t *lut); + +/* + * Image scaling operations... + */ + +extern izoom_t *ImageZoomAlloc(image_t *img, int x0, int y0, int x1, int y1, + int xsize, int ysize, int rotated); +extern void ImageZoomFill(izoom_t *z, int iy); +extern void ImageZoomQFill(izoom_t *z, int iy); +extern void ImageZoomFree(izoom_t *z); + + +#endif /* !_IMAGE_H_ */ + +/* + * End of "$Id$". + */ diff --git a/filter/imagetops.c b/filter/imagetops.c new file mode 100644 index 0000000000..86aec58bfa --- /dev/null +++ b/filter/imagetops.c @@ -0,0 +1,486 @@ +/* + * "$Id$" + * + * Image file to PostScript filter for the Common UNIX Printing System (CUPS). + * + * Copyright 1993-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * main() - Main entry... + * ps_hex() - Print binary data as a series of hexadecimal numbers. + * ps_ascii85() - Print binary data as a series of base-85 numbers. + */ + +/* + * Include necessary headers... + */ + +#include "common.h" +#include "image.h" +#include + + +/* + * Globals... + */ + +int Flip = 0, /* Flip/mirror pages */ + Collate = 0, /* Collate copies? */ + Copies = 1; /* Number of copies */ + + +/* + * Local functions... + */ + +static void ps_hex(ib_t *, int); +static void ps_ascii85(ib_t *, int, int); + + +/* + * 'main()' - Main entry... + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line arguments */ + char *argv[]) /* I - Command-line arguments */ +{ + image_t *img; /* Image to print */ + float xprint, /* Printable area */ + yprint, + xinches, /* Total size in inches */ + yinches; + float xsize, /* Total size in points */ + ysize; + int xpages, /* # x pages */ + ypages, /* # y pages */ + xpage, /* Current x page */ + ypage, /* Current y page */ + page; /* Current page number */ + int x0, y0, /* Corners of the page in image coords */ + x1, y1; + ib_t *row; /* Current row */ + int y; /* Current Y coordinate in image */ + int colorspace; /* Output colorspace */ + int out_offset, /* Offset into output buffer */ + out_length; /* Length of output buffer */ + ppd_file_t *ppd; /* PPD file */ + int num_options; /* Number of print options */ + cups_option_t *options; /* Print options */ + char *val; /* Option value */ + int slowcollate; /* Collate copies the slow way */ + float g; /* Gamma correction value */ + float b; /* Brightness factor */ + float zoom; /* Zoom facter */ + int ppi; /* Pixels-per-inch */ + int hue, sat; /* Hue and saturation adjustment */ + + + if (argc != 7) + { + fputs("ERROR: imagetops job-id user title copies options file\n", stderr); + return (1); + } + + /* + * Process command-line options and write the prolog... + */ + + zoom = 0.0; + ppi = 0; + hue = 0; + sat = 100; + g = 1.0; + b = 1.0; + + options = NULL; + num_options = cupsParseOptions(argv[5], 0, &options); + + ppd = SetCommonOptions(num_options, options, 1); + + ppdMarkDefaults(ppd); + cupsMarkOptions(ppd, num_options, options); + + if ((val = cupsGetOption("copies", num_options, options)) != NULL) + Copies = atoi(val); + + if ((val = cupsGetOption("multiple-document-handling", num_options, options)) != NULL) + { + /* + * This IPP attribute is unnecessarily complicated... + * + * single-document, separate-documents-collated-copies, and + * single-document-new-sheet all require collated copies. + * + * separate-documents-collated-copies allows for uncollated copies. + */ + + Collate = strcmp(val, "separate-documents-collated-copies") != 0; + } + + if ((val = cupsGetOption("Collate", num_options, options)) != NULL && + strcmp(val, "True") == 0) + Collate = 1; + + if ((val = cupsGetOption("gamma", num_options, options)) != NULL) + g = atoi(val) * 0.001f; + + if ((val = cupsGetOption("brightness", num_options, options)) != NULL) + b = atoi(val) * 0.01f; + + if ((val = cupsGetOption("scaling", num_options, options)) != NULL) + zoom = atoi(val) * 0.01; + + if ((val = cupsGetOption("ppi", num_options, options)) != NULL) + ppi = atoi(val); + + if ((val = cupsGetOption("saturation", num_options, options)) != NULL) + sat = atoi(val); + + if ((val = cupsGetOption("hue", num_options, options)) != NULL) + hue = atoi(val); + + /* + * Open the input image to print... + */ + + colorspace = ColorDevice ? IMAGE_RGB : IMAGE_WHITE; + + if ((img = ImageOpen(argv[6], colorspace, IMAGE_WHITE, sat, hue, NULL)) == NULL) + { + fputs("ERROR: Unable to open image file for printing!\n", stderr); + ppdClose(ppd); + return (1); + } + + colorspace = img->colorspace; + + /* + * Scale as necessary... + */ + + xprint = (PageRight - PageLeft) / 72.0; + yprint = (PageTop - PageBottom) / 72.0; + + if (zoom == 0.0 && ppi == 0) + ppi = img->xppi; + + if (ppi > 0) + { + /* + * Scale the image as neccesary to match the desired pixels-per-inch. + */ + + xinches = (float)img->xsize / (float)ppi; + yinches = (float)img->ysize / (float)ppi; + } + else + { + /* + * Scale percentage of page size... + */ + + xsize = xprint * zoom; + ysize = xsize * img->ysize / img->xsize; + + if (ysize > (yprint * zoom)) + { + ysize = yprint * zoom; + xsize = ysize * img->xsize / img->ysize; + } + + xinches = xsize; + yinches = ysize; + } + + xpages = ceil(xinches / xprint); + ypages = ceil(yinches / yprint); + + /* + * See if we need to collate, and if so how we need to do it... + */ + + if (xpages == 1 && ypages == 1) + Collate = 0; + + slowcollate = Collate && ppdFindOption(ppd, "Collate") == NULL; + + /* + * Write any "exit server" options that have been selected... + */ + + ppdEmit(ppd, stdout, PPD_ORDER_EXIT); + + /* + * Write any JCL commands that are needed to print PostScript code... + */ + + if (ppd != NULL && ppd->jcl_begin && ppd->jcl_ps) + { + fputs(ppd->jcl_begin, stdout); + ppdEmit(ppd, stdout, PPD_ORDER_JCL); + fputs(ppd->jcl_ps, stdout); + } + + /* + * Start sending the document with any commands needed... + */ + + puts("%!"); + + ppdEmit(ppd, stdout, PPD_ORDER_DOCUMENT); + ppdEmit(ppd, stdout, PPD_ORDER_ANY); + ppdEmit(ppd, stdout, PPD_ORDER_PROLOG); + + if (g != 1.0 || b != 1.0) + printf("{ neg 1 add %.3f exp neg 1 add %.3f mul } bind settransfer\n", g, b); + + if (Copies > 1 && !slowcollate) + { + printf("/#copies %d def\n", Copies); + Copies = 1; + } + + /* + * Output the pages... + */ + + xprint = xinches / xpages; + yprint = yinches / ypages; + row = malloc(img->xsize * abs(colorspace) + 3); + + for (page = 1; Copies > 0; Copies --) + for (xpage = 0; xpage < xpages; xpage ++) + for (ypage = 0; ypage < ypages; ypage ++, page ++) + { + fprintf(stderr, "INFO: Printing page %d...\n", page); + + ppdEmit(ppd, stdout, PPD_ORDER_PAGE); + + puts("gsave"); + + if (Flip) + printf("%.0f 0 translate -1 1 scale\n", PageWidth); + + switch (Orientation) + { + case 1 : /* Landscape */ + printf("%.0f 0 translate 90 rotate\n", PageLength); + break; + case 2 : /* Reverse Portrait */ + printf("%.0f %.0f translate 180 rotate\n", PageWidth, PageLength); + break; + case 3 : /* Reverse Landscape */ + printf("0 %.0f translate -90 rotate\n", PageWidth); + break; + } + + x0 = img->xsize * xpage / xpages; + x1 = img->xsize * (xpage + 1) / xpages - 1; + y0 = img->ysize * ypage / ypages; + y1 = img->ysize * (ypage + 1) / ypages - 1; + + printf("%.1f %.1f translate\n", PageLeft, PageBottom + 72.0 * yprint); + printf("%.3f %.3f scale\n\n", + xprint * 72.0 / (x1 - x0 + 1), + yprint * 72.0 / (y1 - y0 + 1)); + + if (LanguageLevel == 1) + { + printf("/picture %d string def\n", (x1 - x0 + 1) * abs(colorspace)); + printf("%d %d 8[1 0 0 -1 0 1]", (x1 - x0 + 1), (y1 - y0 + 1)); + + if (colorspace == IMAGE_WHITE) + puts("{currentfile picture readhexstring pop} image"); + else + puts("{currentfile picture readhexstring pop} false 3 colorimage"); + + for (y = y0; y <= y1; y ++) + { + ImageGetRow(img, x0, y, x1 - x0 + 1, row); + ps_hex(row, (x1 - x0 + 1) * abs(colorspace)); + } + } + else + { + if (colorspace == IMAGE_WHITE) + puts("/DeviceGray setcolorspace"); + else + puts("/DeviceRGB setcolorspace"); + + printf("<<" + "/ImageType 1" + "/Width %d" + "/Height %d" + "/BitsPerComponent 8", + x1 - x0 + 1, y1 - y0 + 1); + + if (colorspace == IMAGE_WHITE) + fputs("/Decode[0 1]", stdout); + else + fputs("/Decode[0 1 0 1 0 1]", stdout); + + fputs("/DataSource currentfile /ASCII85Decode filter", stdout); + + if (((x1 - x0 + 1) / xprint) < 100.0) + fputs("/Interpolate true", stdout); + + puts("/ImageMatrix[1 0 0 -1 0 1]>>image"); + + for (y = y0, out_offset = 0; y <= y1; y ++) + { + ImageGetRow(img, x0, y, x1 - x0 + 1, row + out_offset); + + out_length = (x1 - x0 + 1) * abs(colorspace) + out_offset; + out_offset = out_length & 3; + + ps_ascii85(row, out_length, y == y1); + + if (out_offset > 0) + memcpy(row, row + out_length - out_offset, out_offset); + } + } + + puts("grestore"); + puts("showpage"); + } + + /* + * End the job with the appropriate JCL command or CTRL-D otherwise. + */ + + if (ppd != NULL && ppd->jcl_end) + fputs(ppd->jcl_end, stdout); + else + putchar(0x04); + + /* + * Close files... + */ + + ImageClose(img); + ppdClose(ppd); + + return (0); +} + + +/* + * 'ps_hex()' - Print binary data as a series of hexadecimal numbers. + */ + +static void +ps_hex(ib_t *data, /* I - Data to print */ + int length) /* I - Number of bytes to print */ +{ + int col; + static char *hex = "0123456789ABCDEF"; + + + col = 0; + + while (length > 0) + { + /* + * Put the hex chars out to the file; note that we don't use printf() + * for speed reasons... + */ + + putchar(hex[*data >> 4]); + putchar(hex[*data & 15]); + + data ++; + length --; + + col = (col + 1) & 31; + if (col == 0 && length > 0) + putchar('\n'); + } + + putchar('\n'); +} + + +/* + * 'ps_ascii85()' - Print binary data as a series of base-85 numbers. + */ + +static void +ps_ascii85(ib_t *data, /* I - Data to print */ + int length, /* I - Number of bytes to print */ + int last_line) /* I - Last line of raster data? */ +{ + int i; /* Looping var */ + unsigned b; /* Binary data word */ + unsigned char c[5]; /* ASCII85 encoded chars */ + + + while (length > 3) + { + b = (((((data[0] << 8) | data[1]) << 8) | data[2]) << 8) | data[3]; + + if (b == 0) + putchar('z'); + else + { + c[4] = (b % 85) + '!'; + b /= 85; + c[3] = (b % 85) + '!'; + b /= 85; + c[2] = (b % 85) + '!'; + b /= 85; + c[1] = (b % 85) + '!'; + b /= 85; + c[0] = b + '!'; + + fwrite(c, 5, 1, stdout); + } + + data += 4; + length -= 4; + } + + if (last_line) + { + if (length > 0) + { + for (b = 0, i = length; i > 0; b = (b << 8) | data[0], data ++, i --); + + c[4] = (b % 85) + '!'; + b /= 85; + c[3] = (b % 85) + '!'; + b /= 85; + c[2] = (b % 85) + '!'; + b /= 85; + c[1] = (b % 85) + '!'; + b /= 85; + c[0] = b + '!'; + + fwrite(c, length + 1, 1, stdout); + } + + puts("~>"); + } +} + + +/* + * End of "$Id$". + */ diff --git a/filter/imagetoraster.c b/filter/imagetoraster.c new file mode 100644 index 0000000000..7584651802 --- /dev/null +++ b/filter/imagetoraster.c @@ -0,0 +1,3835 @@ +/* + * "$Id$" + * + * Image file to raster filter for the Common UNIX Printing System (CUPS). + * + * Copyright 1993-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * main() - Main entry... + * format_CMY() - Convert image data to CMY. + * format_CMYK() - Convert image data to CMYK. + * format_K() - Convert image data to black. + * format_KCMY() - Convert image data to KCMY. + * format_KCMYcm() - Convert image data to KCMYcm. + * format_RGBA() - Convert image data to RGBA. + * format_W() - Convert image data to luminance. + * format_YMC() - Convert image data to YMC. + * format_YMCK() - Convert image data to YMCK. + * make_lut() - Make a lookup table given gamma and brightness values. + */ + +/* + * Include necessary headers... + */ + +/* + * Include necessary headers... + */ + +#include "common.h" +#include "image.h" +#include +#include + + +/* + * Globals... + */ + +int Flip = 0, /* Flip/mirror pages */ + Collate = 0, /* Collate copies? */ + Copies = 1; /* Number of copies */ +int Floyd16x16[16][16] = /* Traditional Floyd ordered dither */ + { + { 0, 128, 32, 160, 8, 136, 40, 168, + 2, 130, 34, 162, 10, 138, 42, 170 }, + { 192, 64, 224, 96, 200, 72, 232, 104, + 194, 66, 226, 98, 202, 74, 234, 106 }, + { 48, 176, 16, 144, 56, 184, 24, 152, + 50, 178, 18, 146, 58, 186, 26, 154 }, + { 240, 112, 208, 80, 248, 120, 216, 88, + 242, 114, 210, 82, 250, 122, 218, 90 }, + { 12, 140, 44, 172, 4, 132, 36, 164, + 14, 142, 46, 174, 6, 134, 38, 166 }, + { 204, 76, 236, 108, 196, 68, 228, 100, + 206, 78, 238, 110, 198, 70, 230, 102 }, + { 60, 188, 28, 156, 52, 180, 20, 148, + 62, 190, 30, 158, 54, 182, 22, 150 }, + { 252, 124, 220, 92, 244, 116, 212, 84, + 254, 126, 222, 94, 246, 118, 214, 86 }, + { 3, 131, 35, 163, 11, 139, 43, 171, + 1, 129, 33, 161, 9, 137, 41, 169 }, + { 195, 67, 227, 99, 203, 75, 235, 107, + 193, 65, 225, 97, 201, 73, 233, 105 }, + { 51, 179, 19, 147, 59, 187, 27, 155, + 49, 177, 17, 145, 57, 185, 25, 153 }, + { 243, 115, 211, 83, 251, 123, 219, 91, + 241, 113, 209, 81, 249, 121, 217, 89 }, + { 15, 143, 47, 175, 7, 135, 39, 167, + 13, 141, 45, 173, 5, 133, 37, 165 }, + { 207, 79, 239, 111, 199, 71, 231, 103, + 205, 77, 237, 109, 197, 69, 229, 101 }, + { 63, 191, 31, 159, 55, 183, 23, 151, + 61, 189, 29, 157, 53, 181, 21, 149 }, + { 254, 127, 223, 95, 247, 119, 215, 87, + 253, 125, 221, 93, 245, 117, 213, 85 } + }; +int Floyd8x8[8][8] = + { + { 0, 32, 8, 40, 2, 34, 10, 42 }, + { 48, 16, 56, 24, 50, 18, 58, 26 }, + { 12, 44, 4, 36, 14, 46, 6, 38 }, + { 60, 28, 52, 20, 62, 30, 54, 22 }, + { 3, 35, 11, 43, 1, 33, 9, 41 }, + { 51, 19, 59, 27, 49, 17, 57, 25 }, + { 15, 47, 7, 39, 13, 45, 5, 37 }, + { 63, 31, 55, 23, 61, 29, 53, 21 } + }; +int Floyd4x4[4][4] = + { + { 0, 8, 2, 10 }, + { 12, 4, 14, 6 }, + { 3, 11, 1, 9 }, + { 15, 7, 13, 5 } + }; + +ib_t OnPixels[256], /* On-pixel LUT */ + OffPixels[256]; /* Off-pixel LUT */ +int Planes[] = /* Number of planes for each colorspace */ + { 1, 3, 4, 1, 3, 3, 4, 4, 4, 6 }; + + +/* + * Local functions... + */ + +static void exec_choice(cups_page_header_t *header, ppd_choice_t *choice); +static void format_CMY(cups_page_header_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, ib_t *r0, ib_t *r1); +static void format_CMYK(cups_page_header_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, ib_t *r0, ib_t *r1); +static void format_K(cups_page_header_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, ib_t *r0, ib_t *r1); +static void format_KCMYcm(cups_page_header_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, ib_t *r0, ib_t *r1); +static void format_KCMY(cups_page_header_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, ib_t *r0, ib_t *r1); +#define format_RGB format_CMY +static void format_RGBA(cups_page_header_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, ib_t *r0, ib_t *r1); +static void format_W(cups_page_header_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, ib_t *r0, ib_t *r1); +static void format_YMC(cups_page_header_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, ib_t *r0, ib_t *r1); +static void format_YMCK(cups_page_header_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, ib_t *r0, ib_t *r1); +static void make_lut(ib_t *, int, float, float); + + +/* + * 'main()' - Main entry... + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line arguments */ + char *argv[]) /* I - Command-line arguments */ +{ + int i; /* Looping var */ + image_t *img; /* Image to print */ + float xprint, /* Printable area */ + yprint, + xinches, /* Total size in inches */ + yinches; + float xsize, /* Total size in points */ + ysize; + int xpages, /* # x pages */ + ypages, /* # y pages */ + xpage, /* Current x page */ + ypage, /* Current y page */ + xtemp, /* Bitmap width in pixels */ + ytemp, /* Bitmap height in pixels */ + page; /* Current page number */ + int x0, y0, /* Corners of the page in image coords */ + x1, y1; + ppd_file_t *ppd; /* PPD file */ + ppd_choice_t *choice; /* PPD option choice */ + char *resolution, /* Output resolution */ + *media_type; /* Media type */ + ppd_profile_t *profile; /* Color profile */ + cups_raster_t *ras; /* Raster stream */ + cups_page_header_t header; /* Page header */ + int num_options; /* Number of print options */ + cups_option_t *options; /* Print options */ + char *val; /* Option value */ + int slowcollate, /* Collate copies the slow way */ + slowcopies; /* Make copies the "slow" way? */ + float g; /* Gamma correction value */ + float b; /* Brightness factor */ + float zoom; /* Zoom facter */ + int ppi; /* Pixels-per-inch */ + int hue, sat; /* Hue and saturation adjustment */ + izoom_t *z; /* ImageZoom buffer */ + int primary, /* Primary image colorspace */ + secondary; /* Secondary image colorspace */ + ib_t *row, /* Current row */ + *r0, /* Top row */ + *r1; /* Bottom row */ + int y, /* Current Y coordinate on page */ + iy, /* Current Y coordinate in image */ + last_iy, /* Previous Y coordinate in image */ + yerr0, /* Top Y error value */ + yerr1, /* Bottom Y error value */ + blank; /* Blank value */ + ib_t lut[256]; /* Gamma/brightness LUT */ + int plane, /* Current color plane */ + num_planes; /* Number of color planes */ + + + if (argc != 7) + { + fputs("ERROR: imagetoraster job-id user title copies options file\n", stderr); + return (1); + } + + fprintf(stderr, "INFO: %s %s %s %s %s %s %s\n", argv[0], argv[1], argv[2], + argv[3], argv[4], argv[5], argv[6]); + + /* + * Process command-line options and write the prolog... + */ + + zoom = 0.0; + ppi = 0; + hue = 0; + sat = 100; + g = 1.0; + b = 1.0; + + options = NULL; + num_options = cupsParseOptions(argv[5], 0, &options); + + ppd = SetCommonOptions(num_options, options, 0); + + ppdMarkDefaults(ppd); + cupsMarkOptions(ppd, num_options, options); + + if ((val = cupsGetOption("copies", num_options, options)) != NULL) + Copies = atoi(val); + + if ((val = cupsGetOption("multiple-document-handling", num_options, options)) != NULL) + { + /* + * This IPP attribute is unnecessarily complicated... + * + * single-document, separate-documents-collated-copies, and + * single-document-new-sheet all require collated copies. + * + * separate-documents-collated-copies allows for uncollated copies. + */ + + Collate = strcmp(val, "separate-documents-collated-copies") != 0; + } + + if ((val = cupsGetOption("Collate", num_options, options)) != NULL && + strcmp(val, "True") == 0) + Collate = 1; + + if ((val = cupsGetOption("gamma", num_options, options)) != NULL) + g = atoi(val) * 0.001f; + + if ((val = cupsGetOption("brightness", num_options, options)) != NULL) + b = atoi(val) * 0.01f; + + if ((val = cupsGetOption("scaling", num_options, options)) != NULL) + zoom = atoi(val) * 0.01; + + if ((val = cupsGetOption("ppi", num_options, options)) != NULL) + ppi = atoi(val); + + if ((val = cupsGetOption("saturation", num_options, options)) != NULL) + sat = atoi(val); + + if ((val = cupsGetOption("hue", num_options, options)) != NULL) + hue = atoi(val); + + /* + * Set the needed options in the page header... + */ + + memset(&header, 0, sizeof(header)); + header.HWResolution[0] = 100; + header.HWResolution[1] = 100; + header.cupsBitsPerColor = 1; + header.cupsColorOrder = CUPS_ORDER_CHUNKED; + header.cupsColorSpace = CUPS_CSPACE_RGB; + + if ((choice = ppdFindMarkedChoice(ppd, "ColorModel")) != NULL) + exec_choice(&header, choice); + + if ((choice = ppdFindMarkedChoice(ppd, "InputSlot")) != NULL) + exec_choice(&header, choice); + + if ((choice = ppdFindMarkedChoice(ppd, "MediaType")) != NULL) + { + exec_choice(&header, choice); + + media_type = choice->choice; + } + else + media_type = ""; + + if ((choice = ppdFindMarkedChoice(ppd, "Resolution")) != NULL) + { + exec_choice(&header, choice); + + resolution = choice->choice; + } + else + resolution = ""; + + /* + * Choose the appropriate colorspace and color profile... + */ + + switch (header.cupsColorSpace) + { + case CUPS_CSPACE_W : + primary = IMAGE_WHITE; + secondary = IMAGE_WHITE; + header.cupsBitsPerPixel = header.cupsBitsPerColor; + break; + + case CUPS_CSPACE_RGB : + case CUPS_CSPACE_RGBA : + primary = IMAGE_RGB; + secondary = IMAGE_RGB; + + if (header.cupsColorOrder == CUPS_ORDER_CHUNKED) + { + if (header.cupsBitsPerColor >= 8) + header.cupsBitsPerPixel = header.cupsBitsPerColor * 3; + else + header.cupsBitsPerPixel = header.cupsBitsPerColor * 4; + } + else + header.cupsBitsPerPixel = header.cupsBitsPerColor; + break; + + case CUPS_CSPACE_K : + primary = IMAGE_BLACK; + secondary = IMAGE_BLACK; + header.cupsBitsPerPixel = header.cupsBitsPerColor; + break; + + default : + primary = IMAGE_CMYK; + secondary = IMAGE_CMYK; + + if (header.cupsColorOrder == CUPS_ORDER_CHUNKED) + header.cupsBitsPerPixel = header.cupsBitsPerColor * 4; + else + header.cupsBitsPerPixel = header.cupsBitsPerColor; + break; + + case CUPS_CSPACE_CMY : + case CUPS_CSPACE_YMC : + primary = IMAGE_CMY; + secondary = IMAGE_CMY; + + if (header.cupsColorOrder == CUPS_ORDER_CHUNKED) + { + if (header.cupsBitsPerColor >= 8) + header.cupsBitsPerPixel = 24; + else + header.cupsBitsPerPixel = header.cupsBitsPerColor * 4; + } + else + header.cupsBitsPerPixel = header.cupsBitsPerColor; + break; + + case CUPS_CSPACE_KCMYcm : + if (header.cupsBitsPerPixel == 1) + { + primary = IMAGE_CMY; + secondary = IMAGE_CMY; + + if (header.cupsColorOrder == CUPS_ORDER_CHUNKED) + header.cupsBitsPerPixel = 8; + else + header.cupsBitsPerPixel = 1; + } + else + { + primary = IMAGE_CMYK; + secondary = IMAGE_CMYK; + + if (header.cupsColorOrder == CUPS_ORDER_CHUNKED) + header.cupsBitsPerPixel = header.cupsBitsPerColor * 4; + else + header.cupsBitsPerPixel = header.cupsBitsPerColor; + } + break; + } + + /* + * Find a color profile matching the current options... + */ + + if (ppd != NULL) + { + for (i = 0, profile = ppd->profiles; i < ppd->num_profiles; i ++, profile ++) + if ((strcmp(profile->resolution, resolution) == 0 || + profile->resolution[0] == '-') && + (strcmp(profile->media_type, media_type) == 0 || + profile->media_type[0] == '-')) + break; + + /* + * If we found a color profile, use it! + */ + + if (i < ppd->num_profiles) + { + fputs("Setting color profile!\n", stderr); + ImageSetProfile(profile->density, profile->matrix); + } + } + + /* + * Create a gamma/brightness LUT... + */ + + make_lut(lut, primary, g, b); + + /* + * Open the input image to print... + */ + + fputs("INFO: Loading image file...\n", stderr); + + if ((img = ImageOpen(argv[6], primary, secondary, sat, hue, lut)) == NULL) + { + fputs("ERROR: Unable to open image file for printing!\n", stderr); + ppdClose(ppd); + return (1); + } + + /* + * Scale as necessary... + */ + + if (Orientation & 1) + { + xprint = (PageTop - PageBottom) / 72.0; + yprint = (PageRight - PageLeft) / 72.0; + } + else + { + xprint = (PageRight - PageLeft) / 72.0; + yprint = (PageTop - PageBottom) / 72.0; + } + + if (zoom == 0.0 && ppi == 0) + ppi = img->xppi; + + if (ppi > 0) + { + /* + * Scale the image as neccesary to match the desired pixels-per-inch. + */ + + xinches = (float)img->xsize / (float)ppi; + yinches = (float)img->ysize / (float)ppi; + } + else + { + /* + * Scale percentage of page size... + */ + + xsize = xprint * zoom; + ysize = xsize * img->ysize / img->xsize; + + if (ysize > (yprint * zoom)) + { + ysize = yprint * zoom; + xsize = ysize * img->xsize / img->ysize; + } + + xinches = xsize; + yinches = ysize; + } + + xpages = ceil(xinches / xprint); + ypages = ceil(yinches / yprint); + + /* + * Compute the bitmap size... + */ + + xprint = xinches / xpages; + yprint = yinches / ypages; + + if ((val = cupsGetOption("Page", num_options, options)) != NULL && + strncmp(val, "Custom.", 7) == 0) + { + if (Orientation & 1) + { + header.cupsWidth = yprint * header.HWResolution[0]; + header.cupsHeight = xprint * header.HWResolution[1]; + header.PageSize[0] = yprint * 72.0; + header.PageSize[1] = xprint * 72.0; + } + else + { + header.cupsWidth = xprint * header.HWResolution[0]; + header.cupsHeight = yprint * header.HWResolution[1]; + header.PageSize[0] = xprint * 72.0; + header.PageSize[1] = yprint * 72.0; + } + } + else + { + header.cupsWidth = (PageRight - PageLeft) * header.HWResolution[0] / 72.0; + header.cupsHeight = (PageTop - PageBottom) * header.HWResolution[1] / 72.0; + header.PageSize[0] = PageWidth; + header.PageSize[1] = PageLength; + } + + switch (header.cupsColorOrder) + { + case CUPS_ORDER_CHUNKED : + header.cupsBytesPerLine = (header.cupsBitsPerPixel * + header.cupsWidth + 7) / 8; + num_planes = 1; + break; + + case CUPS_ORDER_BANDED : + if (header.cupsColorSpace == CUPS_CSPACE_KCMYcm && + header.cupsBitsPerColor > 1) + header.cupsBytesPerLine = (header.cupsBitsPerPixel * + header.cupsWidth + 7) / 8 * 4; + else + header.cupsBytesPerLine = (header.cupsBitsPerPixel * + header.cupsWidth + 7) / 8 * + Planes[header.cupsColorSpace]; + num_planes = 1; + break; + + case CUPS_ORDER_PLANAR : + header.cupsBytesPerLine = (header.cupsBitsPerPixel * + header.cupsWidth + 7) / 8; + num_planes = Planes[header.cupsColorSpace]; + break; + } + + /* + * See if we need to collate, and if so how we need to do it... + */ + + if (xpages == 1 && ypages == 1) + Collate = 0; + + slowcollate = Collate && ppdFindOption(ppd, "Collate") == NULL; + if (ppd != NULL) + slowcopies = ppd->manual_copies; + else + slowcopies = 1; + + if (Copies > 1 && !slowcollate && !slowcopies) + { + header.Collate = (cups_bool_t)Collate; + header.NumCopies = Copies; + + Copies = 1; + } + + /* + * Create the dithering lookup tables... + */ + + OnPixels[0] = 0x00; + OnPixels[255] = 0xff; + OffPixels[0] = 0x00; + OffPixels[255] = 0xff; + + switch (header.cupsBitsPerColor) + { + case 2 : + for (i = 1; i < 255; i ++) + { + OnPixels[i] = 0x55 * (i / 85 + 1); + OffPixels[i] = 0x55 * (i / 64); + } + break; + case 4 : + for (i = 1; i < 255; i ++) + { + OnPixels[i] = 17 * (i / 17 + 1); + OffPixels[i] = 17 * (i / 16); + } + + OnPixels[255] = OffPixels[255] = 0xff; + break; + } + + /* + * Output the pages... + */ + + fprintf(stderr, "DEBUG: cupsWidth = %d\n", header.cupsWidth); + fprintf(stderr, "DEBUG: cupsHeight = %d\n", header.cupsHeight); + fprintf(stderr, "DEBUG: cupsBitsPerColor = %d\n", header.cupsBitsPerColor); + fprintf(stderr, "DEBUG: cupsBitsPerPixel = %d\n", header.cupsBitsPerPixel); + fprintf(stderr, "DEBUG: cupsBytesPerLine = %d\n", header.cupsBytesPerLine); + fprintf(stderr, "DEBUG: cupsColorOrder = %d\n", header.cupsColorOrder); + fprintf(stderr, "DEBUG: cupsColorSpace = %d\n", header.cupsColorSpace); + fprintf(stderr, "DEBUG: img->colorspace = %d\n", img->colorspace); + + row = malloc(header.cupsBytesPerLine); + ras = cupsRasterOpen(1, CUPS_RASTER_WRITE); + blank = img->colorspace < 0 ? 0 : ~0; + + for (i = 0, page = 1; i < Copies; i ++) + for (xpage = 0; xpage < xpages; xpage ++) + for (ypage = 0; ypage < ypages; ypage ++, page ++) + { + fprintf(stderr, "INFO: Formatting page %d...\n", page); + + if (Orientation & 1) + { + x0 = img->xsize * ypage / ypages; + x1 = img->xsize * (ypage + 1) / ypages - 1; + y0 = img->ysize * xpage / xpages; + y1 = img->ysize * (xpage + 1) / xpages - 1; + + xtemp = header.HWResolution[0] * yprint; + ytemp = header.HWResolution[1] * xprint; + } + else + { + x0 = img->xsize * xpage / xpages; + x1 = img->xsize * (xpage + 1) / xpages - 1; + y0 = img->ysize * ypage / ypages; + y1 = img->ysize * (ypage + 1) / ypages - 1; + + xtemp = header.HWResolution[0] * xprint; + ytemp = header.HWResolution[1] * yprint; + } + + cupsRasterWriteHeader(ras, &header); + + for (plane = 0; plane < num_planes; plane ++) + { + /* + * Initialize the image "zoom" engine... + */ + + z = ImageZoomAlloc(img, x0, y0, x1, y1, xtemp, ytemp, Orientation & 1); + + /* + * Write leading blank space as needed... + */ + + if (header.cupsHeight > z->ysize && Orientation < 2) + { + memset(row, blank, header.cupsBytesPerLine); + + for (y = header.cupsHeight - z->ysize; y > 0; y --) + { + if (cupsRasterWritePixels(ras, row, header.cupsBytesPerLine) < + header.cupsBytesPerLine) + { + fputs("ERROR: Unable to write raster data to driver!\n", stderr); + ImageClose(img); + exit(1); + } + } + } + + /* + * Then write image data... + */ + + for (y = z->ysize, yerr0 = 0, yerr1 = z->ysize, iy = 0, last_iy = -2; + y > 0; + y --) + { + if (iy != last_iy) + { + if (header.cupsBitsPerColor >= 8) + { + /* + * Do bilinear interpolation for 8+ bpp images... + */ + + if ((iy - last_iy) > 1) + ImageZoomFill(z, iy); + + ImageZoomFill(z, iy + z->yincr); + } + else + { + /* + * Just do nearest-neighbor sampling for < 8 bpp images... + */ + + ImageZoomQFill(z, iy); + } + + last_iy = iy; + } + + /* + * Format this line of raster data for the printer... + */ + + memset(row, blank, header.cupsBytesPerLine); + + r0 = z->rows[z->row]; + r1 = z->rows[1 - z->row]; + + switch (header.cupsColorSpace) + { + case CUPS_CSPACE_W : + format_W(&header, row, y, plane, z->xsize, z->ysize, + yerr0, yerr1, r0, r1); + break; + case CUPS_CSPACE_RGB : + format_RGB(&header, row, y, plane, z->xsize, z->ysize, + yerr0, yerr1, r0, r1); + break; + case CUPS_CSPACE_RGBA : + format_RGBA(&header, row, y, plane, z->xsize, z->ysize, + yerr0, yerr1, r0, r1); + break; + case CUPS_CSPACE_K : + format_K(&header, row, y, plane, z->xsize, z->ysize, + yerr0, yerr1, r0, r1); + break; + case CUPS_CSPACE_CMY : + format_CMY(&header, row, y, plane, z->xsize, z->ysize, + yerr0, yerr1, r0, r1); + break; + case CUPS_CSPACE_YMC : + format_YMC(&header, row, y, plane, z->xsize, z->ysize, + yerr0, yerr1, r0, r1); + break; + case CUPS_CSPACE_CMYK : + format_CMYK(&header, row, y, plane, z->xsize, z->ysize, + yerr0, yerr1, r0, r1); + break; + case CUPS_CSPACE_YMCK : + format_YMCK(&header, row, y, plane, z->xsize, z->ysize, + yerr0, yerr1, r0, r1); + break; + case CUPS_CSPACE_KCMY : + format_KCMY(&header, row, y, plane, z->xsize, z->ysize, + yerr0, yerr1, r0, r1); + break; + case CUPS_CSPACE_KCMYcm : + format_KCMYcm(&header, row, y, plane, z->xsize, z->ysize, + yerr0, yerr1, r0, r1); + break; + } + + /* + * Write the raster data to the driver... + */ + + if (cupsRasterWritePixels(ras, row, header.cupsBytesPerLine) < + header.cupsBytesPerLine) + { + fputs("ERROR: Unable to write raster data to driver!\n", stderr); + ImageClose(img); + exit(1); + } + + /* + * Compute the next scanline in the image... + */ + + iy += z->ystep; + yerr0 += z->ymod; + yerr1 -= z->ymod; + if (yerr1 <= 0) + { + yerr0 -= z->ysize; + yerr1 += z->ysize; + iy += z->yincr; + } + } + + /* + * Write trailing blank space as needed... + */ + + if (header.cupsHeight > z->ysize && Orientation >= 2) + { + memset(row, blank, header.cupsBytesPerLine); + + for (y = header.cupsHeight - z->ysize; y > 0; y --) + { + if (cupsRasterWritePixels(ras, row, header.cupsBytesPerLine) < + header.cupsBytesPerLine) + { + fputs("ERROR: Unable to write raster data to driver!\n", stderr); + ImageClose(img); + exit(1); + } + } + } + + /* + * Free memory used for the "zoom" engine... + */ + + ImageZoomFree(z); + } + } + + /* + * Close files... + */ + + free(row); + cupsRasterClose(ras); + ImageClose(img); + ppdClose(ppd); + + return (0); +} + + +/* + * 'exec_choice()' - Execute PostScript setpagedevice commands as appropriate. + */ + +static void +exec_choice(cups_page_header_t *header, /* I - Page header */ + ppd_choice_t *choice) /* I - Option choice to execute */ +{ + char *code, /* Pointer into code string */ + *ptr, /* Pointer into name/value string */ + name[255], /* Name of pagedevice entry */ + value[1024]; /* Value of pagedevice entry */ + + + for (code = choice->code; *code != '\0';) + { + /* + * Search for the start of a dictionary name... + */ + + while (*code != '/' && *code != '\0') + code ++; + + if (*code == '\0') + break; + + /* + * Get the name... + */ + + code ++; + for (ptr = name; isalnum(*code) && (ptr - name) < (sizeof(name) - 1);) + *ptr++ = *code++; + *ptr = '\0'; + + /* + * The parse the value as needed... + */ + + while (isspace(*code)) + code ++; + + if (*code == '\0') + break; + + if (*code == '[') + { + /* + * Read array of values... + */ + + code ++; + for (ptr = value; + *code != ']' && *code != '\0' && + (ptr - value) < (sizeof(value) - 1);) + *ptr++ = *code++; + *ptr = '\0'; + } + else if (*code == '(') + { + /* + * Read string value... + */ + + code ++; + for (ptr = value; + *code != ')' && *code != '\0' && + (ptr - value) < (sizeof(value) - 1);) + if (*code == '\\') + { + code ++; + if (isdigit(*code)) + *ptr++ = (char)strtol(code, &code, 8); + else + *ptr++ = *code++; + } + else + *ptr++ = *code++; + + *ptr = '\0'; + } + else if (isdigit(*code) || *code == '-') + { + /* + * Read single number... + */ + + for (ptr = value; + (isdigit(*code) || *code == '-') && + (ptr - value) < (sizeof(value) - 1);) + *ptr++ = *code++; + *ptr = '\0'; + } + else + continue; + + /* + * Assign the value as needed... + */ + + if (strcmp(name, "cupsMediaType") == 0) + header->cupsMediaType = atoi(value); + else if (strcmp(name, "cupsBitsPerColor") == 0) + header->cupsBitsPerColor = atoi(value); + else if (strcmp(name, "cupsColorOrder") == 0) + header->cupsColorOrder = (cups_order_t)atoi(value); + else if (strcmp(name, "cupsColorSpace") == 0) + header->cupsColorSpace = (cups_cspace_t)atoi(value); + else if (strcmp(name, "cupsCompression") == 0) + header->cupsCompression = atoi(value); + else if (strcmp(name, "cupsRowCount") == 0) + header->cupsRowCount = atoi(value); + else if (strcmp(name, "cupsRowFeed") == 0) + header->cupsRowFeed = atoi(value); + else if (strcmp(name, "cupsRowStep") == 0) + header->cupsRowStep = atoi(value); + else if (strcmp(name, "HWResolution") == 0) + sscanf(value, "%d%d", header->HWResolution + 0, header->HWResolution + 1); + else if (strcmp(name, "cupsMediaPosition") == 0) + header->MediaPosition = atoi(value); + else if (strcmp(name, "MediaType") == 0) + strcpy(header->MediaType, value); + else if (strcmp(name, "OutputType") == 0) + strcpy(header->OutputType, value); + } +} + + +/* + * 'format_CMY()' - Convert image data to CMY. + */ + +static void +format_CMY(cups_page_header_t *header, /* I - Page header */ + unsigned char *row, /* IO - Bitmap data for device */ + int y, /* I - Current row */ + int z, /* I - Current plane */ + int xsize, /* I - Width of image data */ + int ysize, /* I - Height of image data */ + int yerr0, /* I - Top Y error */ + int yerr1, /* I - Bottom Y error */ + ib_t *r0, /* I - Primary image data */ + ib_t *r1) /* I - Image data for interpolation */ +{ + ib_t *ptr, /* Pointer into row */ + *cptr, /* Pointer into cyan */ + *mptr, /* Pointer into magenta */ + *yptr, /* Pointer into yellow */ + bitmask; /* Current mask for pixel */ + int bitoffset; /* Current offset in line */ + int bandwidth; /* Width of a color band */ + int x, /* Current X coordinate on page */ + *dither; /* Pointer into dither array */ + + + if (Orientation == 1 || Orientation == 2) + bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize); + else + bitoffset = 0; + + ptr = row + bitoffset / 8; + bandwidth = header->cupsBytesPerLine / 4; + + switch (header->cupsColorOrder) + { + case CUPS_ORDER_CHUNKED : + switch (header->cupsBitsPerColor) + { + case 1 : + bitmask = 64 >> (bitoffset & 7); + dither = Floyd16x16[y & 15]; + + for (x = xsize ; x > 0; x --) + { + if (*r0++ > dither[x & 15]) + *ptr ^= bitmask; + bitmask >>= 1; + + if (*r0++ > dither[x & 15]) + *ptr ^= bitmask; + bitmask >>= 1; + + if (*r0++ > dither[x & 15]) + *ptr ^= bitmask; + + if (bitmask > 1) + bitmask >>= 2; + else + { + bitmask = 64; + ptr ++; + } + } + break; + + case 2 : + dither = Floyd8x8[y & 7]; + + for (x = xsize ; x > 0; x --, r0 += 3) + { + if ((r0[0] & 63) > dither[x & 7]) + *ptr ^= (0x30 & OnPixels[r0[0]]); + else + *ptr ^= (0x30 & OffPixels[r0[0]]); + + if ((r0[1] & 63) > dither[x & 7]) + *ptr ^= (0x0c & OnPixels[r0[1]]); + else + *ptr ^= (0x0c & OffPixels[r0[1]]); + + if ((r0[2] & 63) > dither[x & 7]) + *ptr++ ^= (0x03 & OnPixels[r0[2]]); + else + *ptr++ ^= (0x03 & OffPixels[r0[2]]); + } + break; + + case 4 : + dither = Floyd4x4[y & 3]; + + for (x = xsize ; x > 0; x --, r0 += 3) + { + if ((r0[0] & 15) > dither[x & 3]) + *ptr++ ^= (0x0f & OnPixels[r0[0]]); + else + *ptr++ ^= (0x0f & OffPixels[r0[0]]); + + if ((r0[1] & 15) > dither[x & 3]) + *ptr ^= (0xf0 & OnPixels[r0[1]]); + else + *ptr ^= (0xf0 & OffPixels[r0[1]]); + + if ((r0[2] & 15) > dither[x & 3]) + *ptr++ ^= (0x0f & OnPixels[r0[2]]); + else + *ptr++ ^= (0x0f & OffPixels[r0[2]]); + } + break; + + case 8 : + for (x = xsize * 3; x > 0; x --, r0 ++, r1 ++) + if (*r0 == *r1) + *ptr++ = *r0; + else + *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize; + break; + } + break; + + case CUPS_ORDER_BANDED : + cptr = ptr; + mptr = ptr + bandwidth; + yptr = ptr + 2 * bandwidth; + + switch (header->cupsBitsPerColor) + { + case 1 : + bitmask = 0x80 >> (bitoffset & 7); + dither = Floyd16x16[y & 15]; + + for (x = xsize; x > 0; x --) + { + if (*r0++ > dither[x & 15]) + *cptr ^= bitmask; + if (*r0++ > dither[x & 15]) + *mptr ^= bitmask; + if (*r0++ > dither[x & 15]) + *yptr ^= bitmask; + + if (bitmask > 1) + bitmask >>= 1; + else + { + bitmask = 0x80; + cptr ++; + mptr ++; + yptr ++; + } + } + break; + + case 2 : + bitmask = 0xc0 >> (bitoffset & 7); + dither = Floyd8x8[y & 7]; + + for (x = xsize; x > 0; x --) + { + if ((*r0 & 63) > dither[x & 7]) + *cptr ^= (bitmask & OnPixels[*r0++]); + else + *cptr ^= (bitmask & OffPixels[*r0++]); + + if ((*r0 & 63) > dither[x & 7]) + *mptr ^= (bitmask & OnPixels[*r0++]); + else + *mptr ^= (bitmask & OffPixels[*r0++]); + + if ((*r0 & 63) > dither[x & 7]) + *yptr ^= (bitmask & OnPixels[*r0++]); + else + *yptr ^= (bitmask & OffPixels[*r0++]); + + if (bitmask > 3) + bitmask >>= 2; + else + { + bitmask = 0xc0; + + cptr ++; + mptr ++; + yptr ++; + } + } + break; + + case 4 : + bitmask = 0xf0 >> (bitoffset & 7); + dither = Floyd4x4[y & 3]; + + for (x = xsize; x > 0; x --) + { + if ((*r0 & 15) > dither[x & 3]) + *cptr ^= (bitmask & OnPixels[*r0++]); + else + *cptr ^= (bitmask & OffPixels[*r0++]); + + if ((*r0 & 15) > dither[x & 3]) + *mptr ^= (bitmask & OnPixels[*r0++]); + else + *mptr ^= (bitmask & OffPixels[*r0++]); + + if ((*r0 & 15) > dither[x & 3]) + *yptr ^= (bitmask & OnPixels[*r0++]); + else + *yptr ^= (bitmask & OffPixels[*r0++]); + + if (bitmask == 0xf0) + bitmask = 0x0f; + else + { + bitmask = 0xf0; + + cptr ++; + mptr ++; + yptr ++; + } + } + break; + + case 8 : + for (x = xsize; x > 0; x --, r0 += 3, r1 += 3) + { + if (r0[0] == r1[0]) + *cptr++ = r0[0]; + else + *cptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize; + + if (r0[1] == r1[1]) + *mptr++ = r0[1]; + else + *mptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize; + + if (r0[2] == r1[2]) + *yptr++ = r0[2]; + else + *yptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize; + } + break; + } + break; + + case CUPS_ORDER_PLANAR : + switch (header->cupsBitsPerColor) + { + case 1 : + bitmask = 0x80 >> (bitoffset & 7); + dither = Floyd16x16[y & 15]; + + switch (z) + { + case 0 : + for (x = xsize; x > 0; x --, r0 += 3) + { + if (r0[0] > dither[x & 15]) + *ptr ^= bitmask; + + if (bitmask > 1) + bitmask >>= 1; + else + { + bitmask = 0x80; + ptr ++; + } + } + break; + + case 1 : + for (x = xsize; x > 0; x --, r0 += 3) + { + if (r0[1] > dither[x & 15]) + *ptr ^= bitmask; + + if (bitmask > 1) + bitmask >>= 1; + else + { + bitmask = 0x80; + ptr ++; + } + } + break; + + case 2 : + for (x = xsize; x > 0; x --, r0 += 3) + { + if (r0[2] > dither[x & 15]) + *ptr ^= bitmask; + + if (bitmask > 1) + bitmask >>= 1; + else + { + bitmask = 0x80; + ptr ++; + } + } + break; + } + break; + + case 2 : + bitmask = 0xc0 >> (bitoffset & 7); + dither = Floyd8x8[y & 7]; + r0 += z; + + for (x = xsize; x > 0; x --, r0 += 3) + { + if ((*r0 & 63) > dither[x & 7]) + *ptr ^= (bitmask & OnPixels[*r0]); + else + *ptr ^= (bitmask & OffPixels[*r0]); + + if (bitmask > 3) + bitmask >>= 2; + else + { + bitmask = 0xc0; + + ptr ++; + } + } + break; + + case 4 : + bitmask = 0xf0 >> (bitoffset & 7); + dither = Floyd4x4[y & 3]; + r0 += z; + + for (x = xsize; x > 0; x --, r0 += 3) + { + if ((*r0 & 15) > dither[x & 3]) + *ptr ^= (bitmask & OnPixels[*r0]); + else + *ptr ^= (bitmask & OffPixels[*r0]); + + if (bitmask == 0xf0) + bitmask = 0x0f; + else + { + bitmask = 0xf0; + + ptr ++; + } + } + break; + + case 8 : + r0 += z; + r1 += z; + + for (x = xsize; x > 0; x --, r0 += 3, r1 += 3) + { + if (*r0 == *r1) + *ptr++ = *r0; + else + *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize; + } + break; + } + break; + } +} + + +/* + * 'format_CMYK()' - Convert image data to CMYK. + */ + +static void +format_CMYK(cups_page_header_t *header, /* I - Page header */ + unsigned char *row, /* IO - Bitmap data for device */ + int y, /* I - Current row */ + int z, /* I - Current plane */ + int xsize, /* I - Width of image data */ + int ysize, /* I - Height of image data */ + int yerr0, /* I - Top Y error */ + int yerr1, /* I - Bottom Y error */ + ib_t *r0, /* I - Primary image data */ + ib_t *r1) /* I - Image data for interpolation */ +{ + ib_t *ptr, /* Pointer into row */ + *cptr, /* Pointer into cyan */ + *mptr, /* Pointer into magenta */ + *yptr, /* Pointer into yellow */ + *kptr, /* Pointer into black */ + bitmask; /* Current mask for pixel */ + int bitoffset; /* Current offset in line */ + int bandwidth; /* Width of a color band */ + int x, /* Current X coordinate on page */ + *dither; /* Pointer into dither array */ + + + if (Orientation == 1 || Orientation == 2) + bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize); + else + bitoffset = 0; + + ptr = row + bitoffset / 8; + bandwidth = header->cupsBytesPerLine / 4; + + switch (header->cupsColorOrder) + { + case CUPS_ORDER_CHUNKED : + switch (header->cupsBitsPerColor) + { + case 1 : + bitmask = 128 >> (bitoffset & 7); + dither = Floyd16x16[y & 15]; + + for (x = xsize ; x > 0; x --) + { + if (*r0++ > dither[x & 15]) + *ptr ^= bitmask; + bitmask >>= 1; + + if (*r0++ > dither[x & 15]) + *ptr ^= bitmask; + bitmask >>= 1; + + if (*r0++ > dither[x & 15]) + *ptr ^= bitmask; + bitmask >>= 1; + + if (*r0++ > dither[x & 15]) + *ptr ^= bitmask; + + if (bitmask > 1) + bitmask >>= 1; + else + { + bitmask = 128; + ptr ++; + } + } + break; + + case 2 : + dither = Floyd8x8[y & 7]; + + for (x = xsize ; x > 0; x --, r0 += 4) + { + if ((r0[0] & 63) > dither[x & 7]) + *ptr ^= (0xc0 & OnPixels[r0[0]]); + else + *ptr ^= (0xc0 & OffPixels[r0[0]]); + + if ((r0[1] & 63) > dither[x & 7]) + *ptr ^= (0x30 & OnPixels[r0[1]]); + else + *ptr ^= (0x30 & OffPixels[r0[1]]); + + if ((r0[2] & 63) > dither[x & 7]) + *ptr ^= (0x0c & OnPixels[r0[2]]); + else + *ptr ^= (0x0c & OffPixels[r0[2]]); + + if ((r0[3] & 63) > dither[x & 7]) + *ptr++ ^= (0x03 & OnPixels[r0[3]]); + else + *ptr++ ^= (0x03 & OffPixels[r0[3]]); + } + break; + + case 4 : + dither = Floyd4x4[y & 3]; + + for (x = xsize ; x > 0; x --, r0 += 4) + { + if ((r0[0] & 15) > dither[x & 3]) + *ptr ^= (0xf0 & OnPixels[r0[0]]); + else + *ptr ^= (0xf0 & OffPixels[r0[0]]); + + if ((r0[1] & 15) > dither[x & 3]) + *ptr++ ^= (0x0f & OnPixels[r0[1]]); + else + *ptr++ ^= (0x0f & OffPixels[r0[1]]); + + if ((r0[2] & 15) > dither[x & 3]) + *ptr ^= (0xf0 & OnPixels[r0[2]]); + else + *ptr ^= (0xf0 & OffPixels[r0[2]]); + + if ((r0[3] & 15) > dither[x & 3]) + *ptr++ ^= (0x0f & OnPixels[r0[3]]); + else + *ptr++ ^= (0x0f & OffPixels[r0[3]]); + } + break; + + case 8 : + for (x = xsize * 4; x > 0; x --, r0 ++, r1 ++) + if (*r0 == *r1) + *ptr++ = *r0; + else + *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize; + break; + } + break; + + case CUPS_ORDER_BANDED : + cptr = ptr; + mptr = ptr + bandwidth; + yptr = ptr + 2 * bandwidth; + kptr = ptr + 3 * bandwidth; + + switch (header->cupsBitsPerColor) + { + case 1 : + bitmask = 0x80 >> (bitoffset & 7); + dither = Floyd16x16[y & 15]; + + for (x = xsize; x > 0; x --) + { + if (*r0++ > dither[x & 15]) + *cptr ^= bitmask; + if (*r0++ > dither[x & 15]) + *mptr ^= bitmask; + if (*r0++ > dither[x & 15]) + *yptr ^= bitmask; + if (*r0++ > dither[x & 15]) + *kptr ^= bitmask; + + if (bitmask > 1) + bitmask >>= 1; + else + { + bitmask = 0x80; + cptr ++; + mptr ++; + yptr ++; + kptr ++; + } + } + break; + + case 2 : + bitmask = 0xc0 >> (bitoffset & 7); + dither = Floyd8x8[y & 7]; + + for (x = xsize; x > 0; x --) + { + if ((*r0 & 63) > dither[x & 7]) + *cptr ^= (bitmask & OnPixels[*r0++]); + else + *cptr ^= (bitmask & OffPixels[*r0++]); + + if ((*r0 & 63) > dither[x & 7]) + *mptr ^= (bitmask & OnPixels[*r0++]); + else + *mptr ^= (bitmask & OffPixels[*r0++]); + + if ((*r0 & 63) > dither[x & 7]) + *yptr ^= (bitmask & OnPixels[*r0++]); + else + *yptr ^= (bitmask & OffPixels[*r0++]); + + if ((*r0 & 63) > dither[x & 7]) + *kptr ^= (bitmask & OnPixels[*r0++]); + else + *kptr ^= (bitmask & OffPixels[*r0++]); + + if (bitmask > 3) + bitmask >>= 2; + else + { + bitmask = 0xc0; + + cptr ++; + mptr ++; + yptr ++; + kptr ++; + } + } + break; + + case 4 : + bitmask = 0xf0 >> (bitoffset & 7); + dither = Floyd4x4[y & 3]; + + for (x = xsize; x > 0; x --) + { + if ((*r0 & 15) > dither[x & 3]) + *cptr ^= (bitmask & OnPixels[*r0++]); + else + *cptr ^= (bitmask & OffPixels[*r0++]); + + if ((*r0 & 15) > dither[x & 3]) + *mptr ^= (bitmask & OnPixels[*r0++]); + else + *mptr ^= (bitmask & OffPixels[*r0++]); + + if ((*r0 & 15) > dither[x & 3]) + *yptr ^= (bitmask & OnPixels[*r0++]); + else + *yptr ^= (bitmask & OffPixels[*r0++]); + + if ((*r0 & 15) > dither[x & 3]) + *kptr ^= (bitmask & OnPixels[*r0++]); + else + *kptr ^= (bitmask & OffPixels[*r0++]); + + if (bitmask == 0xf0) + bitmask = 0x0f; + else + { + bitmask = 0xf0; + + cptr ++; + mptr ++; + yptr ++; + kptr ++; + } + } + break; + + case 8 : + for (x = xsize; x > 0; x --, r0 += 4, r1 += 4) + { + if (r0[0] == r1[0]) + *cptr++ = r0[0]; + else + *cptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize; + + if (r0[1] == r1[1]) + *mptr++ = r0[1]; + else + *mptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize; + + if (r0[2] == r1[2]) + *yptr++ = r0[2]; + else + *yptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize; + + if (r0[3] == r1[3]) + *kptr++ = r0[3]; + else + *kptr++ = (r0[3] * yerr0 + r1[3] * yerr1) / ysize; + } + break; + } + break; + + case CUPS_ORDER_PLANAR : + switch (header->cupsBitsPerColor) + { + case 1 : + bitmask = 0x80 >> (bitoffset & 7); + dither = Floyd16x16[y & 15]; + r0 += z; + + for (x = xsize; x > 0; x --, r0 += 4) + { + if (*r0 > dither[x & 15]) + *ptr ^= bitmask; + + if (bitmask > 1) + bitmask >>= 1; + else + { + bitmask = 0x80; + ptr ++; + } + } + break; + + case 2 : + bitmask = 0xc0 >> (bitoffset & 7); + dither = Floyd8x8[y & 7]; + r0 += z; + + for (x = xsize; x > 0; x --, r0 += 4) + { + if ((*r0 & 63) > dither[x & 7]) + *ptr ^= (bitmask & OnPixels[*r0]); + else + *ptr ^= (bitmask & OffPixels[*r0]); + + if (bitmask > 3) + bitmask >>= 2; + else + { + bitmask = 0xc0; + + ptr ++; + } + } + break; + + case 4 : + bitmask = 0xf0 >> (bitoffset & 7); + dither = Floyd4x4[y & 3]; + r0 += z; + + for (x = xsize; x > 0; x --, r0 += 4) + { + if ((*r0 & 15) > dither[x & 3]) + *ptr ^= (bitmask & OnPixels[*r0]); + else + *ptr ^= (bitmask & OffPixels[*r0]); + + if (bitmask == 0xf0) + bitmask = 0x0f; + else + { + bitmask = 0xf0; + + ptr ++; + } + } + break; + + case 8 : + r0 += z; + r1 += z; + + for (x = xsize; x > 0; x --, r0 += 4, r1 += 4) + { + if (*r0 == *r1) + *ptr++ = *r0; + else + *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize; + } + break; + } + break; + } +} + + +/* + * 'format_K()' - Convert image data to black. + */ + +static void +format_K(cups_page_header_t *header, /* I - Page header */ + unsigned char *row, /* IO - Bitmap data for device */ + int y, /* I - Current row */ + int z, /* I - Current plane */ + int xsize, /* I - Width of image data */ + int ysize, /* I - Height of image data */ + int yerr0, /* I - Top Y error */ + int yerr1, /* I - Bottom Y error */ + ib_t *r0, /* I - Primary image data */ + ib_t *r1) /* I - Image data for interpolation */ +{ + ib_t *ptr, /* Pointer into row */ + bitmask; /* Current mask for pixel */ + int bitoffset; /* Current offset in line */ + int x, /* Current X coordinate on page */ + *dither; /* Pointer into dither array */ + + + if (Orientation == 1 || Orientation == 2) + bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize); + else + bitoffset = 0; + + ptr = row + bitoffset / 8; + + switch (header->cupsBitsPerColor) + { + case 1 : + bitmask = 0x80 >> (bitoffset & 7); + dither = Floyd16x16[y & 15]; + + for (x = xsize; x > 0; x --) + { + if (*r0++ > dither[x & 15]) + *ptr ^= bitmask; + + if (bitmask > 1) + bitmask >>= 1; + else + { + bitmask = 0x80; + ptr ++; + } + } + break; + + case 2 : + bitmask = 0xc0 >> (bitoffset & 7); + dither = Floyd8x8[y & 7]; + + for (x = xsize; x > 0; x --) + { + if ((*r0 & 63) > dither[x & 7]) + *ptr ^= (bitmask & OnPixels[*r0++]); + else + *ptr ^= (bitmask & OffPixels[*r0++]); + + if (bitmask > 3) + bitmask >>= 2; + else + { + bitmask = 0xc0; + + ptr ++; + } + } + break; + + case 4 : + bitmask = 0xf0 >> (bitoffset & 7); + dither = Floyd4x4[y & 3]; + + for (x = xsize; x > 0; x --) + { + if ((*r0 & 15) > dither[x & 3]) + *ptr ^= (bitmask & OnPixels[*r0++]); + else + *ptr ^= (bitmask & OffPixels[*r0++]); + + if (bitmask == 0xf0) + bitmask = 0x0f; + else + { + bitmask = 0xf0; + + ptr ++; + } + } + break; + + case 8 : + for (x = xsize; x > 0; x --, r0 ++, r1 ++) + { + if (*r0 == *r1) + *ptr++ = *r0; + else + *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize; + } + break; + } +} + + +/* + * 'format_KCMY()' - Convert image data to KCMY. + */ + +static void +format_KCMY(cups_page_header_t *header, /* I - Page header */ + unsigned char *row, /* IO - Bitmap data for device */ + int y, /* I - Current row */ + int z, /* I - Current plane */ + int xsize, /* I - Width of image data */ + int ysize, /* I - Height of image data */ + int yerr0, /* I - Top Y error */ + int yerr1, /* I - Bottom Y error */ + ib_t *r0, /* I - Primary image data */ + ib_t *r1) /* I - Image data for interpolation */ +{ + ib_t *ptr, /* Pointer into row */ + *cptr, /* Pointer into cyan */ + *mptr, /* Pointer into magenta */ + *yptr, /* Pointer into yellow */ + *kptr, /* Pointer into black */ + bitmask; /* Current mask for pixel */ + int bitoffset; /* Current offset in line */ + int bandwidth; /* Width of a color band */ + int x, /* Current X coordinate on page */ + *dither; /* Pointer into dither array */ + + + if (Orientation == 1 || Orientation == 2) + bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize); + else + bitoffset = 0; + + ptr = row + bitoffset / 8; + bandwidth = header->cupsBytesPerLine / 4; + + switch (header->cupsColorOrder) + { + case CUPS_ORDER_CHUNKED : + switch (header->cupsBitsPerColor) + { + case 1 : + bitmask = 128 >> (bitoffset & 7); + dither = Floyd16x16[y & 15]; + + for (x = xsize ; x > 0; x --, r0 += 4) + { + if (r0[3] > dither[x & 15]) + *ptr ^= bitmask; + bitmask >>= 1; + + if (r0[0] > dither[x & 15]) + *ptr ^= bitmask; + bitmask >>= 1; + + if (r0[1] > dither[x & 15]) + *ptr ^= bitmask; + bitmask >>= 1; + + if (r0[2] > dither[x & 15]) + *ptr ^= bitmask; + + if (bitmask > 1) + bitmask >>= 1; + else + { + bitmask = 128; + ptr ++; + } + } + break; + + case 2 : + dither = Floyd8x8[y & 7]; + + for (x = xsize ; x > 0; x --, r0 += 4) + { + if ((r0[3] & 63) > dither[x & 7]) + *ptr ^= (0xc0 & OnPixels[r0[3]]); + else + *ptr ^= (0xc0 & OffPixels[r0[3]]); + + if ((r0[0] & 63) > dither[x & 7]) + *ptr ^= (0x30 & OnPixels[r0[0]]); + else + *ptr ^= (0x30 & OffPixels[r0[0]]); + + if ((r0[1] & 63) > dither[x & 7]) + *ptr ^= (0x0c & OnPixels[r0[1]]); + else + *ptr ^= (0x0c & OffPixels[r0[1]]); + + if ((r0[2] & 63) > dither[x & 7]) + *ptr++ ^= (0x03 & OnPixels[r0[2]]); + else + *ptr++ ^= (0x03 & OffPixels[r0[2]]); + } + break; + + case 4 : + dither = Floyd4x4[y & 3]; + + for (x = xsize ; x > 0; x --, r0 += 4) + { + if ((r0[3] & 15) > dither[x & 3]) + *ptr ^= (0xf0 & OnPixels[r0[3]]); + else + *ptr ^= (0xf0 & OffPixels[r0[3]]); + + if ((r0[0] & 15) > dither[x & 3]) + *ptr++ ^= (0x0f & OnPixels[r0[0]]); + else + *ptr++ ^= (0x0f & OffPixels[r0[0]]); + + if ((r0[1] & 15) > dither[x & 3]) + *ptr ^= (0xf0 & OnPixels[r0[1]]); + else + *ptr ^= (0xf0 & OffPixels[r0[1]]); + + if ((r0[2] & 15) > dither[x & 3]) + *ptr++ ^= (0x0f & OnPixels[r0[2]]); + else + *ptr++ ^= (0x0f & OffPixels[r0[2]]); + } + break; + + case 8 : + for (x = xsize; x > 0; x --, r0 += 4, r1 += 4) + { + if (r0[3] == r1[3]) + *ptr++ = r0[3]; + else + *ptr++ = (r0[3] * yerr0 + r1[3] * yerr1) / ysize; + + if (r0[0] == r1[0]) + *ptr++ = r0[0]; + else + *ptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize; + + if (r0[1] == r1[1]) + *ptr++ = r0[1]; + else + *ptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize; + + if (r0[2] == r1[2]) + *ptr++ = r0[2]; + else + *ptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize; + } + break; + } + break; + + case CUPS_ORDER_BANDED : + kptr = ptr; + cptr = ptr + bandwidth; + mptr = ptr + 2 * bandwidth; + yptr = ptr + 3 * bandwidth; + + switch (header->cupsBitsPerColor) + { + case 1 : + bitmask = 0x80 >> (bitoffset & 7); + dither = Floyd16x16[y & 15]; + + for (x = xsize; x > 0; x --) + { + if (*r0++ > dither[x & 15]) + *cptr ^= bitmask; + if (*r0++ > dither[x & 15]) + *mptr ^= bitmask; + if (*r0++ > dither[x & 15]) + *yptr ^= bitmask; + if (*r0++ > dither[x & 15]) + *kptr ^= bitmask; + + if (bitmask > 1) + bitmask >>= 1; + else + { + bitmask = 0x80; + cptr ++; + mptr ++; + yptr ++; + kptr ++; + } + } + break; + + case 2 : + bitmask = 0xc0 >> (bitoffset & 7); + dither = Floyd8x8[y & 7]; + + for (x = xsize; x > 0; x --) + { + if ((*r0 & 63) > dither[x & 7]) + *cptr ^= (bitmask & OnPixels[*r0++]); + else + *cptr ^= (bitmask & OffPixels[*r0++]); + + if ((*r0 & 63) > dither[x & 7]) + *mptr ^= (bitmask & OnPixels[*r0++]); + else + *mptr ^= (bitmask & OffPixels[*r0++]); + + if ((*r0 & 63) > dither[x & 7]) + *yptr ^= (bitmask & OnPixels[*r0++]); + else + *yptr ^= (bitmask & OffPixels[*r0++]); + + if ((*r0 & 63) > dither[x & 7]) + *kptr ^= (bitmask & OnPixels[*r0++]); + else + *kptr ^= (bitmask & OffPixels[*r0++]); + + if (bitmask > 3) + bitmask >>= 2; + else + { + bitmask = 0xc0; + + cptr ++; + mptr ++; + yptr ++; + kptr ++; + } + } + break; + + case 4 : + bitmask = 0xf0 >> (bitoffset & 7); + dither = Floyd4x4[y & 3]; + + for (x = xsize; x > 0; x --) + { + if ((*r0 & 15) > dither[x & 3]) + *cptr ^= (bitmask & OnPixels[*r0++]); + else + *cptr ^= (bitmask & OffPixels[*r0++]); + + if ((*r0 & 15) > dither[x & 3]) + *mptr ^= (bitmask & OnPixels[*r0++]); + else + *mptr ^= (bitmask & OffPixels[*r0++]); + + if ((*r0 & 15) > dither[x & 3]) + *yptr ^= (bitmask & OnPixels[*r0++]); + else + *yptr ^= (bitmask & OffPixels[*r0++]); + + if ((*r0 & 15) > dither[x & 3]) + *kptr ^= (bitmask & OnPixels[*r0++]); + else + *kptr ^= (bitmask & OffPixels[*r0++]); + + if (bitmask == 0xf0) + bitmask = 0x0f; + else + { + bitmask = 0xf0; + + cptr ++; + mptr ++; + yptr ++; + kptr ++; + } + } + break; + + case 8 : + for (x = xsize; x > 0; x --, r0 += 4, r1 += 4) + { + if (r0[0] == r1[0]) + *cptr++ = r0[0]; + else + *cptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize; + + if (r0[1] == r1[1]) + *mptr++ = r0[1]; + else + *mptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize; + + if (r0[2] == r1[2]) + *yptr++ = r0[2]; + else + *yptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize; + + if (r0[3] == r1[3]) + *kptr++ = r0[3]; + else + *kptr++ = (r0[3] * yerr0 + r1[3] * yerr1) / ysize; + } + break; + } + break; + + case CUPS_ORDER_PLANAR : + switch (header->cupsBitsPerColor) + { + case 1 : + bitmask = 0x80 >> (bitoffset & 7); + dither = Floyd16x16[y & 15]; + if (z == 0) + r0 += 3; + else + r0 += z - 1; + + for (x = xsize; x > 0; x --, r0 += 4) + { + if (*r0 > dither[x & 15]) + *ptr ^= bitmask; + + if (bitmask > 1) + bitmask >>= 1; + else + { + bitmask = 0x80; + ptr ++; + } + } + break; + + case 2 : + bitmask = 0xc0 >> (bitoffset & 7); + dither = Floyd8x8[y & 7]; + if (z == 0) + r0 += 3; + else + r0 += z - 1; + + for (x = xsize; x > 0; x --, r0 += 4) + { + if ((*r0 & 63) > dither[x & 7]) + *ptr ^= (bitmask & OnPixels[*r0]); + else + *ptr ^= (bitmask & OffPixels[*r0]); + + if (bitmask > 3) + bitmask >>= 2; + else + { + bitmask = 0xc0; + + ptr ++; + } + } + break; + + case 4 : + bitmask = 0xf0 >> (bitoffset & 7); + dither = Floyd4x4[y & 3]; + if (z == 0) + r0 += 3; + else + r0 += z - 1; + + for (x = xsize; x > 0; x --, r0 += 4) + { + if ((*r0 & 15) > dither[x & 3]) + *ptr ^= (bitmask & OnPixels[*r0]); + else + *ptr ^= (bitmask & OffPixels[*r0]); + + if (bitmask == 0xf0) + bitmask = 0x0f; + else + { + bitmask = 0xf0; + + ptr ++; + } + } + break; + + case 8 : + if (z == 0) + { + r0 += 3; + r1 += 3; + } + else + { + r0 += z - 1; + r1 += z - 1; + } + + for (x = xsize; x > 0; x --, r0 += 4, r1 += 4) + { + if (*r0 == *r1) + *ptr++ = *r0; + else + *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize; + } + break; + } + break; + } +} + + +/* + * 'format_KCMYcm()' - Convert image data to KCMYcm. + */ + +static void +format_KCMYcm(cups_page_header_t *header,/* I - Page header */ + unsigned char *row, /* IO - Bitmap data for device */ + int y, /* I - Current row */ + int z, /* I - Current plane */ + int xsize, /* I - Width of image data */ + int ysize, /* I - Height of image data */ + int yerr0, /* I - Top Y error */ + int yerr1, /* I - Bottom Y error */ + ib_t *r0, /* I - Primary image data */ + ib_t *r1) /* I - Image data for interpolation */ +{ + int pc, pm, py, pk; /* Cyan, magenta, yellow, and black values */ + ib_t *ptr, /* Pointer into row */ + *cptr, /* Pointer into cyan */ + *mptr, /* Pointer into magenta */ + *yptr, /* Pointer into yellow */ + *kptr, /* Pointer into black */ + *lcptr, /* Pointer into light cyan */ + *lmptr, /* Pointer into light magenta */ + bitmask; /* Current mask for pixel */ + int bitoffset; /* Current offset in line */ + int bandwidth; /* Width of a color band */ + int x, /* Current X coordinate on page */ + *dither; /* Pointer into dither array */ + + + if (Orientation == 1 || Orientation == 2) + bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize); + else + bitoffset = 0; + + ptr = row + bitoffset / 8; + if (header->cupsBitsPerColor == 1) + bandwidth = header->cupsBytesPerLine / 6; + else + bandwidth = header->cupsBytesPerLine / 4; + + switch (header->cupsColorOrder) + { + case CUPS_ORDER_CHUNKED : + switch (header->cupsBitsPerColor) + { + case 1 : + dither = Floyd16x16[y & 15]; + + for (x = xsize ; x > 0; x --) + { + pc = *r0++ > dither[x & 15]; + pm = *r0++ > dither[x & 15]; + py = *r0++ > dither[x & 15]; + pk = *r0++ > dither[x & 15]; + + if (pk) + *ptr++ ^= 32; /* Black */ + else if (pc && pm) + *ptr++ ^= 3; /* Blue (light cyan + light magenta) */ + else if (pc && py) + *ptr++ ^= 6; /* Green (light cyan + yellow) */ + else if (pm && py) + *ptr++ ^= 12; /* Red (magenta + yellow) */ + else if (pc) + *ptr++ ^= 16; + else if (pm) + *ptr++ ^= 8; + else if (py) + *ptr++ ^= 4; + } + break; + + case 8 : + for (x = xsize; x > 0; x --, r0 += 4, r1 += 4) + { + if (r0[3] == r1[3]) + *ptr++ = r0[3]; + else + *ptr++ = (r0[3] * yerr0 + r1[3] * yerr1) / ysize; + + if (r0[0] == r1[0]) + *ptr++ = r0[0]; + else + *ptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize; + + if (r0[1] == r1[1]) + *ptr++ = r0[1]; + else + *ptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize; + + if (r0[2] == r1[2]) + *ptr++ = r0[2]; + else + *ptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize; + } + break; + } + break; + + case CUPS_ORDER_BANDED : + kptr = ptr; + cptr = ptr + bandwidth; + mptr = ptr + 2 * bandwidth; + yptr = ptr + 3 * bandwidth; + lcptr = ptr + 4 * bandwidth; + lmptr = ptr + 5 * bandwidth; + + switch (header->cupsBitsPerColor) + { + case 1 : + bitmask = 0x80 >> (bitoffset & 7); + dither = Floyd16x16[y & 15]; + + for (x = xsize; x > 0; x --) + { + pc = *r0++ > dither[x & 15]; + pm = *r0++ > dither[x & 15]; + py = *r0++ > dither[x & 15]; + pk = *r0++ > dither[x & 15]; + + if (pk) + *kptr ^= bitmask; /* Black */ + else if (pc && pm) + { + *lcptr ^= bitmask; /* Blue (light cyan + light magenta) */ + *lmptr ^= bitmask; + } + else if (pc && py) + { + *lcptr ^= bitmask; /* Green (light cyan + yellow) */ + *yptr ^= bitmask; + } + else if (pm && py) + { + *mptr ^= bitmask; /* Red (magenta + yellow) */ + *yptr ^= bitmask; + } + else if (pc) + *cptr ^= bitmask; + else if (pm) + *mptr ^= bitmask; + else if (py) + *yptr ^= bitmask; + + if (bitmask > 1) + bitmask >>= 1; + else + { + bitmask = 0x80; + cptr ++; + mptr ++; + yptr ++; + kptr ++; + lcptr ++; + lmptr ++; + } + } + break; + + case 8 : + for (x = xsize; x > 0; x --, r0 += 4, r1 += 4) + { + if (r0[0] == r1[0]) + *cptr++ = r0[0]; + else + *cptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize; + + if (r0[1] == r1[1]) + *mptr++ = r0[1]; + else + *mptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize; + + if (r0[2] == r1[2]) + *yptr++ = r0[2]; + else + *yptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize; + + if (r0[3] == r1[3]) + *kptr++ = r0[3]; + else + *kptr++ = (r0[3] * yerr0 + r1[3] * yerr1) / ysize; + } + break; + } + break; + + case CUPS_ORDER_PLANAR : + switch (header->cupsBitsPerColor) + { + case 1 : + bitmask = 0x80 >> (bitoffset & 7); + dither = Floyd16x16[y & 15]; + + switch (z) + { + case 0 : + for (x = xsize; x > 0; x --, r0 += 4) + { + if (r0[3] > dither[x & 15]) + *ptr ^= bitmask; + + if (bitmask > 1) + bitmask >>= 1; + else + { + bitmask = 0x80; + ptr ++; + } + } + break; + + case 1 : + for (x = xsize; x > 0; x --, r0 += 4) + { + if (r0[0] > dither[x & 15] && + r0[1] < dither[x & 15] && + r0[2] < dither[x & 15]) + *ptr ^= bitmask; + + if (bitmask > 1) + bitmask >>= 1; + else + { + bitmask = 0x80; + ptr ++; + } + } + break; + + case 2 : + for (x = xsize; x > 0; x --, r0 += 4) + { + if (r0[1] > dither[x & 15] && + (r0[0] < dither[x & 15] || + r0[2] > dither[x & 15])) + *ptr ^= bitmask; + + if (bitmask > 1) + bitmask >>= 1; + else + { + bitmask = 0x80; + ptr ++; + } + } + break; + + case 3 : + for (x = xsize; x > 0; x --, r0 += 4) + { + if (r0[2] > dither[x & 15] && + (r0[0] < dither[x & 15] || + r0[1] < dither[x & 15])) + *ptr ^= bitmask; + + if (bitmask > 1) + bitmask >>= 1; + else + { + bitmask = 0x80; + ptr ++; + } + } + break; + + case 4 : + for (x = xsize; x > 0; x --, r0 += 4) + { + if (r0[0] > dither[x & 15] && + r0[1] < dither[x & 15] && + r0[2] > dither[x & 15]) + *ptr ^= bitmask; + + if (bitmask > 1) + bitmask >>= 1; + else + { + bitmask = 0x80; + ptr ++; + } + } + break; + + case 5 : + for (x = xsize; x > 0; x --, r0 += 4) + { + if (r0[0] > dither[x & 15] && + r0[1] > dither[x & 15] && + r0[2] < dither[x & 15]) + *ptr ^= bitmask; + + if (bitmask > 1) + bitmask >>= 1; + else + { + bitmask = 0x80; + ptr ++; + } + } + break; + } + break; + + case 8 : + if (z == 0) + { + r0 += 3; + r1 += 3; + } + else + { + r0 += z - 1; + r1 += z - 1; + } + + for (x = xsize; x > 0; x --, r0 += 4, r1 += 4) + { + if (*r0 == *r1) + *ptr++ = *r0; + else + *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize; + } + break; + } + break; + } +} + + +/* + * 'format_RGBA()' - Convert image data to RGBA. + */ + +static void +format_RGBA(cups_page_header_t *header, /* I - Page header */ + unsigned char *row, /* IO - Bitmap data for device */ + int y, /* I - Current row */ + int z, /* I - Current plane */ + int xsize, /* I - Width of image data */ + int ysize, /* I - Height of image data */ + int yerr0, /* I - Top Y error */ + int yerr1, /* I - Bottom Y error */ + ib_t *r0, /* I - Primary image data */ + ib_t *r1) /* I - Image data for interpolation */ +{ + ib_t *ptr, /* Pointer into row */ + *cptr, /* Pointer into cyan */ + *mptr, /* Pointer into magenta */ + *yptr, /* Pointer into yellow */ + bitmask; /* Current mask for pixel */ + int bitoffset; /* Current offset in line */ + int bandwidth; /* Width of a color band */ + int x, /* Current X coordinate on page */ + *dither; /* Pointer into dither array */ + + + if (Orientation == 1 || Orientation == 2) + bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize); + else + bitoffset = 0; + + ptr = row + bitoffset / 8; + bandwidth = header->cupsBytesPerLine / 4; + + switch (header->cupsColorOrder) + { + case CUPS_ORDER_CHUNKED : + switch (header->cupsBitsPerColor) + { + case 1 : + bitmask = 128 >> (bitoffset & 7); + dither = Floyd16x16[y & 15]; + + for (x = xsize ; x > 0; x --) + { + if (*r0++ > dither[x & 15]) + *ptr ^= bitmask; + bitmask >>= 1; + + if (*r0++ > dither[x & 15]) + *ptr ^= bitmask; + bitmask >>= 1; + + if (*r0++ > dither[x & 15]) + *ptr ^= bitmask; + + if (bitmask > 2) + { + *ptr ^= 16; + bitmask >>= 2; + } + else + { + bitmask = 128; + *ptr++ ^= 1; + } + } + break; + + case 2 : + dither = Floyd8x8[y & 7]; + + for (x = xsize ; x > 0; x --, r0 += 3) + { + if ((r0[0] & 63) > dither[x & 7]) + *ptr ^= (0xc0 & OnPixels[r0[0]]); + else + *ptr ^= (0xc0 & OffPixels[r0[0]]); + + if ((r0[1] & 63) > dither[x & 7]) + *ptr ^= (0x30 & OnPixels[r0[1]]); + else + *ptr ^= (0x30 & OffPixels[r0[1]]); + + if ((r0[2] & 63) > dither[x & 7]) + *ptr ^= (0x0c & OnPixels[r0[2]]); + else + *ptr ^= (0x0c & OffPixels[r0[2]]); + + *ptr++ ^= 0x03; + } + break; + + case 4 : + dither = Floyd4x4[y & 3]; + + for (x = xsize ; x > 0; x --, r0 += 3) + { + if ((r0[0] & 15) > dither[x & 3]) + *ptr ^= (0xf0 & OnPixels[r0[0]]); + else + *ptr ^= (0xf0 & OffPixels[r0[0]]); + + if ((r0[1] & 15) > dither[x & 3]) + *ptr++ ^= (0x0f & OnPixels[r0[1]]); + else + *ptr++ ^= (0x0f & OffPixels[r0[1]]); + + if ((r0[2] & 15) > dither[x & 3]) + *ptr ^= (0xf0 & OnPixels[r0[2]]); + else + *ptr ^= (0xf0 & OffPixels[r0[2]]); + + *ptr++ ^= 0x0f; + } + break; + + case 8 : + for (x = xsize; x > 0; x --, r0 += 3, r1 += 3) + { + if (r0[0] == r1[0]) + *ptr++ = r0[0]; + else + *ptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize; + + if (r0[1] == r1[1]) + *ptr++ = r0[1]; + else + *ptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize; + + if (r0[2] == r1[2]) + *ptr++ = r0[2]; + else + *ptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize; + + *ptr++ = 255; + } + break; + } + break; + + case CUPS_ORDER_BANDED : + cptr = ptr; + mptr = ptr + bandwidth; + yptr = ptr + 2 * bandwidth; + + memset(ptr + 3 * bandwidth, 255, bandwidth); + + switch (header->cupsBitsPerColor) + { + case 1 : + bitmask = 0x80 >> (bitoffset & 7); + dither = Floyd16x16[y & 15]; + + for (x = xsize; x > 0; x --) + { + if (*r0++ > dither[x & 15]) + *cptr ^= bitmask; + if (*r0++ > dither[x & 15]) + *mptr ^= bitmask; + if (*r0++ > dither[x & 15]) + *yptr ^= bitmask; + + if (bitmask > 1) + bitmask >>= 1; + else + { + bitmask = 0x80; + cptr ++; + mptr ++; + yptr ++; + } + } + break; + + case 2 : + bitmask = 0xc0 >> (bitoffset & 7); + dither = Floyd8x8[y & 7]; + + for (x = xsize; x > 0; x --) + { + if ((*r0 & 63) > dither[x & 7]) + *cptr ^= (bitmask & OnPixels[*r0++]); + else + *cptr ^= (bitmask & OffPixels[*r0++]); + + if ((*r0 & 63) > dither[x & 7]) + *mptr ^= (bitmask & OnPixels[*r0++]); + else + *mptr ^= (bitmask & OffPixels[*r0++]); + + if ((*r0 & 63) > dither[x & 7]) + *yptr ^= (bitmask & OnPixels[*r0++]); + else + *yptr ^= (bitmask & OffPixels[*r0++]); + + if (bitmask > 3) + bitmask >>= 2; + else + { + bitmask = 0xc0; + + cptr ++; + mptr ++; + yptr ++; + } + } + break; + + case 4 : + bitmask = 0xf0 >> (bitoffset & 7); + dither = Floyd4x4[y & 3]; + + for (x = xsize; x > 0; x --) + { + if ((*r0 & 15) > dither[x & 3]) + *cptr ^= (bitmask & OnPixels[*r0++]); + else + *cptr ^= (bitmask & OffPixels[*r0++]); + + if ((*r0 & 15) > dither[x & 3]) + *mptr ^= (bitmask & OnPixels[*r0++]); + else + *mptr ^= (bitmask & OffPixels[*r0++]); + + if ((*r0 & 15) > dither[x & 3]) + *yptr ^= (bitmask & OnPixels[*r0++]); + else + *yptr ^= (bitmask & OffPixels[*r0++]); + + if (bitmask == 0xf0) + bitmask = 0x0f; + else + { + bitmask = 0xf0; + + cptr ++; + mptr ++; + yptr ++; + } + } + break; + + case 8 : + for (x = xsize; x > 0; x --, r0 += 3, r1 += 3) + { + if (r0[0] == r1[0]) + *cptr++ = r0[0]; + else + *cptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize; + + if (r0[1] == r1[1]) + *mptr++ = r0[1]; + else + *mptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize; + + if (r0[2] == r1[2]) + *yptr++ = r0[2]; + else + *yptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize; + } + break; + } + break; + + case CUPS_ORDER_PLANAR : + if (z == 3) + { + memset(row, 255, header->cupsBytesPerLine); + break; + } + + switch (header->cupsBitsPerColor) + { + case 1 : + bitmask = 0x80 >> (bitoffset & 7); + dither = Floyd16x16[y & 15]; + + switch (z) + { + case 0 : + for (x = xsize; x > 0; x --, r0 += 3) + { + if (r0[0] > dither[x & 15]) + *ptr ^= bitmask; + + if (bitmask > 1) + bitmask >>= 1; + else + { + bitmask = 0x80; + ptr ++; + } + } + break; + + case 1 : + for (x = xsize; x > 0; x --, r0 += 3) + { + if (r0[1] > dither[x & 15]) + *ptr ^= bitmask; + + if (bitmask > 1) + bitmask >>= 1; + else + { + bitmask = 0x80; + ptr ++; + } + } + break; + + case 2 : + for (x = xsize; x > 0; x --, r0 += 3) + { + if (r0[2] > dither[x & 15]) + *ptr ^= bitmask; + + if (bitmask > 1) + bitmask >>= 1; + else + { + bitmask = 0x80; + ptr ++; + } + } + break; + } + break; + + case 2 : + bitmask = 0xc0 >> (bitoffset & 7); + dither = Floyd8x8[y & 7]; + r0 += z; + + for (x = xsize; x > 0; x --, r0 += 3) + { + if ((*r0 & 63) > dither[x & 7]) + *ptr ^= (bitmask & OnPixels[*r0]); + else + *ptr ^= (bitmask & OffPixels[*r0]); + + if (bitmask > 3) + bitmask >>= 2; + else + { + bitmask = 0xc0; + + ptr ++; + } + } + break; + + case 4 : + bitmask = 0xf0 >> (bitoffset & 7); + dither = Floyd4x4[y & 3]; + r0 += z; + + for (x = xsize; x > 0; x --, r0 += 3) + { + if ((*r0 & 15) > dither[x & 3]) + *ptr ^= (bitmask & OnPixels[*r0]); + else + *ptr ^= (bitmask & OffPixels[*r0]); + + if (bitmask == 0xf0) + bitmask = 0x0f; + else + { + bitmask = 0xf0; + + ptr ++; + } + } + break; + + case 8 : + r0 += z; + r1 += z; + + for (x = xsize; x > 0; x --, r0 += 3, r1 += 3) + { + if (*r0 == *r1) + *ptr++ = *r0; + else + *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize; + } + break; + } + break; + } +} + + +/* + * 'format_W()' - Convert image data to luminance. + */ + +static void +format_W(cups_page_header_t *header, /* I - Page header */ + unsigned char *row, /* IO - Bitmap data for device */ + int y, /* I - Current row */ + int z, /* I - Current plane */ + int xsize, /* I - Width of image data */ + int ysize, /* I - Height of image data */ + int yerr0, /* I - Top Y error */ + int yerr1, /* I - Bottom Y error */ + ib_t *r0, /* I - Primary image data */ + ib_t *r1) /* I - Image data for interpolation */ +{ + ib_t *ptr, /* Pointer into row */ + bitmask; /* Current mask for pixel */ + int bitoffset; /* Current offset in line */ + int x, /* Current X coordinate on page */ + *dither; /* Pointer into dither array */ + + + if (Orientation == 1 || Orientation == 2) + bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize); + else + bitoffset = 0; + + ptr = row + bitoffset / 8; + + switch (header->cupsBitsPerColor) + { + case 1 : + bitmask = 0x80 >> (bitoffset & 7); + dither = Floyd16x16[y & 15]; + + for (x = xsize; x > 0; x --) + { + if (*r0++ > dither[x & 15]) + *ptr ^= bitmask; + + if (bitmask > 1) + bitmask >>= 1; + else + { + bitmask = 0x80; + ptr ++; + } + } + break; + + case 2 : + bitmask = 0xc0 >> (bitoffset & 7); + dither = Floyd8x8[y & 7]; + + for (x = xsize; x > 0; x --) + { + if ((*r0 & 63) > dither[x & 7]) + *ptr ^= (bitmask & OnPixels[*r0++]); + else + *ptr ^= (bitmask & OffPixels[*r0++]); + + if (bitmask > 3) + bitmask >>= 2; + else + { + bitmask = 0xc0; + + ptr ++; + } + } + break; + + case 4 : + bitmask = 0xf0 >> (bitoffset & 7); + dither = Floyd4x4[y & 3]; + + for (x = xsize; x > 0; x --) + { + if ((*r0 & 15) > dither[x & 3]) + *ptr ^= (bitmask & OnPixels[*r0++]); + else + *ptr ^= (bitmask & OffPixels[*r0++]); + + if (bitmask == 0xf0) + bitmask = 0x0f; + else + { + bitmask = 0xf0; + + ptr ++; + } + } + break; + + case 8 : + for (x = xsize; x > 0; x --, r0 ++, r1 ++) + { + if (*r0 == *r1) + *ptr++ = *r0; + else + *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize; + } + break; + } +} + + +/* + * 'format_YMC()' - Convert image data to YMC. + */ + +static void +format_YMC(cups_page_header_t *header, /* I - Page header */ + unsigned char *row, /* IO - Bitmap data for device */ + int y, /* I - Current row */ + int z, /* I - Current plane */ + int xsize, /* I - Width of image data */ + int ysize, /* I - Height of image data */ + int yerr0, /* I - Top Y error */ + int yerr1, /* I - Bottom Y error */ + ib_t *r0, /* I - Primary image data */ + ib_t *r1) /* I - Image data for interpolation */ +{ + ib_t *ptr, /* Pointer into row */ + *cptr, /* Pointer into cyan */ + *mptr, /* Pointer into magenta */ + *yptr, /* Pointer into yellow */ + bitmask; /* Current mask for pixel */ + int bitoffset; /* Current offset in line */ + int bandwidth; /* Width of a color band */ + int x, /* Current X coordinate on page */ + *dither; /* Pointer into dither array */ + + + if (Orientation == 1 || Orientation == 2) + bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize); + else + bitoffset = 0; + + ptr = row + bitoffset / 8; + bandwidth = header->cupsBytesPerLine / 4; + + switch (header->cupsColorOrder) + { + case CUPS_ORDER_CHUNKED : + switch (header->cupsBitsPerColor) + { + case 1 : + bitmask = 64 >> (bitoffset & 7); + dither = Floyd16x16[y & 15]; + + for (x = xsize ; x > 0; x --, r0 += 3) + { + if (r0[2] > dither[x & 15]) + *ptr ^= bitmask; + bitmask >>= 1; + + if (r0[1] > dither[x & 15]) + *ptr ^= bitmask; + bitmask >>= 1; + + if (r0[0] > dither[x & 15]) + *ptr ^= bitmask; + + if (bitmask > 1) + bitmask >>= 2; + else + { + bitmask = 64; + ptr ++; + } + } + break; + + case 2 : + dither = Floyd8x8[y & 7]; + + for (x = xsize ; x > 0; x --, r0 += 3) + { + if ((r0[2] & 63) > dither[x & 7]) + *ptr ^= (0x30 & OnPixels[r0[2]]); + else + *ptr ^= (0x30 & OffPixels[r0[2]]); + + if ((r0[1] & 63) > dither[x & 7]) + *ptr ^= (0x0c & OnPixels[r0[1]]); + else + *ptr ^= (0x0c & OffPixels[r0[1]]); + + if ((r0[0] & 63) > dither[x & 7]) + *ptr++ ^= (0x03 & OnPixels[r0[0]]); + else + *ptr++ ^= (0x03 & OffPixels[r0[0]]); + } + break; + + case 4 : + dither = Floyd4x4[y & 3]; + + for (x = xsize ; x > 0; x --, r0 += 3) + { + if ((r0[2] & 15) > dither[x & 3]) + *ptr++ ^= (0x0f & OnPixels[r0[2]]); + else + *ptr++ ^= (0x0f & OffPixels[r0[2]]); + + if ((r0[1] & 15) > dither[x & 3]) + *ptr ^= (0xf0 & OnPixels[r0[1]]); + else + *ptr ^= (0xf0 & OffPixels[r0[1]]); + + if ((r0[0] & 15) > dither[x & 3]) + *ptr++ ^= (0x0f & OnPixels[r0[0]]); + else + *ptr++ ^= (0x0f & OffPixels[r0[0]]); + } + break; + + case 8 : + for (x = xsize; x > 0; x --, r0 += 3, r1 += 3) + { + if (r0[2] == r1[2]) + *ptr++ = r0[2]; + else + *ptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize; + + if (r0[1] == r1[1]) + *ptr++ = r0[1]; + else + *ptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize; + + if (r0[0] == r1[0]) + *ptr++ = r0[0]; + else + *ptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize; + } + break; + } + break; + + case CUPS_ORDER_BANDED : + yptr = ptr; + mptr = ptr + bandwidth; + cptr = ptr + 2 * bandwidth; + + switch (header->cupsBitsPerColor) + { + case 1 : + bitmask = 0x80 >> (bitoffset & 7); + dither = Floyd16x16[y & 15]; + + for (x = xsize; x > 0; x --) + { + if (*r0++ > dither[x & 15]) + *cptr ^= bitmask; + if (*r0++ > dither[x & 15]) + *mptr ^= bitmask; + if (*r0++ > dither[x & 15]) + *yptr ^= bitmask; + + if (bitmask > 1) + bitmask >>= 1; + else + { + bitmask = 0x80; + cptr ++; + mptr ++; + yptr ++; + } + } + break; + + case 2 : + bitmask = 0xc0 >> (bitoffset & 7); + dither = Floyd8x8[y & 7]; + + for (x = xsize; x > 0; x --) + { + if ((*r0 & 63) > dither[x & 7]) + *cptr ^= (bitmask & OnPixels[*r0++]); + else + *cptr ^= (bitmask & OffPixels[*r0++]); + + if ((*r0 & 63) > dither[x & 7]) + *mptr ^= (bitmask & OnPixels[*r0++]); + else + *mptr ^= (bitmask & OffPixels[*r0++]); + + if ((*r0 & 63) > dither[x & 7]) + *yptr ^= (bitmask & OnPixels[*r0++]); + else + *yptr ^= (bitmask & OffPixels[*r0++]); + + if (bitmask > 3) + bitmask >>= 2; + else + { + bitmask = 0xc0; + + cptr ++; + mptr ++; + yptr ++; + } + } + break; + + case 4 : + bitmask = 0xf0 >> (bitoffset & 7); + dither = Floyd4x4[y & 3]; + + for (x = xsize; x > 0; x --) + { + if ((*r0 & 15) > dither[x & 3]) + *cptr ^= (bitmask & OnPixels[*r0++]); + else + *cptr ^= (bitmask & OffPixels[*r0++]); + + if ((*r0 & 15) > dither[x & 3]) + *mptr ^= (bitmask & OnPixels[*r0++]); + else + *mptr ^= (bitmask & OffPixels[*r0++]); + + if ((*r0 & 15) > dither[x & 3]) + *yptr ^= (bitmask & OnPixels[*r0++]); + else + *yptr ^= (bitmask & OffPixels[*r0++]); + + if (bitmask == 0xf0) + bitmask = 0x0f; + else + { + bitmask = 0xf0; + + cptr ++; + mptr ++; + yptr ++; + } + } + break; + + case 8 : + for (x = xsize; x > 0; x --, r0 += 3, r1 += 3) + { + if (r0[0] == r1[0]) + *cptr++ = r0[0]; + else + *cptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize; + + if (r0[1] == r1[1]) + *mptr++ = r0[1]; + else + *mptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize; + + if (r0[2] == r1[2]) + *yptr++ = r0[2]; + else + *yptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize; + } + break; + } + break; + + case CUPS_ORDER_PLANAR : + switch (header->cupsBitsPerColor) + { + case 1 : + bitmask = 0x80 >> (bitoffset & 7); + dither = Floyd16x16[y & 15]; + + switch (z) + { + case 2 : + for (x = xsize; x > 0; x --, r0 += 3) + { + if (r0[0] > dither[x & 15]) + *ptr ^= bitmask; + + if (bitmask > 1) + bitmask >>= 1; + else + { + bitmask = 0x80; + ptr ++; + } + } + break; + + case 1 : + for (x = xsize; x > 0; x --, r0 += 3) + { + if (r0[1] > dither[x & 15]) + *ptr ^= bitmask; + + if (bitmask > 1) + bitmask >>= 1; + else + { + bitmask = 0x80; + ptr ++; + } + } + break; + + case 0 : + for (x = xsize; x > 0; x --, r0 += 3) + { + if (r0[2] > dither[x & 15]) + *ptr ^= bitmask; + + if (bitmask > 1) + bitmask >>= 1; + else + { + bitmask = 0x80; + ptr ++; + } + } + break; + } + break; + + case 2 : + bitmask = 0xc0 >> (bitoffset & 7); + dither = Floyd8x8[y & 7]; + z = 2 - z; + r0 += z; + + for (x = xsize; x > 0; x --, r0 += 3) + { + if ((*r0 & 63) > dither[x & 7]) + *ptr ^= (bitmask & OnPixels[*r0]); + else + *ptr ^= (bitmask & OffPixels[*r0]); + + if (bitmask > 3) + bitmask >>= 2; + else + { + bitmask = 0xc0; + + ptr ++; + } + } + break; + + case 4 : + bitmask = 0xf0 >> (bitoffset & 7); + dither = Floyd4x4[y & 3]; + z = 2 - z; + r0 += z; + + for (x = xsize; x > 0; x --, r0 += 3) + { + if ((*r0 & 15) > dither[x & 3]) + *ptr ^= (bitmask & OnPixels[*r0]); + else + *ptr ^= (bitmask & OffPixels[*r0]); + + if (bitmask == 0xf0) + bitmask = 0x0f; + else + { + bitmask = 0xf0; + + ptr ++; + } + } + break; + + case 8 : + z = 2 - z; + r0 += z; + r1 += z; + + for (x = xsize; x > 0; x --, r0 += 3, r1 += 3) + { + if (*r0 == *r1) + *ptr++ = *r0; + else + *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize; + } + break; + } + break; + } +} + + +/* + * 'format_YMCK()' - Convert image data to YMCK. + */ + +static void +format_YMCK(cups_page_header_t *header, /* I - Page header */ + unsigned char *row, /* IO - Bitmap data for device */ + int y, /* I - Current row */ + int z, /* I - Current plane */ + int xsize, /* I - Width of image data */ + int ysize, /* I - Height of image data */ + int yerr0, /* I - Top Y error */ + int yerr1, /* I - Bottom Y error */ + ib_t *r0, /* I - Primary image data */ + ib_t *r1) /* I - Image data for interpolation */ +{ + ib_t *ptr, /* Pointer into row */ + *cptr, /* Pointer into cyan */ + *mptr, /* Pointer into magenta */ + *yptr, /* Pointer into yellow */ + *kptr, /* Pointer into black */ + bitmask; /* Current mask for pixel */ + int bitoffset; /* Current offset in line */ + int bandwidth; /* Width of a color band */ + int x, /* Current X coordinate on page */ + *dither; /* Pointer into dither array */ + + + if (Orientation == 1 || Orientation == 2) + bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize); + else + bitoffset = 0; + + ptr = row + bitoffset / 8; + bandwidth = header->cupsBytesPerLine / 4; + + switch (header->cupsColorOrder) + { + case CUPS_ORDER_CHUNKED : + switch (header->cupsBitsPerColor) + { + case 1 : + bitmask = 128 >> (bitoffset & 7); + dither = Floyd16x16[y & 15]; + + for (x = xsize ; x > 0; x --, r0 += 4) + { + if (r0[2] > dither[x & 15]) + *ptr ^= bitmask; + bitmask >>= 1; + + if (r0[1] > dither[x & 15]) + *ptr ^= bitmask; + bitmask >>= 1; + + if (r0[0] > dither[x & 15]) + *ptr ^= bitmask; + bitmask >>= 1; + + if (r0[3] > dither[x & 15]) + *ptr ^= bitmask; + + if (bitmask > 1) + bitmask >>= 1; + else + { + bitmask = 128; + + ptr ++; + } + } + break; + + case 2 : + dither = Floyd8x8[y & 7]; + + for (x = xsize ; x > 0; x --, r0 += 4) + { + if ((r0[2] & 63) > dither[x & 7]) + *ptr ^= (0xc0 & OnPixels[r0[2]]); + else + *ptr ^= (0xc0 & OffPixels[r0[2]]); + + if ((r0[1] & 63) > dither[x & 7]) + *ptr ^= (0x30 & OnPixels[r0[1]]); + else + *ptr ^= (0x30 & OffPixels[r0[1]]); + + if ((r0[0] & 63) > dither[x & 7]) + *ptr ^= (0x0c & OnPixels[r0[0]]); + else + *ptr ^= (0x0c & OffPixels[r0[0]]); + + if ((r0[3] & 63) > dither[x & 7]) + *ptr++ ^= (0x03 & OnPixels[r0[3]]); + else + *ptr++ ^= (0x03 & OffPixels[r0[3]]); + } + break; + + case 4 : + dither = Floyd4x4[y & 3]; + + for (x = xsize ; x > 0; x --, r0 += 4) + { + if ((r0[2] & 15) > dither[x & 3]) + *ptr ^= (0xf0 & OnPixels[r0[2]]); + else + *ptr ^= (0xf0 & OffPixels[r0[2]]); + + if ((r0[1] & 15) > dither[x & 3]) + *ptr++ ^= (0x0f & OnPixels[r0[1]]); + else + *ptr++ ^= (0x0f & OffPixels[r0[1]]); + + if ((r0[0] & 15) > dither[x & 3]) + *ptr ^= (0xf0 & OnPixels[r0[0]]); + else + *ptr ^= (0xf0 & OffPixels[r0[0]]); + + if ((r0[3] & 15) > dither[x & 3]) + *ptr++ ^= (0x0f & OnPixels[r0[3]]); + else + *ptr++ ^= (0x0f & OffPixels[r0[3]]); + } + break; + + case 8 : + for (x = xsize; x > 0; x --, r0 += 4, r1 += 4) + { + if (r0[2] == r1[2]) + *ptr++ = r0[2]; + else + *ptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize; + + if (r0[1] == r1[1]) + *ptr++ = r0[1]; + else + *ptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize; + + if (r0[0] == r1[0]) + *ptr++ = r0[0]; + else + *ptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize; + + if (r0[3] == r1[3]) + *ptr++ = r0[3]; + else + *ptr++ = (r0[3] * yerr0 + r1[3] * yerr1) / ysize; + } + break; + } + break; + + case CUPS_ORDER_BANDED : + yptr = ptr; + mptr = ptr + bandwidth; + cptr = ptr + 2 * bandwidth; + kptr = ptr + 3 * bandwidth; + + switch (header->cupsBitsPerColor) + { + case 1 : + bitmask = 0x80 >> (bitoffset & 7); + dither = Floyd16x16[y & 15]; + + for (x = xsize; x > 0; x --) + { + if (*r0++ > dither[x & 15]) + *cptr ^= bitmask; + if (*r0++ > dither[x & 15]) + *mptr ^= bitmask; + if (*r0++ > dither[x & 15]) + *yptr ^= bitmask; + if (*r0++ > dither[x & 15]) + *kptr ^= bitmask; + + if (bitmask > 1) + bitmask >>= 1; + else + { + bitmask = 0x80; + + cptr ++; + mptr ++; + yptr ++; + kptr ++; + } + } + break; + + case 2 : + bitmask = 0xc0 >> (bitoffset & 7); + dither = Floyd8x8[y & 7]; + + for (x = xsize; x > 0; x --) + { + if ((*r0 & 63) > dither[x & 7]) + *cptr ^= (bitmask & OnPixels[*r0++]); + else + *cptr ^= (bitmask & OffPixels[*r0++]); + + if ((*r0 & 63) > dither[x & 7]) + *mptr ^= (bitmask & OnPixels[*r0++]); + else + *mptr ^= (bitmask & OffPixels[*r0++]); + + if ((*r0 & 63) > dither[x & 7]) + *yptr ^= (bitmask & OnPixels[*r0++]); + else + *yptr ^= (bitmask & OffPixels[*r0++]); + + if ((*r0 & 63) > dither[x & 7]) + *kptr ^= (bitmask & OnPixels[*r0++]); + else + *kptr ^= (bitmask & OffPixels[*r0++]); + + if (bitmask > 3) + bitmask >>= 2; + else + { + bitmask = 0xc0; + + cptr ++; + mptr ++; + yptr ++; + kptr ++; + } + } + break; + + case 4 : + bitmask = 0xf0 >> (bitoffset & 7); + dither = Floyd4x4[y & 3]; + + for (x = xsize; x > 0; x --) + { + if ((*r0 & 15) > dither[x & 3]) + *cptr ^= (bitmask & OnPixels[*r0++]); + else + *cptr ^= (bitmask & OffPixels[*r0++]); + + if ((*r0 & 15) > dither[x & 3]) + *mptr ^= (bitmask & OnPixels[*r0++]); + else + *mptr ^= (bitmask & OffPixels[*r0++]); + + if ((*r0 & 15) > dither[x & 3]) + *yptr ^= (bitmask & OnPixels[*r0++]); + else + *yptr ^= (bitmask & OffPixels[*r0++]); + + if ((*r0 & 15) > dither[x & 3]) + *kptr ^= (bitmask & OnPixels[*r0++]); + else + *kptr ^= (bitmask & OffPixels[*r0++]); + + if (bitmask == 0xf0) + bitmask = 0x0f; + else + { + bitmask = 0xf0; + + cptr ++; + mptr ++; + yptr ++; + kptr ++; + } + } + break; + + case 8 : + for (x = xsize; x > 0; x --, r0 += 4, r1 += 4) + { + if (r0[0] == r1[0]) + *cptr++ = r0[0]; + else + *cptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize; + + if (r0[1] == r1[1]) + *mptr++ = r0[1]; + else + *mptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize; + + if (r0[2] == r1[2]) + *yptr++ = r0[2]; + else + *yptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize; + + if (r0[3] == r1[3]) + *kptr++ = r0[3]; + else + *kptr++ = (r0[3] * yerr0 + r1[3] * yerr1) / ysize; + } + break; + } + break; + + case CUPS_ORDER_PLANAR : + switch (header->cupsBitsPerColor) + { + case 1 : + bitmask = 0x80 >> (bitoffset & 7); + dither = Floyd16x16[y & 15]; + + if (z < 3) + r0 += 2 - z; + else + r0 += z; + + for (x = xsize; x > 0; x --, r0 += 4) + { + if (*r0 > dither[x & 15]) + *ptr ^= bitmask; + + if (bitmask > 1) + bitmask >>= 1; + else + { + bitmask = 0x80; + ptr ++; + } + } + break; + + case 2 : + bitmask = 0xc0 >> (bitoffset & 7); + dither = Floyd8x8[y & 7]; + if (z == 3) + r0 += 3; + else + r0 += 2 - z; + + for (x = xsize; x > 0; x --, r0 += 4) + { + if ((*r0 & 63) > dither[x & 7]) + *ptr ^= (bitmask & OnPixels[*r0]); + else + *ptr ^= (bitmask & OffPixels[*r0]); + + if (bitmask > 3) + bitmask >>= 2; + else + { + bitmask = 0xc0; + + ptr ++; + } + } + break; + + case 4 : + bitmask = 0xf0 >> (bitoffset & 7); + dither = Floyd4x4[y & 3]; + if (z == 3) + r0 += 3; + else + r0 += 2 - z; + + for (x = xsize; x > 0; x --, r0 += 4) + { + if ((*r0 & 15) > dither[x & 3]) + *ptr ^= (bitmask & OnPixels[*r0]); + else + *ptr ^= (bitmask & OffPixels[*r0]); + + if (bitmask == 0xf0) + bitmask = 0x0f; + else + { + bitmask = 0xf0; + + ptr ++; + } + } + break; + + case 8 : + if (z == 3) + { + r0 += 3; + r1 += 3; + } + else + { + r0 += 2 - z; + r1 += 2 - z; + } + + for (x = xsize; x > 0; x --, r0 += 4, r1 += 4) + { + if (*r0 == *r1) + *ptr++ = *r0; + else + *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize; + } + break; + } + break; + } +} + + +/* + * 'make_lut()' - Make a lookup table given gamma and brightness values. + */ + +static void +make_lut(ib_t *lut, /* I - Lookup table */ + int colorspace, /* I - Colorspace */ + float g, /* I - Image gamma */ + float b) /* I - Image brightness */ +{ + int i; /* Looping var */ + int v; /* Current value */ + + + g = 1.0 / g; + b = 1.0 / b; + + for (i = 0; i < 256; i ++) + { + if (colorspace < 0) + v = 255.0 * b * (1.0 - pow(1.0 - (float)i / 255.0, g)) + 0.5; + else + v = 255.0 * (1.0 - b * (1.0 - pow((float)i / 255.0, g))) + 0.5; + + if (v < 0) + *lut++ = 0; + else if (v > 255) + *lut++ = 255; + else + *lut++ = v; + } +} + + +/* + * End of "$Id$". + */ diff --git a/filter/pstops.c b/filter/pstops.c new file mode 100644 index 0000000000..2418ce90d8 --- /dev/null +++ b/filter/pstops.c @@ -0,0 +1,706 @@ +/* + * "$Id$" + * + * PostScript filter for the Common UNIX Printing System (CUPS). + * + * Copyright 1993-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * main() - Main entry... + * check_range() - Check to see if the current page is selected for + * copy_bytes() - Copy bytes from the input file to stdout... + * end_nup() - End processing for N-up printing... + * psgets() - Get a line from a file. + * start_nup() - Start processing for N-up printing... + */ + +/* + * Include necessary headers... + */ + +#include "common.h" + + +/* + * Constants... + */ + +#define MAX_PAGES 10000 + + +/* + * Globals... + */ + +int NumPages = 0; /* Number of pages in file */ +long Pages[MAX_PAGES]; /* Offsets to each page */ +char PageLabels[MAX_PAGES][64]; + /* Page labels */ +char *PageRanges = NULL; /* Range of pages selected */ +char *PageSet = NULL; /* All, Even, Odd pages */ +int Order = 0, /* 0 = normal, 1 = reverse pages */ + Flip = 0, /* Flip/mirror pages */ + NUp = 1, /* Number of pages on each sheet (1, 2, 4) */ + Collate = 0, /* Collate copies? */ + Copies = 1; /* Number of copies */ + + +/* + * Local functions... + */ + +static int check_range(int page); +static void copy_bytes(FILE *fp, size_t length); +static void end_nup(int number); +static char *psgets(char *buf, size_t len, FILE *fp); +static void start_nup(int number); + + +/* + * 'main()' - Main entry... + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line arguments */ + char *argv[]) /* I - Command-line arguments */ +{ + FILE *fp; /* Print file */ + ppd_file_t *ppd; /* PPD file */ + int num_options; /* Number of print options */ + cups_option_t *options; /* Print options */ + char *val; /* Option value */ + char tempfile[255]; /* Temporary file name */ + FILE *temp; /* Temporary file */ + int number; /* Page number */ + int slowcollate; /* 1 if we need to collate manually */ + int sloworder; /* 1 if we need to order manually */ + char line[8192]; /* Line buffer */ + float g; /* Gamma correction value */ + float b; /* Brightness factor */ + + + if (argc < 6 || argc > 7) + { + fputs("ERROR: pstops job-id user title copies options [file]\n", stderr); + return (1); + } + + /* + * If we have 7 arguments, print the file named on the command-line. + * Otherwise, send stdin instead... + */ + + if (argc == 6) + fp = stdin; + else + { + /* + * Try to open the print file... + */ + + if ((fp = fopen(argv[6], "rb")) == NULL) + { + perror("ERROR: unable to open print file - "); + return (1); + } + } + + /* + * Process command-line options and write the prolog... + */ + + g = 1.0; + b = 1.0; + + ppd = ppdOpenFile(getenv("PPD")); + + options = NULL; + num_options = cupsParseOptions(argv[5], 0, &options); + + ppd = SetCommonOptions(num_options, options, 1); + + ppdMarkDefaults(ppd); + cupsMarkOptions(ppd, num_options, options); + + if ((val = cupsGetOption("page-ranges", num_options, options)) != NULL) + PageRanges = val; + + if ((val = cupsGetOption("page-set", num_options, options)) != NULL) + PageSet = val; + + if ((val = cupsGetOption("copies", num_options, options)) != NULL) + Copies = atoi(val); + + if ((val = cupsGetOption("multiple-document-handling", num_options, options)) != NULL) + { + /* + * This IPP attribute is unnecessarily complicated... + * + * single-document, separate-documents-collated-copies, and + * single-document-new-sheet all require collated copies. + * + * separate-documents-collated-copies allows for uncollated copies. + */ + + Collate = strcmp(val, "separate-documents-collated-copies") != 0; + } + + if ((val = cupsGetOption("Collate", num_options, options)) != NULL && + strcmp(val, "True") == 0) + Collate = 1; + + if ((val = cupsGetOption("OutputOrder", num_options, options)) != NULL && + strcmp(val, "Reverse") == 0) + Order = 1; + + if ((val = cupsGetOption("number-up", num_options, options)) != NULL) + NUp = atoi(val); + + if ((val = cupsGetOption("gamma", num_options, options)) != NULL) + g = atoi(val) * 0.001f; + + if ((val = cupsGetOption("brightness", num_options, options)) != NULL) + b = atoi(val) * 0.01f; + + /* + * See if we have to filter the fast or slow way... + */ + + if (ppdFindOption(ppd, "Collate") == NULL && Collate && Copies > 1) + slowcollate = 1; + else + slowcollate = 0; + + if (ppdFindOption(ppd, "OutputOrder") == NULL && Order) + sloworder = 1; + else + sloworder = 0; + + /* + * If we need to filter slowly, then create a temporary file for page data... + * + * If the temp file can't be created, then we'll ignore the collating/output + * order options... + */ + + if (sloworder || slowcollate) + { + temp = fopen(tmpnam(tempfile), "wb+"); + + if (temp == NULL) + slowcollate = sloworder = 0; + } + + /* + * Write any "exit server" options that have been selected... + */ + + ppdEmit(ppd, stdout, PPD_ORDER_EXIT); + + /* + * Write any JCL commands that are needed to print PostScript code... + */ + + if (ppd != NULL && ppd->jcl_begin && ppd->jcl_ps) + { + fputs(ppd->jcl_begin, stdout); + ppdEmit(ppd, stdout, PPD_ORDER_JCL); + fputs(ppd->jcl_ps, stdout); + } + + /* + * Read the first line to see if we have DSC comments... + */ + + if (psgets(line, sizeof(line), fp) == NULL) + { + fputs("ERROR: Empty print file!\n", stderr); + ppdClose(ppd); + return (1); + } + + /* + * Start sending the document with any commands needed... + */ + + puts(line); + + ppdEmit(ppd, stdout, PPD_ORDER_DOCUMENT); + ppdEmit(ppd, stdout, PPD_ORDER_ANY); + ppdEmit(ppd, stdout, PPD_ORDER_PROLOG); + + if (NUp > 1) + puts("userdict begin\n" + "/ESPshowpage /showpage load def\n" + "/showpage { } def\n" + "end"); + + if (g != 1.0 || b != 1.0) + printf("{ neg 1 add %.3f exp neg 1 add %.3f mul } bind settransfer\n", g, b); + + if (Copies > 1 && (!Collate || !slowcollate)) + printf("/#copies %d def\n", Copies); + + if (strncmp(line, "%!PS-Adobe-", 11) == 0) + { + /* + * OK, we have DSC comments; read until we find a %%Page comment... + */ + + while (psgets(line, sizeof(line), fp) != NULL) + if (strncmp(line, "%%Page:", 7) == 0) + break; + else + puts(line); + + /* + * Then read all of the pages, filtering as needed... + */ + + for (;;) + { + if (strncmp(line, "%%Page:", 7) == 0) + { + if (sscanf(line, "%*s%*s%d", &number) == 1) + { + if (!check_range(number)) + { + while (psgets(line, sizeof(line), fp) != NULL) + if (strncmp(line, "%%Page:", 7) == 0) + break; + continue; + } + + if (!sloworder && NumPages > 0) + end_nup(NumPages - 1); + + if (slowcollate || sloworder) + Pages[NumPages] = ftell(temp); + + NumPages ++; + + if (!sloworder) + { + ppdEmit(ppd, stdout, PPD_ORDER_PAGE); + start_nup(NumPages - 1); + } + } + } + else + { + if (!sloworder) + puts(line); + + if (slowcollate || sloworder) + { + fputs(line, temp); + putc('\n', temp); + } + } + + if (psgets(line, sizeof(line), fp) == NULL) + break; + } + + if (!sloworder) + end_nup((NumPages + NUp - 1) & (NUp - 1)); + + if (slowcollate || sloworder) + { + Pages[NumPages] = ftell(temp); + + if (!sloworder) + { + while (Copies > 1) + { + rewind(temp); + + for (number = 0; number < NumPages; number ++) + { + ppdEmit(ppd, stdout, PPD_ORDER_PAGE); + start_nup(number); + copy_bytes(temp, Pages[number + 1] - Pages[number]); + end_nup(number); + } + + Copies --; + } + } + else + { + if (!slowcollate) + Copies = 1; + + while (Copies > 0) + { + for (number = NumPages - 1; number >= 0; number --) + { + ppdEmit(ppd, stdout, PPD_ORDER_PAGE); + start_nup(NumPages - 1 - number); + fseek(temp, Pages[number], SEEK_SET); + copy_bytes(temp, Pages[number + 1] - Pages[number]); + end_nup(NumPages - 1 - number); + } + + Copies --; + } + } + } + } + else + { + /* + * No DSC comments - write any page commands and then the rest of the file... + */ + + ppdEmit(ppd, stdout, PPD_ORDER_PAGE); + + while (psgets(line, sizeof(line), fp) != NULL) + { + puts(line); + + if (slowcollate) + { + fputs(line, temp); + putc('\n', temp); + } + } + + if (slowcollate) + { + while (Copies > 1) + { + ppdEmit(ppd, stdout, PPD_ORDER_PAGE); + rewind(temp); + copy_bytes(temp, 0); + } + } + } + + /* + * End the job with the appropriate JCL command or CTRL-D otherwise. + */ + + if (ppd != NULL && ppd->jcl_end) + fputs(ppd->jcl_end, stdout); + else + putchar(0x04); + + /* + * Close files and remove the temporary file if needed... + */ + + if (slowcollate || sloworder) + { + fclose(temp); + unlink(tempfile); + } + + ppdClose(ppd); + + if (fp != stdin) + fclose(fp); + + return (0); +} + + +/* + * 'check_range()' - Check to see if the current page is selected for + * printing. + */ + +static int /* O - 1 if selected, 0 otherwise */ +check_range(int page) /* I - Page number */ +{ + char *range; /* Pointer into range string */ + int lower, upper; /* Lower and upper page numbers */ + + + if (PageSet != NULL) + { + /* + * See if we only print even or odd pages... + */ + + if (strcmp(PageSet, "even") == 0 && (page & 1)) + return (0); + if (strcmp(PageSet, "odd") == 0 && !(page & 1)) + return (0); + } + + if (PageRanges == NULL) + return (1); /* No range, print all pages... */ + + for (range = PageRanges; *range != '\0';) + { + if (*range == '-') + { + lower = 1; + range ++; + upper = strtol(range, &range, 10); + } + else + { + lower = strtol(range, &range, 10); + + if (*range == '-') + { + range ++; + if (!isdigit(*range)) + upper = 65535; + else + upper = strtol(range, &range, 10); + } + else + upper = lower; + } + + if (page >= lower && page <= upper) + return (1); + + if (*range == ',') + range ++; + else + break; + } + + return (0); +} + + +/* + * 'copy_bytes()' - Copy bytes from the input file to stdout... + */ + +static void +copy_bytes(FILE *fp, /* I - File to read from */ + size_t length) /* I - Length of page data */ +{ + char buffer[8192]; /* Data buffer */ + size_t nbytes, /* Number of bytes read */ + nleft; /* Number of bytes left/remaining */ + + + nleft = length; + + while (nleft > 0 || length == 0) + { + if ((nbytes = fread(buffer, 1, sizeof(buffer), fp)) < 1) + return; + + nleft -= nbytes; + + fwrite(buffer, 1, nbytes, stdout); + } +} + + +/* + * 'end_nup()' - End processing for N-up printing... + */ + +static void +end_nup(int number) /* I - Page number */ +{ + puts("grestore"); + + switch (NUp) + { + case 2 : + if ((number & 1) == 1) + puts("ESPshowpage"); + break; + + case 4 : + if ((number & 3) == 3) + puts("ESPshowpage"); + break; + } +} + + +/* + * 'psgets()' - Get a line from a file. + * + * Note: + * + * This function differs from the gets() function in that it + * handles any combination of CR, LF, or CR LF to end input + * lines. + */ + +static char * /* O - String or NULL if EOF */ +psgets(char *buf, /* I - Buffer to read into */ + size_t len, /* I - Length of buffer */ + FILE *fp) /* I - File to read from */ +{ + char *bufptr; /* Pointer into buffer */ + int ch; /* Character from file */ + + + len --; + bufptr = buf; + + while ((bufptr - buf) < len) + { + if ((ch = getc(fp)) == EOF) + break; + + if (ch == 0x0d) + { + /* + * Got a CR; see if there is a LF as well... + */ + + ch = getc(fp); + if (ch != EOF && ch != 0x0a) + ungetc(ch, fp); /* Nope, save it for later... */ + + break; + } + else if (ch == 0x0a) + break; + else + *bufptr++ = ch; + } + + /* + * Nul-terminate the string and return it (or NULL for EOF). + */ + + *bufptr = '\0'; + + if (ch == EOF && bufptr == buf) + return (NULL); + else + return (buf); +} + + +/* + * 'start_nup()' - Start processing for N-up printing... + */ + +static void +start_nup(int number) /* I - Page number */ +{ + int x, y; /* Relative position of subpage */ + float w, l, /* Width and length of subpage */ + tx, ty; /* Translation values for subpage */ + + + puts("gsave"); + + if (Flip) + printf("%.0f 0 translate -1 1 scale\n", PageWidth); + + switch (Orientation) + { + case 1 : /* Landscape */ + printf("%.0f 0 translate 90 rotate\n", PageLength); + break; + case 2 : /* Reverse Portrait */ + printf("%.0f %.0f translate 180 rotate\n", PageWidth, PageLength); + break; + case 3 : /* Reverse Landscape */ + printf("0 %.0f translate -90 rotate\n", PageWidth); + break; + } + + switch (NUp) + { + case 2 : + x = number & 1; + + if (Orientation & 1) + { + x = 1 - x; + w = PageLength; + l = w * PageLength / PageWidth; + + if (l > (PageWidth * 0.5)) + { + l = PageWidth * 0.5; + w = l * PageWidth / PageLength; + } + + tx = PageWidth * 0.5 - l; + ty = (PageLength - w) * 0.5; + } + else + { + l = PageWidth; + w = l * PageWidth / PageLength; + + if (w > (PageLength * 0.5)) + { + w = PageLength * 0.5; + l = w * PageLength / PageWidth; + } + + tx = PageLength * 0.5 - w; + ty = (PageWidth - l) * 0.5; + } + + if (Orientation & 1) + { + printf("0 %.0f translate -90 rotate\n", PageLength); + printf("%.0f %.0f translate %.3f %.3f scale\n", + ty, tx + l * x, w / PageWidth, l / PageLength); + } + else + { + printf("%.0f 0 translate 90 rotate\n", PageWidth); + printf("%.0f %.0f translate %.3f %.3f scale\n", + tx + w * x, ty, w / PageWidth, l / PageLength); + } + + printf("newpath\n" + "0 0 moveto\n" + "%.0f 0 lineto\n" + "%.0f %.0f lineto\n" + "0 %.0f lineto\n" + "closepath clip newpath\n", + PageWidth, PageWidth, PageLength, PageLength); + break; + + case 4 : + x = number & 1; + y = 1 - ((number & 2) != 0); + w = PageWidth * 0.5; + l = PageLength * 0.5; + + printf("%.0f %.0f translate 0.5 0.5 scale\n", x * w, y * l); + printf("newpath\n" + "0 0 moveto\n" + "%.0f 0 lineto\n" + "%.0f %.0f lineto\n" + "0 %.0f lineto\n" + "closepath clip newpath\n", + PageWidth, PageWidth, PageLength, PageLength); + break; + } +} + + +/* + * End of "$Id$". + */ diff --git a/filter/pstops.dsp b/filter/pstops.dsp new file mode 100644 index 0000000000..956c8ab655 --- /dev/null +++ b/filter/pstops.dsp @@ -0,0 +1,107 @@ +# Microsoft Developer Studio Project File - Name="pstops" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=pstops - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "pstops.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "pstops.mak" CFG="pstops - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "pstops - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "pstops - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "pstops - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 ../cups/cups.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"pstops.exe" + +!ELSEIF "$(CFG)" == "pstops - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "pstops___Win32_Debug" +# PROP BASE Intermediate_Dir "pstops___Win32_Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 ../cups/cups.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"pstopsd.exe" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "pstops - Win32 Release" +# Name "pstops - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\pstops.c + +!IF "$(CFG)" == "pstops - Win32 Release" + +!ELSEIF "$(CFG)" == "pstops - Win32 Debug" + +# ADD CPP /Zi + +!ENDIF + +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# End Target +# End Project diff --git a/filter/textcommon.c b/filter/textcommon.c new file mode 100644 index 0000000000..f1ea5070c0 --- /dev/null +++ b/filter/textcommon.c @@ -0,0 +1,707 @@ +/* + * "$Id$" + * + * Common text filter routines for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * TextMain() - Standard main entry for text filters. + * compare_keywords() - Compare two C/C++ keywords. + * getutf8() - Get a UTF-8 encoded wide character... + */ + +/* + * Include necessary headers... + */ + +#include "textcommon.h" + + +/* + * Globals... + */ + +int WrapLines = 0, /* Wrap text in lines */ + SizeLines = 60, /* Number of lines on a page */ + SizeColumns = 80, /* Number of columns on a line */ + PageColumns = 1, /* Number of columns on a page */ + ColumnGutter = 0, /* Number of characters between text columns */ + ColumnWidth = 80, /* Width of each column */ + PrettyPrint = 0; /* Do pretty code formatting */ +lchar_t **Page = NULL; /* Page characters */ +int NumPages = 0; /* Number of pages in document */ +int CharsPerInch = 10; /* Number of character columns per inch */ +int LinesPerInch = 6; /* Number of lines per inch */ +int UTF8 = 0; /* Use UTF-8 encoding? */ +char *Keywords[] = /* List of known keywords... */ + { + "auto", + "break", + "case", + "char", + "class", + "const", + "continue", + "default", + "delete", + "double", + "do", + "else", + "enum", + "extern", + "float", + "for", + "friend", + "goto", + "if", + "int", + "long", + "new", + "private", + "protected", + "public", + "register", + "return", + "short", + "signed", + "sizeof", + "static", + "struct", + "switch", + "typedef", + "union", + "unsigned", + "void", + "volatile", + "while" + }; + + +/* + * Local functions... + */ + +static int compare_keywords(const void *, const void *); +static int getutf8(FILE *fp); + + +/* + * 'TextMain()' - Standard main entry for text filters. + */ + +int /* O - Exit status */ +TextMain(char *name, /* I - Name of filter */ + int argc, /* I - Number of command-line arguments */ + char *argv[]) /* I - Command-line arguments */ +{ + FILE *fp; /* Print file */ + ppd_file_t *ppd; /* PPD file */ + int i, /* Looping var */ + ch, /* Current char from file */ + lastch, /* Previous char from file */ + attr, /* Current attribute */ + line, /* Current line */ + column, /* Current column */ + page_column; /* Current page column */ + int num_options; /* Number of print options */ + cups_option_t *options; /* Print options */ + char *val; /* Option value */ + char keyword[64], /* Keyword string */ + *keyptr; /* Pointer into string */ + int keycol; /* Column where keyword starts */ + int ccomment; /* Inside a C-style comment? */ + int cstring; /* Inside a C string */ + + + if (argc < 6 || argc > 7) + { + fprintf(stderr, "ERROR: %s job-id user title copies options [file]\n", + name); + return (1); + } + + /* + * If we have 7 arguments, print the file named on the command-line. + * Otherwise, send stdin instead... + */ + + if (argc == 6) + fp = stdin; + else + { + /* + * Try to open the print file... + */ + + if ((fp = fopen(argv[6], "rb")) == NULL) + { + perror("ERROR: unable to open print file - "); + return (1); + } + } + + /* + * Process command-line options and write the prolog... + */ + + options = NULL; + num_options = cupsParseOptions(argv[5], 0, &options); + + if ((ppd = SetCommonOptions(num_options, options, 1)) != NULL) + ppdClose(ppd); + + WrapLines = cupsGetOption("wrap", num_options, options) != NULL; + + if ((val = cupsGetOption("columns", num_options, options)) != NULL) + PageColumns = atoi(val); + + if ((val = cupsGetOption("cpi", num_options, options)) != NULL) + CharsPerInch = atoi(val); + + if ((val = cupsGetOption("lpi", num_options, options)) != NULL) + LinesPerInch = atoi(val); + + if ((val = cupsGetOption("prettyprint", num_options, options)) != NULL) + { + PrettyPrint = 1; + PageTop -= 216.0f / LinesPerInch; + } + + WriteProlog(argv[3], argv[2]); + + /* + * Read text from the specified source and print it... + */ + + column = 0; + line = 0; + page_column = 0; + attr = 0; + keyptr = keyword; + keycol = 0; + ccomment = 0; + cstring = 0; + + while ((ch = getutf8(fp)) >= 0) + { + /* + * Control codes: + * + * BS Backspace (0x08) + * HT Horizontal tab; next 8th column (0x09) + * LF Line feed; forward full line (0x0a) + * VT Vertical tab; reverse full line (0x0b) + * FF Form feed (0x0c) + * CR Carriage return (0x0d) + * ESC 7 Reverse full line (0x1b 0x37) + * ESC 8 Reverse half line (0x1b 0x38) + * ESC 9 Forward half line (0x1b 0x39) + */ + + switch (ch) + { + case 0x08 : /* BS - backspace for boldface & underline */ + if (column > 0) + column --; + + keyptr = keyword; + keycol = column; + break; + + case 0x09 : /* HT - tab to next 8th column */ + if (PrettyPrint && keyptr > keyword) + { + *keyptr = '\0'; + keyptr = keyword; + + if (bsearch(&keyptr, Keywords, sizeof(Keywords) / sizeof(Keywords[0]), + sizeof(Keywords[0]), compare_keywords)) + { + /* + * Put keywords in boldface... + */ + + i = page_column * (ColumnWidth + ColumnGutter); + + while (keycol < column) + { + Page[line][keycol + i].attr |= ATTR_BOLD; + keycol ++; + } + } + } + + column = (column + 8) & ~7; + + if (column >= ColumnWidth && WrapLines) + { /* Wrap text to margins */ + line ++; + column = 0; + + if (line >= SizeLines) + { + page_column ++; + line = 0; + + if (page_column >= PageColumns) + { + WritePage(); + page_column = 0; + } + } + } + + keycol = column; + break; + + case 0x0a : /* LF - output current line */ + if (PrettyPrint && keyptr > keyword) + { + *keyptr = '\0'; + keyptr = keyword; + + if (bsearch(&keyptr, Keywords, sizeof(Keywords) / sizeof(Keywords[0]), + sizeof(Keywords[0]), compare_keywords)) + { + /* + * Put keywords in boldface... + */ + + i = page_column * (ColumnWidth + ColumnGutter); + + while (keycol < column) + { + Page[line][keycol + i].attr |= ATTR_BOLD; + keycol ++; + } + } + } + + line ++; + column = 0; + keycol = 0; + + if (!ccomment && !cstring) + attr &= ~(ATTR_ITALIC | ATTR_BOLD | ATTR_RED | ATTR_GREEN | ATTR_BLUE); + + if (line >= SizeLines) + { + page_column ++; + line = 0; + + if (page_column >= PageColumns) + { + WritePage(); + page_column = 0; + } + } + break; + + case 0x0b : /* VT - move up 1 line */ + if (line > 0) + line --; + + keyptr = keyword; + keycol = column; + + if (!ccomment && !cstring) + attr &= ~(ATTR_ITALIC | ATTR_BOLD | ATTR_RED | ATTR_GREEN | ATTR_BLUE); + break; + + case 0x0c : /* FF - eject current page... */ + if (PrettyPrint && keyptr > keyword) + { + *keyptr = '\0'; + keyptr = keyword; + + if (bsearch(&keyptr, Keywords, sizeof(Keywords) / sizeof(Keywords[0]), + sizeof(Keywords[0]), compare_keywords)) + { + /* + * Put keywords in boldface... + */ + + i = page_column * (ColumnWidth + ColumnGutter); + + while (keycol < column) + { + Page[line][keycol + i].attr |= ATTR_BOLD; + keycol ++; + } + } + } + + page_column ++; + column = 0; + keycol = 0; + line = 0; + + if (!ccomment && !cstring) + attr &= ~(ATTR_ITALIC | ATTR_BOLD | ATTR_RED | ATTR_GREEN | ATTR_BLUE); + + if (page_column >= PageColumns) + { + WritePage(); + page_column = 0; + } + break; + + case 0x0d : /* CR */ + column = 0; + break; + + case 0x1b : /* Escape sequence */ + ch = getutf8(fp); + if (ch == '7') + { + /* + * ESC 7 Reverse full line (0x1b 0x37) + */ + + if (line > 0) + line --; + } + else if (ch == '8') + { + /* + * ESC 8 Reverse half line (0x1b 0x38) + */ + + if ((attr & ATTR_RAISED) && line > 0) + { + attr &= ~ATTR_RAISED; + line --; + } + else if (attr & ATTR_LOWERED) + attr &= ~ATTR_LOWERED; + else + attr |= ATTR_RAISED; + } + else if (ch == '9') + { + /* + * ESC 9 Forward half line (0x1b 0x39) + */ + + if ((attr & ATTR_LOWERED) && line < (SizeLines - 1)) + { + attr &= ~ATTR_LOWERED; + line ++; + } + else if (attr & ATTR_RAISED) + attr &= ~ATTR_RAISED; + else + attr |= ATTR_LOWERED; + } + break; + + default : /* All others... */ + if (ch < ' ') + break; /* Ignore other control chars */ + + if (PrettyPrint) + { + /* + * Do highlighting of C/C++ keywords, preprocessor commands, + * and comments... + */ + + if ((ch == ' ' || ch == '\t') && (attr & ATTR_BOLD)) + { + /* + * Stop bolding preprocessor command... + */ + + attr &= ~ATTR_BOLD; + } + else if (!isalpha(ch) && keyptr > keyword) + { + /* + * Look for a keyword... + */ + + *keyptr = '\0'; + keyptr = keyword; + + if (!(attr & ATTR_ITALIC) && + bsearch(&keyptr, Keywords, sizeof(Keywords) / sizeof(Keywords[0]), + sizeof(Keywords[0]), compare_keywords)) + { + /* + * Put keywords in boldface... + */ + + i = page_column * (ColumnWidth + ColumnGutter); + + while (keycol < column) + { + Page[line][keycol + i].attr |= ATTR_BOLD; + keycol ++; + } + } + } + else if (isalpha(ch) && !ccomment && !cstring) + { + /* + * Add characters to the current keyword (if they'll fit). + */ + + if (keyptr == keyword) + keycol = column; + + if (keyptr < (keyword + sizeof(keyword) - 1)) + *keyptr++ = ch; + } + else if (ch == '\"' && lastch != '\\' && !ccomment && !cstring) + { + /* + * Start a C string constant... + */ + + cstring = -1; + attr |= ATTR_BLUE; + } + else if (ch == '*' && lastch == '/' && !cstring) + { + /* + * Start a C-style comment... + */ + + ccomment = 1; + attr |= ATTR_ITALIC | ATTR_GREEN; + } + else if (ch == '/' && lastch == '/' && !cstring) + { + /* + * Start a C++-style comment... + */ + + attr |= ATTR_ITALIC | ATTR_GREEN; + } + else if (ch == '#' && column == 0 && !ccomment && !cstring) + { + /* + * Start a preprocessor command... + */ + + attr |= ATTR_BOLD | ATTR_RED; + } + } + + if (column >= ColumnWidth && WrapLines) + { /* Wrap text to margins */ + column = 0; + line ++; + + if (line >= SizeLines) + { + page_column ++; + line = 0; + + if (page_column >= PageColumns) + { + WritePage(); + page_column = 0; + } + } + } + + /* + * Add text to the current column & line... + */ + + if (column < ColumnWidth) + { + i = column + page_column * (ColumnWidth + ColumnGutter); + + if (PrettyPrint) + Page[line][i].attr = attr; + else if (ch == Page[line][i].ch) + Page[line][i].attr |= ATTR_BOLD; + else if (Page[line][i].ch == '_') + Page[line][i].attr |= ATTR_UNDERLINE; + else + Page[line][i].attr = attr; + + Page[line][i].ch = ch; + } + + if (PrettyPrint) + { + if ((ch == '{' || ch == '}') && !ccomment && !cstring && + column < ColumnWidth) + { + /* + * Highlight curley braces... + */ + + Page[line][i].attr |= ATTR_BOLD; + } + else if ((ch == '/' || ch == '*') && lastch == '/' && + column < ColumnWidth) + { + /* + * Highlight first comment character... + */ + + Page[line][i - 1].attr = attr; + } + else if (ch == '\"' && lastch != '\\' && !ccomment && cstring > 0) + { + /* + * End a C string constant... + */ + + cstring = 0; + attr &= ~ATTR_BLUE; + } + else if (ch == '/' && lastch == '*' && ccomment) + { + /* + * End a C-style comment... + */ + + ccomment = 0; + attr &= ~(ATTR_ITALIC | ATTR_GREEN); + } + + if (cstring < 0) + cstring = 1; + } + + column ++; + break; + } + + /* + * Save this character for the next cycle. + */ + + lastch = ch; + } + + /* + * Write any remaining page data... + */ + + if (line > 0 || page_column > 0 || column > 0) + WritePage(); + + /* + * Write the epilog and return... + */ + + WriteEpilogue(); + + return (0); +} + + +/* + * 'compare_keywords()' - Compare two C/C++ keywords. + */ + +static int /* O - Result of strcmp */ +compare_keywords(const void *k1, /* I - First keyword */ + const void *k2) /* I - Second keyword */ +{ + return (strcmp(*((const char **)k1), *((const char **)k2))); +} + + +/* + * 'getutf8()' - Get a UTF-8 encoded wide character... + */ + +static int /* O - Character or -1 on error */ +getutf8(FILE *fp) /* I - File to read from */ +{ + int ch; /* Current character value */ + int next; /* Next character from file */ + + + /* + * Read the first character and process things accordingly... + * + * UTF-8 maps 16-bit characters to: + * + * 0 to 127 = 0xxxxxxx + * 128 to 2047 = 110xxxxx 10yyyyyy (xxxxxyyyyyy) + * 2048 to 65535 = 1110xxxx 10yyyyyy 10zzzzzz (xxxxyyyyyyzzzzzz) + * + * We also accept: + * + * 128 to 191 = 10xxxxxx + * + * since this range of values is otherwise undefined unless you are + * in the middle of a multi-byte character... + * + * This code currently does not support anything beyond 16-bit + * characters, in part because PostScript doesn't support more than + * 16-bit characters... + */ + + if ((ch = getc(fp)) == EOF) + return (EOF); + + if (ch < 0xc0 || !UTF8) /* One byte character? */ + return (ch); + else if ((ch & 0xe0) == 0xc0) + { + /* + * Two byte character... + */ + + if ((next = getc(fp)) == EOF) + return (EOF); + else + return (((ch & 0x1f) << 6) | (next & 0x3f)); + } + else if ((ch & 0xf0) == 0xe0) + { + /* + * Three byte character... + */ + + if ((next = getc(fp)) == EOF) + return (EOF); + + ch = ((ch & 0x0f) << 6) | (next & 0x3f); + + if ((next = getc(fp)) == EOF) + return (EOF); + else + return ((ch << 6) | (next & 0x3f)); + } + else + { + /* + * More than three bytes... We don't support that... + */ + + return (EOF); + } +} + + +/* + * End of "$Id$". + */ diff --git a/filter/textcommon.h b/filter/textcommon.h new file mode 100644 index 0000000000..e601e33606 --- /dev/null +++ b/filter/textcommon.h @@ -0,0 +1,88 @@ +/* + * "$Id$" + * + * Common text filter definitions for the Common UNIX Printing System (CUPS). + * + * Copyright 1997-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + */ + +/* + * Include necessary headers... + */ + +#include "common.h" + + +/* + * Constants... + */ + +#define ATTR_BOLD 0x01 +#define ATTR_UNDERLINE 0x02 +#define ATTR_RAISED 0x04 +#define ATTR_LOWERED 0x08 +#define ATTR_ITALIC 0x10 +#define ATTR_RED 0x20 +#define ATTR_GREEN 0x40 +#define ATTR_BLUE 0x80 + + +/* + * Structures... + */ + +typedef struct /**** Character/attribute structure... ****/ +{ + unsigned short ch, /* Character */ + attr; /* Any attributes */ +} lchar_t; + + +/* + * Globals... + */ + +extern int WrapLines, /* Wrap text in lines */ + SizeLines, /* Number of lines on a page */ + SizeColumns, /* Number of columns on a line */ + PageColumns, /* Number of columns on a page */ + ColumnGutter, /* Number of characters between text columns */ + ColumnWidth, /* Width of each column */ + PrettyPrint; /* Do pretty code formatting */ +extern lchar_t **Page; /* Page characters */ +extern int NumPages; /* Number of pages in document */ +extern int CharsPerInch, /* Number of character columns per inch */ + LinesPerInch, /* Number of lines per inch */ + UTF8; /* Use UTF-8 encoding? */ +extern char *Keywords[]; /* List of known keywords... */ + + +/* + * Required functions... + */ + +extern int TextMain(char *name, int argc, char *argv[]); +extern void WriteEpilogue(void); +extern void WritePage(void); +extern void WriteProlog(char *title, char *user); + + +/* + * End of "$Id$". + */ diff --git a/filter/texttops.c b/filter/texttops.c new file mode 100644 index 0000000000..98f241f325 --- /dev/null +++ b/filter/texttops.c @@ -0,0 +1,569 @@ +/* + * "$Id$" + * + * Text to PostScript filter for the Common UNIX Printing System (CUPS). + * + * Copyright 1993-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * Contents: + * + * main() - Main entry for text to PostScript filter. + * WriteEpilogue() - Write the PostScript file epilogue. + * WritePage() - Write a page of text. + * WriteProlog() - Write the PostScript file prolog with options. + * write_line() - Write a row of text. + * write_string() - Write a string of text. + */ + +/* + * Include necessary headers... + */ + +#include "textcommon.h" + + +/* + * Globals... + */ + +char *Glyphs[65536]; /* PostScript glyphs for Unicode */ + +/* + * Local functions... + */ + +static void write_line(int row, lchar_t *line); +static void write_string(int col, int row, int len, lchar_t *s); + + +/* + * 'main()' - Main entry for text to PostScript filter. + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line arguments */ + char *argv[]) /* I - Command-line arguments */ +{ + return (TextMain("texttops", argc, argv)); +} + + +/* + * 'WriteEpilogue()' - Write the PostScript file epilogue. + */ + +void +WriteEpilogue(void) +{ + puts("%%BeginTrailer"); + printf("%%%%Pages: %d\n", NumPages); + puts("%%EOF"); + + free(Page[0]); + free(Page); +} + + +/* + * 'WritePage()' - Write a page of text. + */ + +void +WritePage(void) +{ + int line; /* Current line */ + + + NumPages ++; + printf("%%%%Page: %d %d\n", NumPages, NumPages); + + puts("gsave"); + + if (PrettyPrint) + printf("%d H\n", NumPages); + + for (line = 0; line < SizeLines; line ++) + write_line(line, Page[line]); + + puts("grestore"); + puts("showpage"); + + memset(Page[0], 0, sizeof(lchar_t) * SizeColumns * SizeLines); +} + + +/* + * 'WriteProlog()' - Write the PostScript file prolog with options. + */ + +void +WriteProlog(char *title, /* I - Title of job */ + char *user) /* I - Username */ +{ + int line; /* Current output line */ + char *charset; /* Character set string */ + char filename[1024]; /* Glyph filenames */ + FILE *fp; /* Glyph files */ + int ch, unicode; /* Character values */ + char glyph[64]; /* Glyph name */ + int chars[256]; /* Character encoding array */ + time_t curtime; /* Current time */ + struct tm *curtm; /* Current date */ + char curdate[255]; /* Current date (text format) */ + + + curtime = time(NULL); + curtm = localtime(&curtime); + strftime(curdate, sizeof(curdate), "%c", curtm); + + puts("%!PS-Adobe-3.0"); + printf("%%%%BoundingBox: %.0f %.0f %.0f %.0f\n", PageLeft, PageBottom, + PageRight, PageTop); + if (Orientation & 1) + puts("%%Orientation: Landscape"); + puts("%%Creator: texttops/" CUPS_SVERSION); + printf("%%%%CreationDate: %s\n", curdate); + printf("%%%%Title: %s\n", title); + printf("%%%%For: %s\n", user); + if (PrettyPrint) + puts("%%DocumentNeededResources: font Courier Courier-Bold Courier-Oblique"); + else + puts("%%DocumentNeededResources: font Courier Courier-Bold"); + puts("%%DocumentSuppliedResources: procset texttops 1.0 0"); + puts("%%Pages: (atend)"); + + puts("%%EndComments"); + + SizeColumns = (PageRight - PageLeft) / 72.0 * CharsPerInch; + SizeLines = (PageTop - PageBottom) / 72.0 * LinesPerInch; + + Page = calloc(sizeof(lchar_t *), SizeLines); + Page[0] = calloc(sizeof(lchar_t), SizeColumns * SizeLines); + for (line = 1; line < SizeLines; line ++) + Page[line] = Page[0] + line * SizeColumns; + + if (PageColumns > 1) + { + ColumnGutter = CharsPerInch / 2; + ColumnWidth = (SizeColumns - ColumnGutter * (PageColumns - 1)) / + PageColumns; + } + else + ColumnWidth = SizeColumns; + + /* + * Get the output character set; if it is undefined or "us-ascii", do + * nothing because we can use the default encoding... + */ + + puts("%%BeginProlog"); + puts("%%BeginResource: procset texttops 1.0 0"); + + charset = getenv("CHARSET"); + if (charset != NULL && strcmp(charset, "us-ascii") != 0) + { + /* + * Load the PostScript glyph names and the corresponding character + * set definition... + */ + + memset(Glyphs, 0, sizeof(Glyphs)); + + if ((fp = fopen(CUPS_DATADIR "/data/psglyphs", "r")) != NULL) + { + while (fscanf(fp, "%x%s", &unicode, glyph) == 2) + Glyphs[unicode] = strdup(glyph); + + fclose(fp); + } + + if (strncmp(charset, "iso-", 4) == 0) + { + memset(chars, 0, sizeof(chars)); + + sprintf(filename, CUPS_DATADIR "/%s", charset + 4); + + if ((fp = fopen(filename, "r")) != NULL) + { + while (fscanf(fp, "%x%x", &ch, &unicode) == 2) + chars[ch] = unicode; + + fclose(fp); + } + } + else + { + /* + * UTF-8 encoding - just pass the first 256 characters for now... + */ + + UTF8 = 1; + + for (unicode = 0; unicode < 256; unicode ++) + chars[unicode] = unicode; + } + + /* + * Write the encoding array... + */ + + printf("%% %s encoding\n", charset); + puts("/textEncoding ["); + + for (ch = 0; ch < 256; ch ++) + { + if (Glyphs[chars[ch]]) + printf("/%s", Glyphs[chars[ch]]); + else + printf("/.notdef"); + + if ((ch & 7) == 7) + putchar('\n'); + } + + puts("] def"); + + puts("% Reencode fonts"); + puts("/Courier findfont"); + puts("dup length dict begin\n" + " { 1 index /FID ne { def } { pop pop } ifelse } forall\n" + " /Encoding textEncoding def\n" + " currentdict\n" + "end"); + puts("/Courier exch definefont pop"); + + puts("/Courier-Bold findfont"); + puts("dup length dict begin\n" + " { 1 index /FID ne { def } { pop pop } ifelse } forall\n" + " /Encoding textEncoding def\n" + " currentdict\n" + "end"); + puts("/Courier-Bold exch definefont pop"); + + if (PrettyPrint) + { + puts("/Courier-Oblique findfont"); + puts("dup length dict begin\n" + " { 1 index /FID ne { def } { pop pop } ifelse } forall\n" + " /Encoding textEncoding def\n" + " currentdict\n" + "end"); + puts("/Courier-Oblique exch definefont pop"); + } + } + + puts("% Define fonts"); + + printf("/FN /Courier findfont [%.1f 0 0 %.1f 0 0] makefont def\n", + 120.0 / CharsPerInch, 68.0 / LinesPerInch); + printf("/FB /Courier-Bold findfont [%.1f 0 0 %.1f 0 0] makefont def\n", + 120.0 / CharsPerInch, 68.0 / LinesPerInch); + if (PrettyPrint) + printf("/FI /Courier-Oblique findfont [%.1f 0 0 %.1f 0 0] makefont def\n", + 120.0 / CharsPerInch, 68.0 / LinesPerInch); + + puts("% Common procedures"); + + puts("/N { FN setfont moveto } bind def"); + puts("/B { FB setfont moveto } bind def"); + puts("/U { gsave 0 rlineto stroke grestore } bind def"); + + if (PrettyPrint) + { + if (ColorDevice) + { + puts("/S { 0.0 setgray show } bind def"); + puts("/r { 0.5 0.0 0.0 setrgbcolor show } bind def"); + puts("/g { 0.0 0.5 0.0 setrgbcolor show } bind def"); + puts("/b { 0.0 0.0 0.5 setrgbcolor show } bind def"); + } + else + { + puts("/S { 0.0 setgray show } bind def"); + puts("/r { 0.2 setgray show } bind def"); + puts("/g { 0.2 setgray show } bind def"); + puts("/b { 0.2 setgray show } bind def"); + } + + puts("/I { FI setfont moveto } bind def"); + + puts("/P 20 string def"); + printf("/T("); + + while (*title != '\0') + { + if (*title == '(' || *title == ')' || *title == '\\') + putchar('\\'); + + putchar(*title++); + } + + puts(")def"); + + puts("/H {"); + puts("gsave"); + puts("\t0.9 setgray"); + + if (Duplex) + { + puts("\tdup 2 mod 0 eq {"); + printf("\t\t%.1f %.1f translate } {\n", + PageWidth - PageRight, PageTop + 72.0f / LinesPerInch); + printf("\t\t%.1f %.1f translate } ifelse\n", + PageLeft, PageTop + 72.0f / LinesPerInch); + } + else + printf("\t%.1f %.1f translate\n", + PageLeft, PageTop + 72.0f / LinesPerInch); + + printf("\t0 0 %.1f %.1f rectfill\n", PageRight - PageLeft, + 144.0f / LinesPerInch); + + puts("\tFN setfont"); + puts("\t0 setgray"); + + if (Duplex) + { + puts("\tdup 2 mod 0 eq {"); + printf("\t\tT stringwidth pop neg %.1f add %.1f } {\n", + PageRight - PageLeft - 36.0f / LinesPerInch, 54.0f / LinesPerInch); + printf("\t\t%.1f %.1f } ifelse\n", 36.0f / LinesPerInch, + 54.0f / LinesPerInch); + } + else + printf("\t%.1f %.1f\n", 36.0f / LinesPerInch, + 54.0f / LinesPerInch); + + puts("\tmoveto T show"); + + printf("\t(%s)\n", curdate); + printf("\tdup stringwidth pop neg 2 div %.1f add %.1f\n", + (PageRight - PageLeft) * 0.5, 54.0f / LinesPerInch); + puts("\tmoveto show"); + + if (Duplex) + { + puts("\tdup P cvs exch 2 mod 0 eq {"); + printf("\t\t%.1f %.1f } {\n", 36.0f / LinesPerInch, + 54.0f / LinesPerInch); + printf("\t\tdup stringwidth pop neg %.1f add %.1f } ifelse\n", + PageRight - PageLeft - 36.0f / LinesPerInch, + 54.0f / LinesPerInch); + } + else + printf("\tP cvs dup stringwidth pop neg %.1f add %.1f\n", + PageRight - PageLeft - 36.0f / LinesPerInch, + 54.0f / LinesPerInch); + + puts("\tmoveto show"); + puts("\tgrestore"); + puts("} bind def"); + } + else + puts("/S { show } bind def"); + + puts("%%EndResource"); + + puts("%%EndProlog"); +} + + +/* + * 'write_line()' - Write a row of text. + */ + +static void +write_line(int row, /* I - Row number (0 to N) */ + lchar_t *line) /* I - Line to print */ +{ + int col; /* Current column */ + int attr; /* Current attribute */ + lchar_t *start; /* First character in sequence */ + + + for (col = 0, start = line; col < SizeColumns;) + { + while (col < SizeColumns && (line->ch == ' ' || line->ch == 0)) + { + col ++; + line ++; + } + + if (col >= SizeColumns) + break; + + attr = line->attr; + start = line; + + while (col < SizeColumns && line->ch != 0 && attr == line->attr) + { + col ++; + line ++; + } + + write_string(col - (line - start), row, line - start, start); + } +} + + +/* + * 'write_string()' - Write a string of text. + */ + +static void +write_string(int col, /* I - Start column */ + int row, /* I - Row */ + int len, /* I - Number of characters */ + lchar_t *s) /* I - String to print */ +{ + int i; /* Looping var */ + float x, y; /* Position of text */ + unsigned attr; /* Character attributes */ + + + /* + * Position the text and set the font... + */ + + if (Duplex && (NumPages & 1) == 0) + { + x = PageWidth - PageRight; + y = PageTop; + } + else + { + x = PageLeft; + y = PageTop; + } + + x += (float)col * 72.0 / (float)CharsPerInch; + y -= (float)(row + 1) * 72.0 / (float)LinesPerInch; + + attr = s->attr; + + if (attr & ATTR_RAISED) + y += 36.0 / (float)LinesPerInch; + else if (attr & ATTR_LOWERED) + y -= 36.0 / (float)LinesPerInch; + + if (x == (int)x) + printf("%.0f ", x); + else + printf("%.1f ", x); + + if (y == (int)y) + printf("%.0f ", y); + else + printf("%.1f ", y); + + if (attr & ATTR_BOLD) + putchar('B'); + else if (attr & ATTR_ITALIC) + putchar('I'); + else + putchar('N'); + + if (attr & ATTR_UNDERLINE) + printf(" %.1f U", (float)len * 72.0 / (float)CharsPerInch); + + /* + * See if the string contains 16-bit characters... + */ + + for (i = 0; i < len; i ++) + if (s[i].ch > 255) + break; + + if (i < len) + { + /* + * Write a hex Unicode string... + */ + + fputs(" 0) + { + printf("%04x", s->ch); + len --; + s ++; + } + + putchar('>'); + + if (attr & ATTR_RED) + puts("r"); + else if (attr & ATTR_GREEN) + puts("g"); + else if (attr & ATTR_BLUE) + puts("b"); + else + puts("S"); + } + else + { + /* + * Write a quoted string... + */ + + putchar('('); + + while (len > 0) + { + if (s->ch > 126) + { + /* + * Quote 8-bit characters... + */ + + printf("\\%03o", s->ch); + } + else + { + /* + * Quote the parenthesis and backslash as needed... + */ + + if (s->ch == '(' || s->ch == ')' || s->ch == '\\') + putchar('\\'); + + putchar(s->ch); + } + + len --; + s ++; + } + + putchar(')'); + + if (attr & ATTR_RED) + puts("r"); + else if (attr & ATTR_GREEN) + puts("g"); + else if (attr & ATTR_BLUE) + puts("b"); + else + puts("S"); + } +} + + +/* + * End of "$Id$". + */ diff --git a/filter/texttops.dsp b/filter/texttops.dsp new file mode 100644 index 0000000000..12b7cc6be7 --- /dev/null +++ b/filter/texttops.dsp @@ -0,0 +1,98 @@ +# Microsoft Developer Studio Project File - Name="texttops" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=texttops - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "texttops.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "texttops.mak" CFG="texttops - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "texttops - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "texttops - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "texttops - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W1 /GX /O2 /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 ../cups/cups.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"texttops.exe" + +!ELSEIF "$(CFG)" == "texttops - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W1 /Gm /GX /Zi /Od /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 ../cups/cupsd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"texttopsd.exe" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "texttops - Win32 Release" +# Name "texttops - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\texttops.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# End Target +# End Project diff --git a/locale/C/cups_C b/locale/C/cups_C new file mode 100644 index 0000000000..b053ecda3d --- /dev/null +++ b/locale/C/cups_C @@ -0,0 +1,116 @@ +us-ascii +OK +Cancel +Help +Quit +Close +Yes +No +Auto +On +Off +Save +Discard +Default +User-Defined +Options +More Info +Black +Color +Cyan +Magenta +Yellow +Copyright +All Rights Reserved +General +Printer +PostScript +Image +Text +HPGL +Advanced +Print Banner Page +Verbose Logging +Print Pages +Document +Entire Document +Page Range +Reverse Order +Page Format + 1-Up + 2-Up + 4-Up +Image Scaling +Use Natural Image Size +Zoom by Percent +Zoom by PPI +Mirror Image +Rotate Image +Best Fit +Color Saturation +Color Hue +Number of Columns +Margins +Wrap Text +Fit to Page +Shading +Default Pen Width +Gamma Correction +Brightness +Color Profile +Add Printer +Delete Printer +Modify Printer +Printer URI +Printer Name +Printer Location +Printer Info +Printer Make and Model +Device URI +Formatting Page +Printing Page +Initializing Printer +Printer State +Accepting Jobs +Not Accepting Jobs +Print Jobs +Class +Local +Remote +Duplexing +Stapling +Fast Copies +Collated Copies +Hole Punching +Covering +Binding +Sorting +Small (up to 9.5x14in) +Medium (9.5x14in to 13x19in) +Large (13x19in and larger) +Custom Size +Idle +Processing +Stopped +400 Your browser sent a request that this server could not understand. +This server could not verify that you are authorized to access the resource. +You must pay to access this server. +You don't have permission to access the resource on this server. +The requested resource was not found on this server. +The requested method is not allowed with the resource. +An appropriate representation for the resource was not found on this server. +You don't have permission to use this server as a proxy host. +The request has taken too long to complete and has been aborted. +The requested resource has more than one value. +The requested resource is gone and has not been replaced. +The requested method requires a valid Content-Length. +The precondition on the request evaluated to false. +The request is too large for this server to process. +The request URI is too large for this server to process. +The request format is not understood by this server. +500 The server has detected an unrecoverable error and cannot process your request. +The requested method is not implemented by this server. +The proxy server received an invalid response from an upstream server. +The requested resource is currently unavailable on this server. +The proxy server has taken too long to respond to this server. +This server does not support the HTTP version required by your browser. diff --git a/locale/Makefile b/locale/Makefile new file mode 100644 index 0000000000..b0b46a4765 --- /dev/null +++ b/locale/Makefile @@ -0,0 +1,60 @@ +# +# "$Id$" +# +# Locale file makefile for the Common UNIX Printing System (CUPS). +# +# Copyright 1993-1999 by Easy Software Products. +# +# These coded instructions, statements, and computer programs are the +# property of Easy Software Products and are protected by Federal +# copyright law. Distribution and use rights are outlined in the file +# "LICENSE.txt" which should have been included with this file. If this +# file is missing or damaged please contact Easy Software Products +# at: +# +# Attn: CUPS Licensing Information +# Easy Software Products +# 44141 Airport View Drive, Suite 204 +# Hollywood, Maryland 20636-3111 USA +# +# Voice: (301) 373-9603 +# EMail: cups-info@cups.org +# WWW: http://www.cups.org +# + +include ../Makedefs + +# +# Locales... +# + +LOCALES = C de en es fr it + +# +# Make everything... +# + +all: + +# +# Clean all config and object files... +# + +clean: + +# +# Install files... +# + +install: + -$(MKDIR) $(LIBDIR)/locale + for dir in $(LOCALES) ; do \ + if test ! -d $(LIBDIR)/locale/$$dir ; then \ + $(MKDIR) $(LIBDIR)/locale/$$dir ; \ + fi ; \ + $(CP) cups_$$dir $(LIBDIR)/locale/$$dir ; \ + done + +# +# End of "$Id$". +# diff --git a/locale/de/cups_de b/locale/de/cups_de new file mode 100644 index 0000000000..4d0921bcb3 --- /dev/null +++ b/locale/de/cups_de @@ -0,0 +1,116 @@ +iso-8859-1 +OK +Cancel +Help +Quit +Close +Yes +No +Auto +On +Off +Save +Discard +Default +User-Defined +Options +More Info +Black +Colour +Cyan +Magenta +Yellow +Copyright +All Rights Reserved +General +Printer +PostScript +Image +Text +HPGL +Advanced +Print Banner Page +Verbose Logging +Print Pages +Document +Entire Document +Page Range +Reverse Order +Page Format + 1-Up + 2-Up + 4-Up +Image Scaling +Use Natural Image Size +Zoom by Percent +Zoom by PPI +Mirror Image +Rotate Image +Best Fit +Colour Saturation +Colour Hue +Number of Columns +Margins +Wrap Text +Fit to Page +Shading +Default Pen Width +Gamma Correction +Brightness +Colour Profile +Add Printer +Delete Printer +Modify Printer +Printer URI +Printer Name +Printer Location +Printer Info +Printer Make and Model +Device URI +Formatting Page +Printing Page +Initializing Printer +Printer State +Accepting Jobs +Not Accepting Jobs +Print Jobs +Class +Local +Remote +Duplexing +Stapling +Fast Copies +Collated Copies +Hole Punching +Covering +Binding +Sorting +Small (up to 241x356mm) +Medium (241x356mm to 330x483mm) +Large (330x483mm and larger) +Custom Size +Idle +Processing +Stopped +400 Your browser sent a request that this server could not understand. +This server could not verify that you are authorized to access the resource. +You must pay to access this server. +You don't have permission to access the resource on this server. +The requested resource was not found on this server. +The requested method is not allowed with the resource. +An appropriate representation for the resource was not found on this server. +You don't have permission to use this server as a proxy host. +The request has taken too long to complete and has been aborted. +The requested resource has more than one value. +The requested resource is gone and has not been replaced. +The requested method requires a valid Content-Length. +The precondition on the request evaluated to false. +The request is too large for this server to process. +The request URI is too large for this server to process. +The request format is not understood by this server. +500 The server has detected an unrecoverable error and cannot process your request. +The requested method is not implemented by this server. +The proxy server received an invalid response from an upstream server. +The requested resource is currently unavailable on this server. +The proxy server has taken too long to respond to this server. +This server does not support the HTTP version required by your browser. diff --git a/locale/en/cups_en b/locale/en/cups_en new file mode 100644 index 0000000000..4d0921bcb3 --- /dev/null +++ b/locale/en/cups_en @@ -0,0 +1,116 @@ +iso-8859-1 +OK +Cancel +Help +Quit +Close +Yes +No +Auto +On +Off +Save +Discard +Default +User-Defined +Options +More Info +Black +Colour +Cyan +Magenta +Yellow +Copyright +All Rights Reserved +General +Printer +PostScript +Image +Text +HPGL +Advanced +Print Banner Page +Verbose Logging +Print Pages +Document +Entire Document +Page Range +Reverse Order +Page Format + 1-Up + 2-Up + 4-Up +Image Scaling +Use Natural Image Size +Zoom by Percent +Zoom by PPI +Mirror Image +Rotate Image +Best Fit +Colour Saturation +Colour Hue +Number of Columns +Margins +Wrap Text +Fit to Page +Shading +Default Pen Width +Gamma Correction +Brightness +Colour Profile +Add Printer +Delete Printer +Modify Printer +Printer URI +Printer Name +Printer Location +Printer Info +Printer Make and Model +Device URI +Formatting Page +Printing Page +Initializing Printer +Printer State +Accepting Jobs +Not Accepting Jobs +Print Jobs +Class +Local +Remote +Duplexing +Stapling +Fast Copies +Collated Copies +Hole Punching +Covering +Binding +Sorting +Small (up to 241x356mm) +Medium (241x356mm to 330x483mm) +Large (330x483mm and larger) +Custom Size +Idle +Processing +Stopped +400 Your browser sent a request that this server could not understand. +This server could not verify that you are authorized to access the resource. +You must pay to access this server. +You don't have permission to access the resource on this server. +The requested resource was not found on this server. +The requested method is not allowed with the resource. +An appropriate representation for the resource was not found on this server. +You don't have permission to use this server as a proxy host. +The request has taken too long to complete and has been aborted. +The requested resource has more than one value. +The requested resource is gone and has not been replaced. +The requested method requires a valid Content-Length. +The precondition on the request evaluated to false. +The request is too large for this server to process. +The request URI is too large for this server to process. +The request format is not understood by this server. +500 The server has detected an unrecoverable error and cannot process your request. +The requested method is not implemented by this server. +The proxy server received an invalid response from an upstream server. +The requested resource is currently unavailable on this server. +The proxy server has taken too long to respond to this server. +This server does not support the HTTP version required by your browser. diff --git a/locale/es/cups_es b/locale/es/cups_es new file mode 100644 index 0000000000..4d0921bcb3 --- /dev/null +++ b/locale/es/cups_es @@ -0,0 +1,116 @@ +iso-8859-1 +OK +Cancel +Help +Quit +Close +Yes +No +Auto +On +Off +Save +Discard +Default +User-Defined +Options +More Info +Black +Colour +Cyan +Magenta +Yellow +Copyright +All Rights Reserved +General +Printer +PostScript +Image +Text +HPGL +Advanced +Print Banner Page +Verbose Logging +Print Pages +Document +Entire Document +Page Range +Reverse Order +Page Format + 1-Up + 2-Up + 4-Up +Image Scaling +Use Natural Image Size +Zoom by Percent +Zoom by PPI +Mirror Image +Rotate Image +Best Fit +Colour Saturation +Colour Hue +Number of Columns +Margins +Wrap Text +Fit to Page +Shading +Default Pen Width +Gamma Correction +Brightness +Colour Profile +Add Printer +Delete Printer +Modify Printer +Printer URI +Printer Name +Printer Location +Printer Info +Printer Make and Model +Device URI +Formatting Page +Printing Page +Initializing Printer +Printer State +Accepting Jobs +Not Accepting Jobs +Print Jobs +Class +Local +Remote +Duplexing +Stapling +Fast Copies +Collated Copies +Hole Punching +Covering +Binding +Sorting +Small (up to 241x356mm) +Medium (241x356mm to 330x483mm) +Large (330x483mm and larger) +Custom Size +Idle +Processing +Stopped +400 Your browser sent a request that this server could not understand. +This server could not verify that you are authorized to access the resource. +You must pay to access this server. +You don't have permission to access the resource on this server. +The requested resource was not found on this server. +The requested method is not allowed with the resource. +An appropriate representation for the resource was not found on this server. +You don't have permission to use this server as a proxy host. +The request has taken too long to complete and has been aborted. +The requested resource has more than one value. +The requested resource is gone and has not been replaced. +The requested method requires a valid Content-Length. +The precondition on the request evaluated to false. +The request is too large for this server to process. +The request URI is too large for this server to process. +The request format is not understood by this server. +500 The server has detected an unrecoverable error and cannot process your request. +The requested method is not implemented by this server. +The proxy server received an invalid response from an upstream server. +The requested resource is currently unavailable on this server. +The proxy server has taken too long to respond to this server. +This server does not support the HTTP version required by your browser. diff --git a/locale/fr/cups_fr b/locale/fr/cups_fr new file mode 100644 index 0000000000..8325970595 --- /dev/null +++ b/locale/fr/cups_fr @@ -0,0 +1,116 @@ +iso-8859-1 +OK +Cancel +Aide +Quitté +Fin +Oui +Non +Automatique +Sur +Outre +Enregistrent +Jettent +Défaut +User-Defined +Options +More Info +Black +Couleur +Cyan +Magenta +Yellow +Copyright +Tous droits réservés +General +Imprimante +PostScript +Image +Text +HPGL +Advanced +Page D'Accueil D'Impression +Bavard Enregistrement +La Copie Pagine +Document +Entire Document +Page Range +Reverse Order +Page Format + 1-Up + 2-Up + 4-Up +Image Scaling +Use Natural Image Size +Zoom by Percent +Zoom by PPI +Mirror Image +Rotate Image +Best Fit +Saturation De Couleur +Tonalité De Couleur +Nombre de Colonnes +Margins +Wrap Text +Fit to Page +Shading +Default Pen Width +Gamma Correction +Brightness +Couleur Profile +Add Imprimante +Delete Imprimante +Modify Imprimante +URI D'Imprimante +Nom D'Imprimante +Emplacement D'Imprimante +L'Information D'Imprimante +L'imprimante Font et Modèlent +URI De Dispositif +Page de formatage +Imprimant la page +Imprimante D'Initialisation +Mode D'Imprimante +Les Travaux De Recevoir +Ne recevant pas Les Travaux +Print Jobs +Class +Local +Remote +Duplexing +Stapling +Fast Copies +Collated Copies +Hole Punching +Covering +Binding +Sorting +Petit (up to 241x356mm) +Moyenne (241x356mm to 330x483mm) +Grand (330x483mm and larger) +Faite sur Commande Taille +Idle +Processing +Stopped +400 Votre browser a envoyé une demande que ce serveur ne pourrait pas comprendre. +Ce serveur ne pourrait pas vérifier que vous êtes autorisés à accéder à la ressource. +You must pay to access this server. +You don't have permission to access the resource on this server. +La ressource demandée n'a pas été trouvée sur ce serveur. +The requested method is not allowed with the resource. +An appropriate representation for the resource was not found on this server. +You don't have permission to use this server as a proxy host. +The request has taken too long to complete and has been aborted. +The requested resource has more than one value. +The requested resource is gone and has not been replaced. +The requested method requires a valid Content-Length. +The precondition on the request evaluated to false. +The request is too large for this server to process. +The request URI is too large for this server to process. +The request format is not understood by this server. +500 The server has detected an unrecoverable error and cannot process your request. +The requested method is not implemented by this server. +The proxy server received an invalid response from an upstream server. +The requested resource is currently unavailable on this server. +The proxy server has taken too long to respond to this server. +This server does not support the HTTP version required by your browser. diff --git a/locale/it/cups_it b/locale/it/cups_it new file mode 100644 index 0000000000..4d0921bcb3 --- /dev/null +++ b/locale/it/cups_it @@ -0,0 +1,116 @@ +iso-8859-1 +OK +Cancel +Help +Quit +Close +Yes +No +Auto +On +Off +Save +Discard +Default +User-Defined +Options +More Info +Black +Colour +Cyan +Magenta +Yellow +Copyright +All Rights Reserved +General +Printer +PostScript +Image +Text +HPGL +Advanced +Print Banner Page +Verbose Logging +Print Pages +Document +Entire Document +Page Range +Reverse Order +Page Format + 1-Up + 2-Up + 4-Up +Image Scaling +Use Natural Image Size +Zoom by Percent +Zoom by PPI +Mirror Image +Rotate Image +Best Fit +Colour Saturation +Colour Hue +Number of Columns +Margins +Wrap Text +Fit to Page +Shading +Default Pen Width +Gamma Correction +Brightness +Colour Profile +Add Printer +Delete Printer +Modify Printer +Printer URI +Printer Name +Printer Location +Printer Info +Printer Make and Model +Device URI +Formatting Page +Printing Page +Initializing Printer +Printer State +Accepting Jobs +Not Accepting Jobs +Print Jobs +Class +Local +Remote +Duplexing +Stapling +Fast Copies +Collated Copies +Hole Punching +Covering +Binding +Sorting +Small (up to 241x356mm) +Medium (241x356mm to 330x483mm) +Large (330x483mm and larger) +Custom Size +Idle +Processing +Stopped +400 Your browser sent a request that this server could not understand. +This server could not verify that you are authorized to access the resource. +You must pay to access this server. +You don't have permission to access the resource on this server. +The requested resource was not found on this server. +The requested method is not allowed with the resource. +An appropriate representation for the resource was not found on this server. +You don't have permission to use this server as a proxy host. +The request has taken too long to complete and has been aborted. +The requested resource has more than one value. +The requested resource is gone and has not been replaced. +The requested method requires a valid Content-Length. +The precondition on the request evaluated to false. +The request is too large for this server to process. +The request URI is too large for this server to process. +The request format is not understood by this server. +500 The server has detected an unrecoverable error and cannot process your request. +The requested method is not implemented by this server. +The proxy server received an invalid response from an upstream server. +The requested resource is currently unavailable on this server. +The proxy server has taken too long to respond to this server. +This server does not support the HTTP version required by your browser. diff --git a/locale/locale.txt b/locale/locale.txt new file mode 100644 index 0000000000..f9abe72d67 --- /dev/null +++ b/locale/locale.txt @@ -0,0 +1,32 @@ +This directory contains the message strings used by CUPS for various +languages. Each subdirectory corresponds to a different locale, and +the cups_xx and cups_xx_YY files contain the messages for the locales +named "xx" or "xx_YY". + +Each message file starts with a character set identifier, which can be +one of the following: + + us-ascii + iso-8859-1 + iso-8859-2 + iso-8859-3 + iso-8859-4 + iso-8859-5 + iso-8859-6 + iso-8859-7 + iso-8859-8 + iso-8859-9 + utf-8 + +After that, all non-blank lines are treated as messages, with any +leading whitespace removed. If a line starts with a number then the +message index is updated to the number. Otherwise, the next message +number is used. + +The message indices are defined in the include file . +The HTTP status messages use the status codes defined in . + +If you would like to contribute a new message file for your locale, or +have corrections to the current ones, please send them to: + + cups-support@cups.org diff --git a/man/Makefile b/man/Makefile new file mode 100644 index 0000000000..a7ac786f31 --- /dev/null +++ b/man/Makefile @@ -0,0 +1,74 @@ +# +# "$Id$" +# +# Man page makefile for the Common UNIX Printing System (CUPS). +# +# Copyright 1993-1999 by Easy Software Products. +# +# These coded instructions, statements, and computer programs are the +# property of Easy Software Products and are protected by Federal +# copyright law. Distribution and use rights are outlined in the file +# "LICENSE.txt" which should have been included with this file. If this +# file is missing or damaged please contact Easy Software Products +# at: +# +# Attn: CUPS Licensing Information +# Easy Software Products +# 44141 Airport View Drive, Suite 204 +# Hollywood, Maryland 20636-3111 USA +# +# Voice: (301) 373-9603 +# EMail: cups-info@cups.org +# WWW: http://www.cups.org +# + +include ../Makedefs + +# +# Man pages... +# + +MAN1 = backend.1 filter.1 lprm.1 lpr.1 lpstat.1 lp.1 +MAN5 = classes.conf.5 cupsd.conf.5 mime.convs.5 mime.types.5 \ + printers.conf.5 +MAN8 = accept.8 cupsd.8 enable.8 lpadmin.8 lpc.8 + +# +# Make everything... +# + +all: $(MAN1:.1=.z) $(MAN5:.5=.z) $(MAN8:.8=.z) + +# +# Clean all config and object files... +# + +clean: + +# +# Install files... +# + +install: + -$(MKDIR) $(MANDIR)/man1 + $(CP) $(MAN1) $(MANDIR)/man1 + $(LN) lp.1 $(MANDIR)/man1/cancel.1 + -$(MKDIR) $(MANDIR)/man5 + $(CP) $(MAN5) $(MANDIR)/man5 + -$(MKDIR) $(MANDIR)/man8 + $(CP) $(MAN8) $(MANDIR)/man8 + $(LN) accept.8 $(MANDIR)/man8/reject.8 + $(LN) enable.8 $(MANDIR)/man8/disable.8 + -$(MKDIR) $(MANDIR)/cat1 + $(CP) $(CAT1) $(MANDIR)/cat1 + $(LN) lp.z $(MANDIR)/cat1/cancel.z + -$(MKDIR) $(MANDIR)/cat5 + $(CP) $(CAT5) $(MANDIR)/cat5 + -$(MKDIR) $(MANDIR)/cat8 + $(CP) $(CAT8) $(MANDIR)/cat8 + $(LN) accept.z $(MANDIR)/cat8/reject.z + $(LN) enable.z $(MANDIR)/cat8/disable.z + +# +# End of "$Id$". +# diff --git a/man/accept.8 b/man/accept.8 new file mode 100644 index 0000000000..63490d5ffe --- /dev/null +++ b/man/accept.8 @@ -0,0 +1,53 @@ +.\" +.\" "$Id: accept.8 327 1999-05-14 17:03:06Z mike $" +.\" +.\" accept/reject man page for the Common UNIX Printing System (CUPS). +.\" +.\" Copyright 1997-1999 by Easy Software Products. +.\" +.\" These coded instructions, statements, and computer programs are the +.\" property of Easy Software Products and are protected by Federal +.\" copyright law. Distribution and use rights are outlined in the file +.\" "LICENSE.txt" which should have been included with this file. If this +.\" file is missing or damaged please contact Easy Software Products +.\" at: +.\" +.\" Attn: CUPS Licensing Information +.\" Easy Software Products +.\" 44141 Airport View Drive, Suite 204 +.\" Hollywood, Maryland 20636-3111 USA +.\" +.\" Voice: (301) 373-9603 +.\" EMail: cups-info@cups.org +.\" WWW: http://www.cups.org +.\" +.TH accept 8 "Common UNIX Printing System" "14 May 1999" "Easy Software Products" +.SH NAME +accept/reject \- accept/reject jobs sent to a destination +.SH SYNOPSIS +.B accept +destination(s) +.br +.B reject +.I [ -r [ reason ] ] +destination(s) +.SH DESCRIPTION +\fBaccept\fR instructs the printing system to accept print jobs to the +specified destinations. +.LP +\fBreject\fR instructs the printing system to reject print jobs to the +specified destinations. The \fI-r\fR option sets the reason for rejecting +print jobs. If not specified the reason defaults to "Reason Unknown". +.SH COMPATIBILITY +The CUPS versions of \fBaccept\fR and \fBreject\fR may ask the user for an +access password depending on the printing system configuration. This differs +from the System V versions which require the root user to execute these +commands. +.SH SEE ALSO +cancel(1), disable(8), enable(8), lp(1), lpadmin(8), lpstat(1), +CUPS Software Administrator's Manual +.SH COPYRIGHT +Copyright 1993-1999 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: accept.8 327 1999-05-14 17:03:06Z mike $". +.\" diff --git a/man/accept.z b/man/accept.z new file mode 100644 index 0000000000000000000000000000000000000000..44afc6bc1ef4ecf849e5982497273543f019655f GIT binary patch literal 896 zc-jGg1AqJ<9smFZV+#NQ00ajG5()MxU6aWAJj!Vqv zG@XZ~)sS;fFspz6|N2y_M#Kb(nUJ^(83O{KD0B{=|I(#WHU@PSrCtxEN~CNI>MKgT zt3#i@nSHlTeLmL2+SGrlJ*47Ak znUE3yLC`qpIBX3JfWu(Y5I~F(HVq#G!r(4{|4b!Nr9!GH7)Ij#Y<;-Gt^J`|E?X^Z zDZI<>i}u|rRU>*XTQ4fm=gv?F!Ly*=u1<=3jJQw(g>|tI=}VepR8*pa1Q>pLjjgQTR{qef)R1}q{q1H=uH8jxR<;z;a@l!Shdd)Rp2ptvX-g)$KeQ{|Nqbp8 z|DQzCV70%t;84m-+RPHbA&n1U6e4774Icx-peTe883PEx6JXFh0nLL!5C}F6BLqWW zHh=#jg?P|O1H2bbdfLbPN$G^D6sT22BM97HmLIwuQAJ>_MJg3>d32f5@FTPzr`YC(E+T-)-8e!{UO|1Juy%#N(wiNf7ebIUU{Y_ytlrZGl+Q5&0=2niAm^u&i2p#dU6zbuG> zLP5VQicc=K2niAmKmV3R_L~qWNH#PQKaB-53A=|Nrq*G66t3aGoFl literal 0 Hc-jL100001 diff --git a/man/backend.1 b/man/backend.1 new file mode 100644 index 0000000000..6b89cef89e --- /dev/null +++ b/man/backend.1 @@ -0,0 +1,88 @@ +.\" +.\" "$Id: backend.1 327 1999-05-14 17:03:06Z mike $" +.\" +.\" backend man page for the Common UNIX Printing System (CUPS). +.\" +.\" Copyright 1997-1999 by Easy Software Products. +.\" +.\" These coded instructions, statements, and computer programs are the +.\" property of Easy Software Products and are protected by Federal +.\" copyright law. Distribution and use rights are outlined in the file +.\" "LICENSE.txt" which should have been included with this file. If this +.\" file is missing or damaged please contact Easy Software Products +.\" at: +.\" +.\" Attn: CUPS Licensing Information +.\" Easy Software Products +.\" 44141 Airport View Drive, Suite 204 +.\" Hollywood, Maryland 20636-3111 USA +.\" +.\" Voice: (301) 373-9603 +.\" EMail: cups-info@cups.org +.\" WWW: http://www.cups.org +.\" +.TH backend 1 "Common UNIX Printing System" "14 May 1999" "Easy Software Products" +.SH NAME +backend \- backend transmission interfaces +.SH SYNOPSIS +.B backend +job user title num-copies options +.I [ filename ] +.SH DESCRIPTION +The CUPS backend interface provides a standard method for sending document +files to different physical interfaces. +.LP +Backends must be capable of reading from a filename on the command-line +or from the standard input, copying stdin to a temporary if required by +the physical interface. +.LP +The command name (argv[0]) is set to the device URI of the destination printer. +.SH ENVIRONMENT VARIABLES +The following environment variables are defined by the CUPS server when +executing the backend: +.TP 5 +CHARSET +.br +The default text character set (typically us-ascii or iso-8859-1). +.TP 5 +LANG +.br +The default language locale (typically C or en). +.TP 5 +PATH +.br +The standard execution path for external programs that may be run by the backend. +.TP 5 +PPD +.br +The full pathname of the PostScript Printer Description (PPD) file for +this printer. +.TP 5 +RIP_CACHE +.br +The recommended amount of memory to use for Raster Image Processors (RIPs). +.TP 5 +SERVER_ROOT +.br +The root directory of the server. +.TP 5 +SOFTWARE +.br +The name and version number of the server (typically CUPS/1.0). +.TP 5 +TZ +.br +The timezone of the server (typically GMT). +.TP 5 +USER +.br +The user executing the backend (typically root). +.SH SEE ALSO +cupsd(8), filter(1) +CUPS Software Administrator's Manual, +CUPS Interface Design Description +.SH COPYRIGHT +Copyright 1993-1999 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: backend.1 327 1999-05-14 17:03:06Z mike $". +.\" diff --git a/man/backend.z b/man/backend.z new file mode 100644 index 0000000000000000000000000000000000000000..2baa1b475b9fffd5aee7e08abd3db70fe4cc8fbd GIT binary patch literal 1387 zc-oVfV_@Jo!Nb7Fz{JVT&(6Wd&7i=Q%8{6ynU`NwToMo*l9HB@lUq<)siCQ7=;-X~ z>E|C5pOl`hYw6+}T2`)O;qKuR7Fl6n;uH}bt8Zj%YULIll~q`!zG_iUW_0Djqa6SL z|Cc(cJ(KyF)QNjB2}Qkg_W%E{c5LeQIWhrVtK>F5x~8L<=p1IYA1pYx`N@q-+dl6+ z+CRx}%3St$HSg3nZr55YmSC80@U@&{3U_3h&cV|%NoUsoKe=YM*s--s!@{oTN1uzl z!P#i*8B@6{iVzPG+Awjo zRMHuVjV)m=MaRW9osC>P&7$c9f5fl#UHrVzws)_^0mI`l+lpq( z6)TlZJ#S&ir#>>HnYCHFv(5z2L9K z&d)nKS4nMLe9cB|L&VcQrA;bg4pqlnbu_Y$^+$XT%j1sFi8?wlQt-5lZqk9)Muw$L zZEG^SjrRXH<^KGj%Ye7|RP7$ai_Mp|pFb=qZZOMSKPBJleDNEQ%Xa<$lMtC!w4*Ji z;EL|w=G;}j=QYoApWL`K_c=q<`v1q6Tqhc2ZvFrNUzYgX^o=g*=MHYZ)vR>v+~ZTv z+h?uZxyDtrRE6)P>A8nez@$^MfRCNI!J(nhiREhjKQ1vF!TA6Gp8-8pE#g+CQ|T%Z z^d;e%az*8;*|UxWhD#o@-QxfZ`O{(E_{_5aVNL)rg9DZ$ny@N&upU{tYxcKY;CbHP~Yrjya(i83)QAO{>=;+X6) zNy(uR5>Cei<`pl_oujlK7>PCO6sHTC#{Zw;z%0dhbfPpkJgRR@eN%ZO^_XAt_Z1VZ z`=QF@`Avh1Bf7M%|NsBvz@{?{N-YhCK*5;70d)H3fPHyh2V&%FfXVO^D6&3>nwxek zTF1d<0t&)IXQbS~uK%i9_(nQ6D6i5lBMzJ^poV^IQB&{@4GmZz&y}=eK|@3T|Bn+q zHSD?NEI3bh&o{SOmb7W^QeX`Jf3#}Vs!mYIvWqAKLp57vT?+q7X~O#AXhi*7|=}g(n_7@QC4F^~AYHEEY-tJ#nV-GjB@1 zSdm}#Qj1Lm9Sq)F$ybsTvcPFBdA@b$o7{)y>LPW*ML98Z?y_Iyi8#cq5OtbON5VD5 zU8g`Xp~35*+L~Mc|D*_q>1nilbYx`UkqK~caPy5pbr^HfMfVds770(S|L69!kY{tt Q)leLOa0oo$TGhY;0GM&AfB*mh literal 0 Hc-jL100001 diff --git a/man/classes.conf.5 b/man/classes.conf.5 new file mode 100644 index 0000000000..5fb42a7b95 --- /dev/null +++ b/man/classes.conf.5 @@ -0,0 +1,36 @@ +.\" +.\" "$Id: classes.conf.5 327 1999-05-14 17:03:06Z mike $" +.\" +.\" classes.conf man page for the Common UNIX Printing System (CUPS). +.\" +.\" Copyright 1997-1999 by Easy Software Products. +.\" +.\" These coded instructions, statements, and computer programs are the +.\" property of Easy Software Products and are protected by Federal +.\" copyright law. Distribution and use rights are outlined in the file +.\" "LICENSE.txt" which should have been included with this file. If this +.\" file is missing or damaged please contact Easy Software Products +.\" at: +.\" +.\" Attn: CUPS Licensing Information +.\" Easy Software Products +.\" 44141 Airport View Drive, Suite 204 +.\" Hollywood, Maryland 20636-3111 USA +.\" +.\" Voice: (301) 373-9603 +.\" EMail: cups-info@cups.org +.\" WWW: http://www.cups.org +.\" +.TH classes.conf 5 "Common UNIX Printing System" "14 May 1999" "Easy Software Products" +.SH NAME +classes.conf \- class configuration file for cups +.SH DESCRIPTION +.SH SEE ALSO +cupsd(8), cupsd.conf(5), mime.convs(5), mime.types(5), printers.conf(5), +CUPS Software Administrator's Manual, +CUPS Interface Design Description +.SH COPYRIGHT +Copyright 1993-1999 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: classes.conf.5 327 1999-05-14 17:03:06Z mike $". +.\" diff --git a/man/classes.conf.z b/man/classes.conf.z new file mode 100644 index 0000000000000000000000000000000000000000..1d3b5b98f4d0dd93b88950aafca2de18c13b8b1e GIT binary patch literal 433 zc-oVfV_;wk;bLH9WMtzJ;$&q|;NnP5&C4$?(X(`R4G2z5%go6w($Lf~G<9_G^!4)( z3Q0*XD6Q0W_wWgg%qS~YH#Uh#ve>pUWFgyuW40&TMCAW}zSLMNzFc6-^t`6`YLOG$ z|05*jZrQnaPfT7?_^I~)->#(`W^9J<{F!g83TQjN)09grR%6BY%oVFk?(I8tG%@3( zM9sXOMJ03GJbEXt@M2jq;ii<62mi#ck}f}Oe%gyG9b6(Q>C!S`|NjjeBZPSv*ad%c zi#8fdd{>hQD3sgOZF0=^U;vMXMSrC0tQ7C5Im}#qO8@_bmdc8)XND+}Jn%yK#a@fn zCA(`PO{Wx1=z8h;x*_rLq{5V`g7yC`WLXN=b%*<^nM>Tz2)uFZVE2kJE!%5z)dePT zcrgkIfSk2p5(l@!k|k6B|9L)DZ&xc*@*`gp7B-d3z6X|~g+fD5)T$>T8p0Cs|4(e= zjnQ0kX4~ytROHg|@uc{XS(*F)KetVt_eQ4Tf?CrnD=mv;M1%|6_Ir6983N Bz0Uvu literal 0 Hc-jL100001 diff --git a/man/cupsd.8 b/man/cupsd.8 new file mode 100644 index 0000000000..3e81631af4 --- /dev/null +++ b/man/cupsd.8 @@ -0,0 +1,47 @@ +.\" +.\" "$Id: cupsd.8 327 1999-05-14 17:03:06Z mike $" +.\" +.\" cupsd man page for the Common UNIX Printing System (CUPS). +.\" +.\" Copyright 1997-1999 by Easy Software Products. +.\" +.\" These coded instructions, statements, and computer programs are the +.\" property of Easy Software Products and are protected by Federal +.\" copyright law. Distribution and use rights are outlined in the file +.\" "LICENSE.txt" which should have been included with this file. If this +.\" file is missing or damaged please contact Easy Software Products +.\" at: +.\" +.\" Attn: CUPS Licensing Information +.\" Easy Software Products +.\" 44141 Airport View Drive, Suite 204 +.\" Hollywood, Maryland 20636-3111 USA +.\" +.\" Voice: (301) 373-9603 +.\" EMail: cups-info@cups.org +.\" WWW: http://www.cups.org +.\" +.TH cupsd 8 "Common UNIX Printing System" "14 May 1999" "Easy Software Products" +.SH NAME +cupsd \- common unix printing system daemon +.SH SYNOPSIS +.B cups +.I [ \-c config-file ] +.SH DESCRIPTION +\fBcupsd\fR is the scheduler for the Common UNIX Printing System. It implements +a printing system based upon the Internet Printing Protocol, version 1.0. If +no options are specified on the command-line then the default configuration file +(usually \fI/var/cups/conf/cupsf.conf\fR) will be used. +.SH COMPATIBILITY +\fBcupsd\fR implements all of the required IPP/1.0 attributes and operations. +It also implements optional operation set 1 and several CUPS-specific +administation operations. +.SH SEE ALSO +classes.conf(5), cupsd.conf(5), mime.convs(5), mime.types(5), printers.conf(5), +CUPS Software Administrator's Manual, +CUPS Interface Design Description +.SH COPYRIGHT +Copyright 1993-1999 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: cupsd.8 327 1999-05-14 17:03:06Z mike $". +.\" diff --git a/man/cupsd.conf.5 b/man/cupsd.conf.5 new file mode 100644 index 0000000000..33d5781c8b --- /dev/null +++ b/man/cupsd.conf.5 @@ -0,0 +1,36 @@ +.\" +.\" "$Id: cupsd.conf.5 327 1999-05-14 17:03:06Z mike $" +.\" +.\" cupsd.conf man page for the Common UNIX Printing System (CUPS). +.\" +.\" Copyright 1997-1999 by Easy Software Products. +.\" +.\" These coded instructions, statements, and computer programs are the +.\" property of Easy Software Products and are protected by Federal +.\" copyright law. Distribution and use rights are outlined in the file +.\" "LICENSE.txt" which should have been included with this file. If this +.\" file is missing or damaged please contact Easy Software Products +.\" at: +.\" +.\" Attn: CUPS Licensing Information +.\" Easy Software Products +.\" 44141 Airport View Drive, Suite 204 +.\" Hollywood, Maryland 20636-3111 USA +.\" +.\" Voice: (301) 373-9603 +.\" EMail: cups-info@cups.org +.\" WWW: http://www.cups.org +.\" +.TH cupsd.conf 5 "Common UNIX Printing System" "14 May 1999" "Easy Software Products" +.SH NAME +cupsd.conf \- server configuration file for cups +.SH DESCRIPTION +.SH SEE ALSO +classes.conf(5), cupsd(8), mime.convs(5), mime.types(5), printers.conf(5), +CUPS Software Administrator's Manual, +CUPS Interface Design Description +.SH COPYRIGHT +Copyright 1993-1999 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: cupsd.conf.5 327 1999-05-14 17:03:06Z mike $". +.\" diff --git a/man/cupsd.conf.z b/man/cupsd.conf.z new file mode 100644 index 0000000000000000000000000000000000000000..84ac20774b428b6df0caa366ab8461eea379fe05 GIT binary patch literal 432 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 literal 0 Hc-jL100001 diff --git a/man/lp.1 b/man/lp.1 new file mode 100644 index 0000000000..cdc327e9f4 --- /dev/null +++ b/man/lp.1 @@ -0,0 +1,44 @@ +.\" +.\" "$Id: lp.1 327 1999-05-14 17:03:06Z mike $" +.\" +.\" lp/cancel man page for the Common UNIX Printing System (CUPS). +.\" +.\" Copyright 1997-1999 by Easy Software Products. +.\" +.\" These coded instructions, statements, and computer programs are the +.\" property of Easy Software Products and are protected by Federal +.\" copyright law. Distribution and use rights are outlined in the file +.\" "LICENSE.txt" which should have been included with this file. If this +.\" file is missing or damaged please contact Easy Software Products +.\" at: +.\" +.\" Attn: CUPS Licensing Information +.\" Easy Software Products +.\" 44141 Airport View Drive, Suite 204 +.\" Hollywood, Maryland 20636-3111 USA +.\" +.\" Voice: (301) 373-9603 +.\" EMail: cups-info@cups.org +.\" WWW: http://www.cups.org +.\" +.TH lp 1 "Common UNIX Printing System" "14 May 1999" "Easy Software Products" +.SH NAME +lp \- print files +.br +cancel \- cancel jobs +.SH SYNOPSIS +.B lpstat +.SH DESCRIPTION +\fBlpstat\fR +.SH COMPATIBILITY +Unlike the System V printing system, CUPS allows printer names to contain +any printable character except SPACE and TAB. Also, printer and class names are +\fBnot\fR case-sensitive. +.SH SEE ALSO +lpstat(1), +CUPS Software User's Manual +.SH COPYRIGHT +Copyright 1993-1999 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: lp.1 327 1999-05-14 17:03:06Z mike $". +.\" diff --git a/man/lp.z b/man/lp.z new file mode 100644 index 0000000000000000000000000000000000000000..1d781a4b77cc81a4724f85aba590125b1e2d0beb GIT binary patch literal 531 zc-jFI0_^=C9smFX3<>}N00RdO2Mq@VAP5R{Q(qJqbYBH0d~0im(6O zE>cvC#^%{9xw@j{v!vlNB>6n4DG5N?G%7-klS1Sy*)<73Y>lt~#y!ab8}=UGTCui| zz%585`$^&4RgJWGK3K!ovCd3JI*>{B*jNAWVD`tf^izGYC+vErx` V!6({J4%Vz~qyPW^|NM%o0YK!(_)h=; literal 0 Hc-jL100001 diff --git a/man/lpadmin.8 b/man/lpadmin.8 new file mode 100644 index 0000000000..5558641e97 --- /dev/null +++ b/man/lpadmin.8 @@ -0,0 +1,109 @@ +.\" +.\" "$Id: lpadmin.8 327 1999-05-14 17:03:06Z mike $" +.\" +.\" lpadmin man page for the Common UNIX Printing System (CUPS). +.\" +.\" Copyright 1997-1999 by Easy Software Products. +.\" +.\" These coded instructions, statements, and computer programs are the +.\" property of Easy Software Products and are protected by Federal +.\" copyright law. Distribution and use rights are outlined in the file +.\" "LICENSE.txt" which should have been included with this file. If this +.\" file is missing or damaged please contact Easy Software Products +.\" at: +.\" +.\" Attn: CUPS Licensing Information +.\" Easy Software Products +.\" 44141 Airport View Drive, Suite 204 +.\" Hollywood, Maryland 20636-3111 USA +.\" +.\" Voice: (301) 373-9603 +.\" EMail: cups-info@cups.org +.\" WWW: http://www.cups.org +.\" +.TH lpadmin 8 "Common UNIX Printing System" "14 May 1999" "Easy Software Products" +.SH NAME +lpadmin \- configure cups destinations +.SH SYNOPSIS +.B lpadmin +\-d +.I destination +.br +.B lpadmin +\-p +.I printer +.I option(s) +.br +.B lpadmin +\-x +.I destination +.SH DESCRIPTION +\fBlpadmin\fR configures printer and class queues provided by CUPS. It can also +be used to set the system default printer or class. +.LP +The first form of the command sets the default printer or class to +\fIdestination\fR. Subsequent print jobs submitted via the \fIlp(1)\fR or +\fIlpr(1)\fR commands will use this destination unless the user specifies +otherwise. +.LP +The second form of the command configures the named printer. The additional +options are described below. +.LP +The third form of the command deletes the printer or class \fIdestination\fR. +Any jobs that are pending for the destination will be removed and any job that +is currently printed will be aborted. +.SH CONFIGURATION OPTIONS +The following options are recognized when configuring a printer queue: +.TP 5 +\-c \fIclass\fR +.br +Adds the named \fIprinter\fR to \fIclass\fR. If \fIclass\fR does not +exist it is created automatically. +.TP 5 +\-i \fIinterface\fR +.br +Sets a System V style interface script for the printer. This option cannot +be specified with the \fI\-P\fR option (PPD file) and is intended for +providing support for legacy printer drivers. +.TP 5 +\-r \fIclass\fR +.br +Removes the named \fIprinter\fR from \fIclass\fR. If the resulting class +becomes empty it is removed. +.TP 5 +\-v \fIdevice-uri\fR +.br +Sets the \fIdevice-uri\fR attribute of the printer queue. If \fIdevice-uri\fR +is a filename it is automatically converted to the form \fBfile:/file/name\fR. +.TP 5 +\-F \fIfilter\fR +.br +Adds a filter for the printer. \fIFilter\fR is a string of the form +\fI"mime-type cost program"\fR, where \fImime-type\fR is a MIME type string +(e.g. "application/postscript", "text/*"), \fIcost\fR is a filtering cost from +0 to 100, and \fIprogram\fR is the filter program to use. If \fIprogram\fR +is not an absolute path then the filter is assumed to reside in the +scheduler's standard filter directory. +.TP 5 +\-P \fIppd-file\fR +.br +Specifies a PostScript Printer Description file to use with the printer. If +specified, this option overrides the \fI-i\fR option (interface script). +.SH COMPATIBILITY +Unlike the System V printing system, CUPS allows printer names to contain +any printable character except SPACE and TAB. Also, printer and class names are +\fBnot\fR case-sensitive. Also, the CUPS version of \fBlpadmin\fR may ask the +user for an access password depending on the printing system configuration. +This differs from the System V version which requires the root user to execute +this command. +.LP +The CUPS version of \fBlpadmin\fR does not support all of the System V +printing system configuration options. +.SH SEE ALSO +accept(8), cancel(1), disable(8), enable(8), lp(1), lpstat(1), reject(8), +CUPS Software Administrator's Manual +.SH COPYRIGHT +Copyright 1993-1999 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: lpadmin.8 327 1999-05-14 17:03:06Z mike $". +.\" diff --git a/man/lpadmin.z b/man/lpadmin.z new file mode 100644 index 0000000000000000000000000000000000000000..8ef541dd3dd66bc94b4767f57a88719d04c8c4e5 GIT binary patch literal 2502 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 HGY!n2Pnp>Q literal 0 Hc-jL100001 diff --git a/man/lpc.8 b/man/lpc.8 new file mode 100644 index 0000000000..0ce5029d99 --- /dev/null +++ b/man/lpc.8 @@ -0,0 +1,79 @@ +.\" +.\" "$Id: lpc.8 327 1999-05-14 17:03:06Z mike $" +.\" +.\" lpc man page for the Common UNIX Printing System (CUPS). +.\" +.\" Copyright 1997-1999 by Easy Software Products. +.\" +.\" These coded instructions, statements, and computer programs are the +.\" property of Easy Software Products and are protected by Federal +.\" copyright law. Distribution and use rights are outlined in the file +.\" "LICENSE.txt" which should have been included with this file. If this +.\" file is missing or damaged please contact Easy Software Products +.\" at: +.\" +.\" Attn: CUPS Licensing Information +.\" Easy Software Products +.\" 44141 Airport View Drive, Suite 204 +.\" Hollywood, Maryland 20636-3111 USA +.\" +.\" Voice: (301) 373-9603 +.\" EMail: cups-info@cups.org +.\" WWW: http://www.cups.org +.\" +.TH lpc 8 "Common UNIX Printing System" "14 May 1999" "Easy Software Products" +.SH NAME +lpc \- line printer control program +.SH SYNOPSIS +.B lpc +[ +.I command +[ +.I parameter(s) +] ] +.SH DESCRIPTION +\fBlpc\fR provides limited control over printer and class queues provided by +CUPS. It can also be used to query the state of queues. +.LP +If no command is specified on the command-line, \fRlpc\fR will display a +prompt and accept commands from the standard input. +.SH COMMANDS +The \fBlpc\fR program accepts a subset of commands accepted by the Berkeley +\fBlpc\fR program of the same name: +.TP 5 +\fIexit +.br +Exits the command interpreter. +.TP 5 +help \fI[command]\fR +.br +Displays a short help message. +.TP 5 +quit +.br +Exits the command interpreter. +.TP 5 +status \fI[queue]\fR +.br +Displays the status of one or more printer or class queues. +.TP 5 +? \fI[command]\fR +.br +Display a short help message. +.SH LIMITATIONS +Since \fBlpc\fR is geared towards the Berkeley printing system, it is impossible +to use \fBlpc\fR to configure printer or class queues provided by CUPS. To +configure printer or class queues you must use the \fBlpadmin(8)\fR command +or another CUPS-compatible client with that functionality. +.SH COMPATIBILITY +The CUPS version of \fBlpc\fR does not implement all of the standard Berkeley +commands. +.SH SEE ALSO +accept(8), cancel(1), disable(8), enable(8), lp(1), lpr(1), lprm(1), +lpstat(1), reject(8), +CUPS Software Administrator's Manual +.SH COPYRIGHT +Copyright 1993-1999 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: lpc.8 327 1999-05-14 17:03:06Z mike $". +.\" diff --git a/man/lpc.z b/man/lpc.z new file mode 100644 index 0000000000000000000000000000000000000000..9151be9a50263fbcb92c487ddbc3c7b9c940027c GIT binary patch literal 1264 zc-mEzdsNbA7{?JWc@H&&tilevTR;PWu=gTm#M7; z1MQr4rYoAu%GuHcmna3cvO=Ppxy-yBCExwB{j(O-NOKp-aPh9O40Nci&rfcJ{(;yzLRVM&okms%TC0>ILzBhh*j zuCxDfgxIu|Lj){T>1?~U$BX+9;mPYe6FOAQDSnu(1a{xT=0Zonwi-wON=*2G!~rZa ze`)ouE1Mox@1U%02nuLX3nQN$#hDEY6DghnoLn`PLeKSVwrbnNdsd0ynW>`Rtj$4h zIet7LW5G4{q?0)7RgsH3ip&5XuZ+-8aXM6aeV%fkefHbYeD2unJM+{-5&Uy~)GEz` z*ktzX(S8i*@iF&(6lmvD1wZSX9(wrx1VuRcXt1X7uX*;IBk_-NPi$sgk^as1CMmp-pI!r@TxV*<4C#9?GcRxd`R)YMa&eOzQ>!vkH)3- ze1ENp)5Pj(Nk2Gn)hLy@v^EI9$SaH=gY>scWW^b=nMbJtjUs0TIOd=QpuhH3-WH_! z@RCDOa_a&%RT2*`TXWiC7J8uDaL7&|Cr&C_XXJ|b>o003fWd7Rz zsC2`+3_DBk5y!khXP#`60AMV@3hVr}mtU@xt!Y>P))Tn30`fAY8DU-^FqtwbAEKSa z?3YkUJZOTvj)dIP%5U5UDkE2+(;-X7p6i3~M?>MU4;}2Z z2_phn1H-<7&U`HqMr{%`a2WSh>!GJ~ULqIqLZ@@_-dg!>f?*@Fok7}ZzOwnbN9ls= z_LG&(yjS%Lu8|eTR4Jl8MBv9y`%I!EWfzV0B!4B10$DEec5BS5(>W7Z?DPo3R(ui> zWY5NBs)}2>HBSRyDrVK0328o!GdJ#_Y4cAlAvo^@moJH`!8{ZX<#K)+br+3{Rn_Ij z|Ec)$OG!~c*Y|MF>-ylmQ0icfQMp^*XkFeGIV4LQkP@2Qd8R6SgVT6XpJ(r){!QTv z`j`Opmc^h=cik(Oc59xS!lQ>ASCMKQSBF~-`Ar8~ zk;v1*UzVRxO>yJxNZBPz@mJ?no*ROZY@zGBq8-agF=`)Q3q4~018bZ+gS)OM#4^AV zm0Crkbk`v$a^-Rdcj<^6G~tAO^N0eCBu6Il7^jFJNn21~%67kz%b5_H@J<;uG33kb zu(61e{R#V6Bz*O5IUL%K0u#J#rdG(sOeY?+Oz@;_6&8-0^%*W&KS+G&Q#;Fl00S5^ zWqt#qv9_CT@Dy|W4DPcXTC^Q0Lt%>v?~XNr(M@880!o%}lRnN!Y%to*4OaR`IUMdg zJa34;nWcyiN$e7(Gsl~bWw|`H%}i3CB?8;dRPxu1E9)&SU@7LPPii9Q?b84B*4jB3 X{#@Kg;cu=_r~Y~iij;A+C27UKF34~H literal 0 Hc-jL100001 diff --git a/man/lpr.1 b/man/lpr.1 new file mode 100644 index 0000000000..d7858745bb --- /dev/null +++ b/man/lpr.1 @@ -0,0 +1,41 @@ +.\" +.\" "$Id: lpr.1 327 1999-05-14 17:03:06Z mike $" +.\" +.\" lpr man page for the Common UNIX Printing System (CUPS). +.\" +.\" Copyright 1997-1999 by Easy Software Products. +.\" +.\" These coded instructions, statements, and computer programs are the +.\" property of Easy Software Products and are protected by Federal +.\" copyright law. Distribution and use rights are outlined in the file +.\" "LICENSE.txt" which should have been included with this file. If this +.\" file is missing or damaged please contact Easy Software Products +.\" at: +.\" +.\" Attn: CUPS Licensing Information +.\" Easy Software Products +.\" 44141 Airport View Drive, Suite 204 +.\" Hollywood, Maryland 20636-3111 USA +.\" +.\" Voice: (301) 373-9603 +.\" EMail: cups-info@cups.org +.\" WWW: http://www.cups.org +.\" +.TH lpr 1 "Common UNIX Printing System" "14 May 1999" "Easy Software Products" +.SH NAME +lpr \- print files +.SH SYNOPSIS +.B lpr +.SH DESCRIPTION +\fBlpr\fR +.SH COMPATIBILITY +The ... options are not supported by CUPS and will produce a warning message +if used. +.SH SEE ALSO +cancel(1), lp(1), lpstat(1), +CUPS Software User's Manual +.SH COPYRIGHT +Copyright 1993-1999 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: lpr.1 327 1999-05-14 17:03:06Z mike $". +.\" diff --git a/man/lpr.z b/man/lpr.z new file mode 100644 index 0000000000000000000000000000000000000000..0f8d82f00afff60754e92e92df25b56c6ef018b2 GIT binary patch literal 451 zc-jHO0X+U69smFWiwOV$0RaUL69)t!3J6nWY;tokIYUKBPf%20X>Mf({oRY6}ZEUoBj~OEolv0$NEkaOiw*UV5dlJMZ z7J|qr@_S{cNyB7n5`t2aa+(r?GKk3;fB$^FiDDBAPLq+8MaZu5Zu*$2g9Y{M_c6gOxh2YDG;RW-DB;7@b<&}H(Ah{Bx9e@8* zETk4yVtGeKDie08EUa8aMXi>fC!Z(cWJswL*=jP4|NMfB5Oczq7(Vs_m>53xBFc<~ zFfe@K$v0}`nJlCoj*FlGjx9xssQXTnk(5%Dhsg1=H3>i(L4o8QIZprna_kp^q{3Ou zG|&hchMH~=Up+{d+PNl6DF(HlM5qFbbxrFlyVCmg&`oE*@hESQt|;qyX>^v#}qwi=TkzcrGmvB{BYaflJ? zaoxCJgXqS^3dfEu7L;ed|Nl}YD~x)M8m$wwe(hEVf%9f=QLX83canlb1+4pNbsG;Jo2om`7Ujhq!ZBU}op#=45A4;NU6=PE5_oD=Id0bawUh4+u%l%rB_a(6RLO3kr=) z$t~5?)pPPmOV21*cX9U!ODZ!qiO8;4wOms=wOvL0|NsAn6T_nt!=z4_+i~_Q^&bEK z|L-Zcn~5h`S1l~kS*a1yW#qH||D7ed)0?v#)$etRDj&O@ILKdvuwkghu{{W{F- zl7xH^r`@HBc+uos1!bMg*EgQ4Ny~bu{Laz-|9wMq@~tY(eK#h5vyBA`B`BV~$de+` zyG`1`C2Hwwn?+~7+0@qmYjkAz>DQHHsxbNOh8rJ$>7^v^ZIPCpkoU8yXztk;n{?T_ z<3-jgcsstDu5ILFM<2lAU;ou|tt~h_tgt;-D&A|X-8ej}V<$oSjwanm zM@*v9v||Pw!;xYpu+i)udk;Z~5Mcw@c;*fo!L=45a}GI&V%RJhfXJ~C%pHIKOqx=Y zWLj`~frSSV>6BVTLjVE9dSw=o64Qg!3@A8_S1Quxy3LSbLBwDG){CDu#zm(Gs2EUj z8KDRx=)p;ar55U|eB`9Qj1-t!QEr4_ zM51$$j9D^x_Yw-6um9uQCd8{qmurjX;e&P>;@hU`~Uxn0@7Vyx#+4%FF1Ts)X(7m z|Ikxgc5K?6AQ4cV@lr<5wRhrj&+Grc#;o@4*4`!|w|Z*6Sa_c22H$plaob#Xk-Wt> zE^F=4l~m@NJaLNeWDif~Ctp;Vj9h-&)bz_LuQKYqRCuXO&$ZdZ$f)C|eEol)MFGtT zQTdS$hnhRSoLbN1*ue0})@b#CiJ5y-nYs9sfwphCw;=?`RQmsKH(!))66>I6%@AaJH*(Uk_U-s3|*9njN YnKBHXE_&MeVl&6q`2Rp4oXg+<0ChjPGynhq literal 0 Hc-jL100001 diff --git a/man/printers.conf.5 b/man/printers.conf.5 new file mode 100644 index 0000000000..490c506014 --- /dev/null +++ b/man/printers.conf.5 @@ -0,0 +1,36 @@ +.\" +.\" "$Id: printers.conf.5 327 1999-05-14 17:03:06Z mike $" +.\" +.\" printers.conf man page for the Common UNIX Printing System (CUPS). +.\" +.\" Copyright 1997-1999 by Easy Software Products. +.\" +.\" These coded instructions, statements, and computer programs are the +.\" property of Easy Software Products and are protected by Federal +.\" copyright law. Distribution and use rights are outlined in the file +.\" "LICENSE.txt" which should have been included with this file. If this +.\" file is missing or damaged please contact Easy Software Products +.\" at: +.\" +.\" Attn: CUPS Licensing Information +.\" Easy Software Products +.\" 44141 Airport View Drive, Suite 204 +.\" Hollywood, Maryland 20636-3111 USA +.\" +.\" Voice: (301) 373-9603 +.\" EMail: cups-info@cups.org +.\" WWW: http://www.cups.org +.\" +.TH printers.conf 5 "Common UNIX Printing System" "14 May 1999" "Easy Software Products" +.SH NAME +printers.conf \- printer configuration file for cups +.SH DESCRIPTION +.SH SEE ALSO +classes.conf(5), cupsd(8), cupsd.conf(5), mime.convs(5), mime.types(5), +CUPS Software Administrator's Manual, +CUPS Interface Design Description +.SH COPYRIGHT +Copyright 1993-1999 by Easy Software Products, All Rights Reserved. +.\" +.\" End of "$Id: printers.conf.5 327 1999-05-14 17:03:06Z mike $". +.\" diff --git a/man/printers.conf.z b/man/printers.conf.z new file mode 100644 index 0000000000000000000000000000000000000000..43157f31ce7d8d4bc34e09e54a8c20ebcba5979f GIT binary patch literal 434 zc-oVfV_;wk;$mQAWZ>iy;$&q|;NnP5&CJU$DlXBpbao90PE5-!(9qN|G<9_G^!4)( z3Q0-NDXr9X_wWgg%qS~YH#Uh#ve>p-+%C7LCq-^XqT~NRUzWtXah}oD*zRPY7CCwP zzcn#Gw;35us7h>Q-_{@TF4M58=P;9|6Z{dsx-QzL&)W<%iDyGfSSRa*{r@+t z3YwgftnlS97oYNt$Vg!x26n+WI%_&-oUk=G)ZB5UsMl~pMMyIjpVI$-i>G8x)?1w- z5l|?3;Dz#HmS + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/pstoraster/Makefile b/pstoraster/Makefile new file mode 100644 index 0000000000..b6bdc7e85e --- /dev/null +++ b/pstoraster/Makefile @@ -0,0 +1,148 @@ +# +# "$Id$" +# +# GNU Ghostscript makefile for the Common UNIX Printing System (CUPS). +# +# Copyright 1993-1999 by Easy Software Products. +# +# These coded instructions, statements, and computer programs are the +# property of Easy Software Products and are protected by Federal +# copyright law. Distribution and use rights are outlined in the file +# "LICENSE.txt" which should have been included with this file. If this +# file is missing or damaged please contact Easy Software Products +# at: +# +# Attn: CUPS Licensing Information +# Easy Software Products +# 44141 Airport View Drive, Suite 204 +# Hollywood, Maryland 20636-3111 USA +# +# Voice: (301) 373-9603 +# EMail: cups-info@cups.org +# WWW: http://www.cups.org +# +# This makefile and any derivative of it may be used and distributed +# freely under the terms of the GNU General Public License when +# used with GNU Ghostscript or its derivatives. Use of the makefile +# (or any derivative of it) with software other than GNU GhostScript +# (or its derivatives) is governed by the CUPS license agreement. +# + +include ../Makedefs + +# +# Object files... +# + +OBJS = gconf.o gdevabuf.o gdevcups.o gdevddrw.o gdevdflt.o \ + gdevemap.o gdevm1.o gdevm16.o gdevm2.o gdevm24.o \ + gdevm32.o gdevm4.o gdevm8.o gdevmem.o gdevmpla.o \ + gdevmrop.o gdevnfwd.o gdevpipe.o gdevprn.o gp_nofb.o \ + gp_unifn.o gp_unifs.o gp_unix.o gsalloc.o gsbitops.o \ + gsbittab.o gscdef.o gschar.o gschar0.o gscie.o \ + gscolor.o gscolor1.o gscolor2.o gscoord.o gscsepr.o \ + gsdevice.o gsdevmem.o gsdparam.o gsdps1.o gsfont.o \ + gsfont0.o gshsb.o gsht.o gsht1.o gshtscr.o gsimage.o \ + gsimpath.o gsinit.o gsiodev.o gsline.o gsmatrix.o \ + gsmemory.o gsmisc.o gspaint.o gsparam.o gspath.o \ + gspath1.o gspcolor.o gsrop.o gsroptab.o gsstate.o \ + gstype1.o gstype42.o gsutil.o gxacpath.o gxbcache.o \ + gxccache.o gxccman.o gxcht.o gxclbits.o gxclfile.o \ + gxclimag.o gxclip2.o gxclist.o gxclpath.o gxclread.o \ + gxcmap.o gxcpath.o gxctable.o gxdcconv.o gxdcolor.o \ + gxdither.o gxfill.o gxhint1.o gxhint2.o gxhint3.o \ + gxht.o gximage.o gximage0.o gximage1.o gximage2.o \ + gximage3.o gximage4.o gximage5.o gxpaint.o gxpath.o \ + gxpath2.o gxpcmap.o gxpcopy.o gxpdash.o gxstroke.o \ + ialloc.o ibnum.o iccinit0.o iconf.o idebug.o idict.o \ + idparam.o igc.o igcref.o igcstr.o iinit.o ilocate.o \ + imain.o iname.o interp.o iparam.o ireclaim.o isave.o \ + iscan.o iscanbin.o iscannum.o iscantab.o istack.o \ + iutil.o iutil2.o pstoraster.o sbcp.o sbhc.o sbwbs.o \ + scfd.o scfdtab.o scfe.o scfetab.o sdctc.o sdctd.o \ + sdcte.o seexec.o sfile.o sfilter1.o sfilter2.o shc.o \ + shcgen.o siscale.o sjpegc.o sjpegd.o sjpege.o \ + sjpegerr.o slzwc.o slzwce.o slzwd.o smtf.o spcxd.o \ + spdiff.o spngp.o srld.o srle.o sstring.o stream.o \ + szlibc.o szlibd.o szlibe.o zarith.o zarray.o zbseq.o \ + zchar.o zchar1.o zchar2.o zchar42.o zcharout.o zcie.o \ + zcolor.o zcolor1.o zcolor2.o zcontrol.o zcrd.o \ + zcsindex.o zcssepr.o zdevcal.o zdevice.o zdevice2.o \ + zdict.o zdps1.o zfbcp.o zfdctc.o zfdctd.o zfdcte.o \ + zfdecode.o zfile.o zfileio.o zfilter.o zfilter2.o \ + zfilterx.o zfname.o zfont.o zfont0.o zfont1.o zfont2.o \ + zfont42.o zfproc.o zfzlib.o zgeneric.o zgstate.o zhsb.o \ + zht.o zht1.o zht2.o zimage2.o ziodev.o ziodev2.o \ + zmath.o zmatrix.o zmedia2.o zmisc.o zmisc1.o zmisc2.o \ + zpacked.o zpaint.o zpath.o zpath1.o zpcolor.o zrelbit.o \ + zstack.o zstring.o zsysvm.o ztoken.o ztype.o zupath.o \ + zusparam.o zvmem.o zvmem2.o + +# +# Data files... +# + +DFILES = Fontmap gs_btokn.ps gs_ccfnt.ps gs_cidfn.ps gs_cmap.ps \ + gs_cmdl.ps gs_dbt_e.ps gs_diskf.ps gs_dps1.ps \ + gs_fform.ps gs_fonts.ps gs_init.ps gs_iso_e.ps \ + gs_kanji.ps gs_ksb_e.ps gs_l2img.ps gs_lev2.ps \ + gs_mex_e.ps gs_mro_e.ps gs_pdfwr.ps gs_pdf.ps \ + gs_pdf_e.ps gs_pfile.ps gs_res.ps gs_setpd.ps \ + gs_statd.ps gs_std_e.ps gs_sym_e.ps gs_ttf.ps \ + gs_typ42.ps gs_type1.ps gs_wan_e.ps gs_wl1_e.ps \ + gs_wl2_e.ps gs_wl5_e.ps pdf_2ps.ps pdf_base.ps \ + pdf_draw.ps pdf_font.ps pdf_main.ps pdf_sec.ps \ + pfbtogs.ps + +# +# Targets... +# + +TARGETS = genarch arch.h pstoraster + +# +# Make everything... +# + +all: $(TARGETS) + +# +# Clean all config and object files... +# + +clean: + $(RM) $(TARGETS) + $(RM) $(OBJS) + +# +# Install files... +# + +install: $(TARGETS) + -$(MKDIR) $(SERVERROOT)/filter + $(CP) pstoraster $(SERVERROOT)/filter + -$(MKDIR) $(DATADIR)/pstoraster + $(CP) $(DFILES) $(DATADIR)/pstoraster + +# +# genarch - generate the architecture configuration file. +# + +genarch: genarch.o + $(CC) $(LDFLAGS) -o genarch genarch.o +arch.h: genarch + ./genarch arch.h + +# +# pstoraster - PostScript conversion filter. +# + +pstoraster: $(OBJS) ../Makedefs ../cups/libcups.a + $(CC) $(LDFLAGS) -o pstoraster $(OBJS) $(IMGLIBS) + +$(OBJS): arch.h ../config.h ../Makedefs +gconf.o iconf.o gscdef.o: gconfig.h + +# +# End of "$Id$". +# diff --git a/pstoraster/bfont.h b/pstoraster/bfont.h new file mode 100644 index 0000000000..a653ce3998 --- /dev/null +++ b/pstoraster/bfont.h @@ -0,0 +1,54 @@ +/* Copyright (C) 1992, 1995, 1996 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to + anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer to + the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given to + you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises is not affiliated with the Free Software Foundation or + the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, + does not depend on any other GNU software. +*/ + +/* bfont.h */ +/* Interpreter internal routines and data needed for building fonts */ +/* Requires gxfont.h */ +#include "ifont.h" + +/* In zfont.c */ +int add_FID(P2(ref *pfdict, gs_font *pfont)); +font_proc_make_font(zdefault_make_font); +font_proc_make_font(zbase_make_font); +/* The global font directory */ +extern gs_font_dir *ifont_dir; + +/* Structure for passing BuildChar and BuildGlyph procedures. */ +typedef struct build_proc_refs_s { + ref BuildChar; + ref BuildGlyph; +} build_proc_refs; + +/* In zfont2.c */ +int build_proc_name_refs(P3(build_proc_refs *pbuild, + const char _ds *bcstr, + const char _ds *bgstr)); +int build_gs_font_procs(P2(os_ptr, build_proc_refs *)); +int build_gs_primitive_font(P5(os_ptr, gs_font_base **, font_type, + gs_memory_type_ptr_t, const build_proc_refs *)); +int build_gs_simple_font(P5(os_ptr, gs_font_base **, font_type, + gs_memory_type_ptr_t, const build_proc_refs *)); +void lookup_gs_simple_font_encoding(P1(gs_font_base *)); +int build_gs_font(P5(os_ptr, gs_font **, font_type, + gs_memory_type_ptr_t, const build_proc_refs *)); +int define_gs_font(P1(gs_font *)); diff --git a/pstoraster/bseq.h b/pstoraster/bseq.h new file mode 100644 index 0000000000..46dab4a60f --- /dev/null +++ b/pstoraster/bseq.h @@ -0,0 +1,66 @@ +/* Copyright (C) 1990, 1994 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to + anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer to + the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given to + you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises is not affiliated with the Free Software Foundation or + the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, + does not depend on any other GNU software. +*/ + +/* bseq.h */ +/* Definitions for Level 2 binary object sequences */ + +/* Binary object sequence element types */ +typedef enum { + bs_null = 0, + bs_integer = 1, + bs_real = 2, + bs_name = 3, + bs_boolean = 4, + bs_string = 5, + bs_eval_name = 6, + bs_array = 9, + bs_mark = 10, + /* + * We extend the PostScript language definition by allowing + * dictionaries in binary object sequences. The data for + * a dictionary is like that for an array, with the following + * changes: + * - If the size is an even number, the value is the index of + * the first of a series of alternating keys and values. + * - If the size is 1, the value is the index of another + * object (which must also be a dictionary, and must not have + * size = 1); this object represents the same object as that one. + */ + bs_dictionary = 15 +} bin_seq_type; +#define bs_executable 128 + +/* Definition of an object in a binary object sequence. */ +typedef struct { + byte tx; /* type and executable flag */ + byte unused; + union { + bits16 w; + byte b[2]; + } size; + union { + bits32 w; + float f; + byte b[4]; + } value; +} bin_seq_obj; diff --git a/pstoraster/btoken.h b/pstoraster/btoken.h new file mode 100644 index 0000000000..69a7d63e91 --- /dev/null +++ b/pstoraster/btoken.h @@ -0,0 +1,65 @@ +/* Copyright (C) 1990 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to + anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer to + the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given to + you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises is not affiliated with the Free Software Foundation or + the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, + does not depend on any other GNU software. +*/ + +/* btoken.h */ +/* Definitions for Level 2 binary tokens */ + +/* Binary token types */ +typedef enum { + bt_seq = 128, + bt_seq_IEEE_msb = 128, /* binary object sequence, */ + /* IEEE floats, big-endian */ + bt_seq_IEEE_lsb = 129, /* ditto, little-endian */ + bt_seq_native_msb = 130, /* ditto, native floats, big-endian */ + bt_seq_native_lsb = 131, /* ditto, little-endian */ + bt_int32_msb = 132, + bt_int32_lsb = 133, + bt_int16_msb = 134, + bt_int16_lsb = 135, + bt_int8 = 136, + bt_fixed = 137, + bt_float_IEEE_msb = 138, + bt_float_IEEE_lsb = 139, + bt_float_native = 140, + bt_boolean = 141, + bt_string_256 = 142, + bt_string_64k_msb = 143, + bt_string_64k_lsb = 144, + bt_litname_system = 145, + bt_execname_system = 146, + bt_litname_user = 147, + bt_execname_user = 148, + bt_num_array = 149 +} bt_char; +#define bt_char_min 128 +#define bt_char_max 159 + +/* Define the number of required initial bytes for binary tokens */ +/* (including the token type byte). */ +extern const byte bin_token_bytes[]; /* in iscan2.c */ +#define bin_token_bytes_values\ + 4, 4, 4, 4, 5, 5, 3, 3, 2, 2, 5, 5, 5,\ + 2, 2, 3, 3, 2, 2, 2, 2, 4,\ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 /* undefined */ +#define binary_token_bytes(btchar)\ + (bin_token_bytes[(btchar) - bt_char_min]) diff --git a/pstoraster/ctype_.h b/pstoraster/ctype_.h new file mode 100644 index 0000000000..42af5c4a38 --- /dev/null +++ b/pstoraster/ctype_.h @@ -0,0 +1,31 @@ +/* Copyright (C) 1993 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to + anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer to + the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given to + you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises is not affiliated with the Free Software Foundation or + the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, + does not depend on any other GNU software. +*/ + +/* ctype_.h */ +/* Wrapper for ctype.h */ + +/* We must include std.h before any file that includes sys/types.h. */ +#include "std.h" + +/* ... and that's the only reason for having this file at all. */ +#include diff --git a/pstoraster/dirent_.h b/pstoraster/dirent_.h new file mode 100644 index 0000000000..548de3bab9 --- /dev/null +++ b/pstoraster/dirent_.h @@ -0,0 +1,50 @@ +/* + Copyright 1993-1999 by Easy Software Products. + Copyright (C) 1993 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to + anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer to + the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given to + you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises is not affiliated with the Free Software Foundation or + the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, + does not depend on any other GNU software. +*/ + +/* dirent_.h */ +/* Generic substitute for Unix dirent.h */ + +/* We must include std.h before any file that includes sys/types.h. */ +#include "std.h" + +#include + +/* Directory entries may be defined in quite a number of different */ +/* header files. The following switches are defined in gconfig_.h. */ +#ifdef HAVE_DIRENT_H +# include +typedef struct dirent dir_entry; +#else +# if HAVE_SYS_NDIR_H +# include +# endif +# if HAVE_SYS_DIR_H +# include +# endif +# if HAVE_NDIR_H +# include +# endif +typedef struct direct dir_entry; +#endif diff --git a/pstoraster/dstack.h b/pstoraster/dstack.h new file mode 100644 index 0000000000..b897393c5a --- /dev/null +++ b/pstoraster/dstack.h @@ -0,0 +1,307 @@ +/* Copyright (C) 1992, 1996 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to + anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer to + the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given to + you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises is not affiliated with the Free Software Foundation or + the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, + does not depend on any other GNU software. +*/ + +/* dstack.h */ +/* Definitions for the dictionary stack */ +#include "istack.h" + +/* Define the dictionary stack and systemdict. */ +extern ref_stack d_stack; +extern ref ref_systemdict; +#define systemdict (&ref_systemdict) + +/* Define the dictionary stack pointers. */ +typedef s_ptr ds_ptr; +typedef const_s_ptr const_ds_ptr; +#define dsbot (d_stack.bot) +#define dsp (d_stack.p) +#define dstop (d_stack.top) + +/* Macro to ensure enough room on the dictionary stack */ +#define check_dstack(n)\ + if ( dstop - dsp < (n) )\ + { d_stack.requested = (n); return_error(e_dictstackoverflow); } + +/* Check whether a dictionary is one of the permanent ones on the d-stack. */ +bool dict_is_permanent_on_dstack(P1(const ref *)); + +/* + * Switching between Level 1 and Level 2 involves inserting and removing + * globaldict on the dictionary stack. Instead of truly inserting and + * removing entries, we replace globaldict by a copy of systemdict in + * Level 1 mode. min_dstack_size, the minimum number of entries, does not + * change depending on language level; the countdictstack and dictstack + * operators must take this into account. + */ +extern uint min_dstack_size; + +/* + * The dictionary stack is implemented as a linked list of blocks; + * operators that access the entire d-stack must take this into account. + * These are: + * countdictstack dictstack + * In addition, name lookup requires searching the entire stack, not just + * the top block, and the underflow check for the dictionary stack + * (`end' operator) is not just a check for underflowing the top block. + */ + +/* + * Cache a value for fast checking of def operations. + * If the top entry on the dictionary stack is a writable dictionary, + * dsspace is the space of the dictionary; if it is a non-writable + * dictionary, dsspace = -1. Then def is legal precisely if + * r_space(pvalue) <= dsspace. Note that in order for this trick to work, + * the result of r_space must be a signed integer; some compilers treat + * enums as unsigned, probably in violation of the ANSI standard. + */ +extern int dsspace; +#define dtop_can_store(pvalue) ((int)r_space(pvalue) <= dsspace) +/* + * Cache values for fast name lookup. If the top entry on the dictionary + * stack is a readable dictionary with packed keys, dtop_keys, dtop_npairs, + * and dtop_values are keys.value.packed, npairs, and values.value.refs + * for that dictionary; otherwise, these variables point to a dummy + * empty dictionary. + */ +extern const ref_packed *dtop_keys; +extern uint dtop_npairs; +extern ref *dtop_values; +/* + * Reset the cached top values. Every routine that alters the + * dictionary stack (including changing the protection or size of the + * top dictionary on the stack) must call this. + */ +void dict_set_top(P0()); + +/* + * Define a special fast entry for name lookup in the interpreter. + * The key is known to be a name; search the entire dict stack. + * Return the pointer to the value slot. + * If the name isn't found, just return 0. + */ +ref *dict_find_name_by_index(P1(uint nidx)); +#define dict_find_name(pnref) dict_find_name_by_index(name_index(pnref)) + +/* Define some auxiliary macros needed for inline code. */ + +#define hash_mod_large(hash, size) ((hash) & ((size) - 1)) +#define hash_mod_small(hash, size) ((hash) % (size)) +#define dict_round_size_large(asize)\ + while ( asize & (asize - 1) ) asize = (asize | (asize - 1)) + 1 +#define dict_round_size_small(asize)\ + DO_NOTHING +#if arch_small_memory +# define hash_mod(h, s) hash_mod_small(h, s) +# define dict_round_size(s) dict_round_size_small(s) +#else +# ifdef DEBUG +# define hash_mod(h, s)\ + (gs_debug_c('.') ? hash_mod_small(h, s) : hash_mod_large(h, s)) +# define dict_round_size(s)\ + if ( !gs_debug_c('.') ) dict_round_size_large(s) +# else +# define hash_mod(h, s) hash_mod_large(h, s) +# define dict_round_size(s) dict_round_size_large(s) +# endif +#endif + +/* Define the hashing function for names. */ +/* We don't have to scramble the index, because */ +/* indices are assigned in a scattered order (see name_ref in iname.c). */ +#define dict_name_index_hash(nidx) (nidx) + +/* + * Define an extra-fast macro for name lookup, optimized for + * a single-probe lookup in the top dictionary on the stack. + * Amazingly enough, this seems to hit over 90% of the time + * (aside from operators, of course, which are handled either with + * the special cache pointer or with 'bind'). + */ +#define dict_find_name_by_index_inline(nidx,htemp)\ + (dtop_keys[htemp = hash_mod(dict_name_index_hash(nidx),\ + dtop_npairs) + 1] == pt_tag(pt_literal_name) + (nidx) ?\ + dtop_values + htemp : dict_find_name_by_index(nidx)) +/* + * Define a similar macro that only checks the top dictionary on the stack. + */ +#define if_dict_find_name_by_index_top(nidx,htemp,pvslot)\ + if ( ((dtop_keys[htemp = hash_mod(dict_name_index_hash(nidx),\ + dtop_npairs) + 1] == pt_tag(pt_literal_name) + (nidx)) ?\ + ((pvslot) = dtop_values + (htemp), 1) :\ + 0)\ + ) + +/* +Notes on dictionary lookup performance +-------------------------------------- + +We mark heavily used operations with a * below; moderately heavily used +operations with a +. + +The following operations change the dictionary stack: + +begin, +end + readonly (on a dictionary that is on the stack) + noaccess (on a dictionary that is on the stack) +We implement cleardictstack as a series of ends. + +The following operations change the contents of dictionaries: + *def, +put + undef + restore + .setmaxlength +We implement store in PostScript, and copy as a series of puts. Many +other operators also do puts (e.g., ScaleMatrix in makefont, +Implementation in makepattern, ...). Note that put can do an implicit +.setmaxlength (if it has to grow the dictionary). + +The following operations look up keys on the dictionary stack: + *(interpreter name lookup) + load + where + +Current design +-------------- + +Each name has a pointer that has one of 3 states: + - This name has no definitions. + - This name has exactly one definition, in systemdict or userdict. + In this case, the pointer points to the value slot. + - This name has some other status. + +We cache some pointers to the top dictionary on the stack if it is a +readable dictionary with packed keys, which allows us to do fast, +single-probe lookups in this dictionary. We also cache a value that +allows us to do a fast check for stores into the top dictionary +(writability + space check). + +Full shallow binding +-------------------- + +We implement shallow binding with a pointer in each name that points to +the value slot that holds the name's definition. If the name is +undefined, or if we don't know where the slot is, the binding pointer +points to a ref with a special type t__invalid, which cannot occur +anywhere else. "Clearing" the pointer means setting it to point to this +ref. + +We also maintain a pair of pointers that bracket the value region of the +top dictionary on the stack, for fast checking in def. If the top +dictionary is readonly or noaccess, the pointers designate an empty area. +We call this the "def region" cache. + +We implement the above operations as follows: + begin - push the dictionary on the stack; set the pointers of + all name keys to point to the corresponding value slots. + end - pop the stack; clear the pointers of all name keys. + readonly - if the dictionary is the top one on the stack, + reset the def region cache. + noaccess - clear the pointers of all name keys. (This is overly + conservative, but this is a very rare operation.) + Also reset the def region cache if the dictionary is + the top one on the stack. + def - if the key is a name and its pointer points within the cached + def region, store the value through the pointer; otherwise, + look up the key in the top dictionary, store the value, + and if the key is a name, set its pointer to the value slot. + put - if the key is a name and wasn't in the dictionary before, + clear its pointer. (Conservative, but rare.) + undef - if the key is a name, clear its pointer. (Overly + conservative, but rare.) + restore - if either the old or the new value of a change is a name + (possibly in a packed array), clear its pointer. This is + conservative, but easy to detect, and probably not *too* + conservative. + .setmaxlength - clear all the pointers, like noaccess. + (name lookup) - fetch the value through the pointer and dispatch + on its type; if the type is t__invalid, do a full search + and set the pointer. This avoids a separate check for a + clear pointer in the usual case where the pointer is valid. + load - if the pointer is clear, do a search and set the pointer; + then fetch the value. + where - always do a full search and set the pointer. + (Conservative, but rare.) + +One place where shallow binding will result in major new overhead is the +extra push of systemdict for loading fonts. This probably isn't a problem +in real life. + +Adaptive shallow binding +------------------------ + +We do validity checking for the name value cache using an epoch counter. +For each dictionary D, we keep an on-stack flag F. Each dictionary stack +entry is where D is the actual dictionary, M is a mark vector of +V bits (V is a system constant, probably 64), F is D's former on-stack +flag, and E is the epoch at which the entry was made. For each name K, we +keep a cache where P is a pointer to the dictionary value slot that +holds the current value of K, and E is an epoch value; the cache is valid +if K->E >= dsp->E. Here is what happens for each operation: + +****** Still need to handle names defined only in systemdict or userdict? + +To initialize: + Epoch = 0 +To clear the cache entry for K: + *K = +begin(D): + *++dsp = F, ++Epoch> + set D->F +value = lookup(K): + if K->E >= dsp->E + value = *K->P + else + do lookup as usual + *K = + set dp->M[i mod V] where dp is the dstack slot of the dictionary + where K was found and i is the index within that dictionary +end: + for each i such that dsp->M[i] is set, + clear the cache entry for dsp->D->keys[i, i+V, ...] + dsp->D->F = dsp->F + --dsp +noaccess(D): + if D->F is set, + clear the cache entries for all name keys of D +readonly(D): + << nothing >> +.setmaxlength(D,N): + same as noaccess +restore: + If either the old or the new value of a change is a name + (possibly in a packed array), clear its cache entry. This is + conservative, but easy to detect, and probably not *too* + conservative. +def(K,V): + if K->P points into dsp->D + *K->P = V + else + put the new value in dsp->D + set *K and dsp->M[i mod V] as for a lookup +put(D,K,V): + if K is already defined in D, do nothing special + otherwise, if D->F isn't set, do nothing special + otherwise, clear K's cache entry +undef(D,K): + if D->F is set, + clear K's cache entry +*/ diff --git a/pstoraster/errno_.h b/pstoraster/errno_.h new file mode 100644 index 0000000000..f5dbfdebe5 --- /dev/null +++ b/pstoraster/errno_.h @@ -0,0 +1,35 @@ +/* Copyright (C) 1993 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to + anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer to + the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given to + you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises is not affiliated with the Free Software Foundation or + the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, + does not depend on any other GNU software. +*/ + +/* errno_.h */ +/* Generic substitute for Unix errno.h */ + +/* We must include std.h before any file that includes sys/types.h. */ +#include "std.h" + +/* All environments provide errno.h, but in some of them, errno.h */ +/* only defines the error numbers, and doesn't declare errno. */ +#include +#ifndef errno /* in case it was #defined (very implausible!) */ +extern int errno; +#endif diff --git a/pstoraster/errors.h b/pstoraster/errors.h new file mode 100644 index 0000000000..9c9defcce0 --- /dev/null +++ b/pstoraster/errors.h @@ -0,0 +1,179 @@ +/* Copyright (C) 1989, 1995 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to + anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer to + the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given to + you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises is not affiliated with the Free Software Foundation or + the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, + does not depend on any other GNU software. +*/ + +/* errors.h */ +/* Definition of error codes */ + +/* + * A procedure that may return an error always returns + * a non-negative value (zero, unless otherwise noted) for success, + * or negative for failure. + * We use ints rather than an enum to avoid a lot of casting. + */ + +/* + * The following peculiar structure allows us to include this file + * wherever error code definitions are needed, and use the same file + * to generate the table of error names by setting INCLUDE_ERROR_NAMES. + */ + +# ifdef INCLUDE_ERROR_NAMES + +/* Define the error name table */ +const char _ds *gs_error_names[] = { +#define _e_(code,name) name, + +# else /* !INCLUDE_ERROR_NAMES */ + +extern const char _ds *gs_error_names[]; +# define _e_(code,name) + +#endif /* (!)INCLUDE_ERROR_NAMES */ + + /* ------ PostScript Level 1 errors ------ */ + +#define e_unknownerror (-1) /* unknown error */ + _e_(e_unknown, "unknownerror") +#define e_dictfull (-2) + _e_(e_dictfull, "dictfull") +#define e_dictstackoverflow (-3) + _e_(e_dictstackoverflow, "dictstackoverflow") +#define e_dictstackunderflow (-4) + _e_(e_dictstackunderflow, "dictstackunderflow") +#define e_execstackoverflow (-5) + _e_(e_execstackoverflow, "execstackoverflow") +#define e_interrupt (-6) +/* We also need to define gs_error_interrupt, for gpcheck.h. */ +#undef gs_error_interrupt +#define gs_error_interrupt e_interrupt + _e_(e_interrupt, "interrupt") +#define e_invalidaccess (-7) + _e_(e_invalidaccess, "invalidaccess") +#define e_invalidexit (-8) + _e_(e_invalidexit, "invalidexit") +#define e_invalidfileaccess (-9) + _e_(e_invalidfileaccess, "invalidfileaccess") +#define e_invalidfont (-10) + _e_(e_invalidfont, "invalidfont") +#define e_invalidrestore (-11) + _e_(e_invalidrestore, "invalidrestore") +#define e_ioerror (-12) + _e_(e_ioerror, "ioerror") +#define e_limitcheck (-13) + _e_(e_limitcheck, "limitcheck") +#define e_nocurrentpoint (-14) + _e_(e_nocurrentpoint, "nocurrentpoint") +#define e_rangecheck (-15) + _e_(e_rangecheck, "rangecheck") +#define e_stackoverflow (-16) + _e_(e_stackoverflow, "stackoverflow") +#define e_stackunderflow (-17) + _e_(e_stackunderflow, "stackunderflow") +#define e_syntaxerror (-18) + _e_(e_syntaxerror, "syntaxerror") +#define e_timeout (-19) + _e_(e_timeout, "timeout") +#define e_typecheck (-20) + _e_(e_typecheck, "typecheck") +#define e_undefined (-21) + _e_(e_undefined, "undefined") +#define e_undefinedfilename (-22) + _e_(e_undefinedfilename, "undefinedfilename") +#define e_undefinedresult (-23) + _e_(e_undefinedresult, "undefinedresult") +#define e_unmatchedmark (-24) + _e_(e_unmatchedmark, "unmatchedmark") +#define e_VMerror (-25) + _e_(e_VMerror, "VMerror") + + /* ------ Additional Level 2 and DPS errors ------ */ + +#define e_configurationerror (-26) + _e_(e_configurationerror, "configurationerror") +#define e_invalidcontext (-27) + _e_(e_invalidcontext, "invalidcontext") +#define e_undefinedresource (-28) + _e_(e_undefinedresource, "undefinedresource") +#define e_unregistered (-29) + _e_(e_unregistered, "unregistered") + +# ifdef INCLUDE_ERROR_NAMES + +/* End of error name table */ + 0 +}; + +# endif /* INCLUDE_ERROR_NAMES */ + + /* ------ Pseudo-errors used internally ------ */ + +/* + * Internal code for a fatal error. + * gs_interpret also returns this for a .quit with a positive exit code. + */ +#define e_Fatal (-100) + +/* + * Internal code for the .quit operator. + * The real quit code is an integer on the operand stack. + * gs_interpret returns this only for a .quit with a zero exit code. + */ +#define e_Quit (-101) + +/* + * Internal code for a normal exit from the interpreter. + * Do not use outside of interp.c. + */ +#define e_InterpreterExit (-102) + +/* + * Internal code that indicates that a procedure has been inserted + * on the e-stack at (former) esp+2, to be executed before retrying + * the current token. This is used for color remapping + * involving a call back into the interpreter -- inelegant, but effective. + */ +#define e_InsertProc (-103) + +/* + * Internal code to indicate we have underflowed the top block + * of the e-stack. + */ +#define e_ExecStackUnderflow (-104) + +/* + * Internal code for the vmreclaim operator with a positive operand. + * We need to handle this as an error because otherwise the interpreter + * won't reload enough of its state when the operator returns. + */ +#define e_VMreclaim (-105) + +/* + * Internal code for requesting more input from run_string. + */ +#define e_NeedInput (-106) + +/* + * Define which error codes require re-executing the current object. + */ +#define error_is_interrupt(ecode)\ + ((ecode) == e_interrupt || (ecode) == e_timeout) diff --git a/pstoraster/estack.h b/pstoraster/estack.h new file mode 100644 index 0000000000..3dfd42b75c --- /dev/null +++ b/pstoraster/estack.h @@ -0,0 +1,137 @@ +/* Copyright (C) 1989, 1992, 1993, 1994 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to + anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer to + the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given to + you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises is not affiliated with the Free Software Foundation or + the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, + does not depend on any other GNU software. +*/ + +/* estack.h */ +/* Definitions for the execution stack */ +#include "istack.h" + +/* Define the execution stack pointers. */ +typedef s_ptr es_ptr; +typedef const_s_ptr const_es_ptr; +extern ref_stack e_stack; +#define esbot (e_stack.bot) +#define esp (e_stack.p) +#define estop (e_stack.top) + +/* + * To improve performance, we cache the currentfile pointer + * (i.e., `shallow-bind' it in Lisp terminology). The invariant is as + * follows: either esfile points to the currentfile slot on the estack + * (i.e., the topmost slot with an executable file), or it is 0. + * To maintain the invariant, it is sufficient that whenever a routine + * pushes or pops anything on the estack, if the object *might* be + * an executable file, invoke esfile_clear_cache(); alternatively, + * immediately after pushing an object, invoke esfile_check_cache(). + */ +extern ref *esfile; +#define esfile_clear_cache() (esfile = 0) +#define esfile_set_cache(pref) (esfile = (pref)) +#define esfile_check_cache()\ + if ( r_has_type_attrs(esp, t_file, a_executable) )\ + esfile_set_cache(esp) + +/* + * The execution stack is used for three purposes: + * + * - Procedures being executed are held here. They always have + * type = t_array, t_mixedarray, or t_shortarray, with a_executable set. + * More specifically, the e-stack holds the as yet unexecuted tail of the + * procedure. + * + * - if, ifelse, etc. push arguments to be executed here. + * They may be any kind of object whatever. + * + * - Control operators (filenameforall, for, repeat, loop, forall, + * pathforall, run, stopped, ...) mark the stack by pushing + * an object with type = t_null, attrs = a_executable, size = es_xxx + * (see below), and value.opproc = a cleanup procedure that will get called + * whenever the execution stack is about to get cut back beyond this point + * (either for normal completion of the operator, or any kind of exit). + * (Executable null objects can't ever appear on the e-stack otherwise: + * if a control operator pushes one, it gets popped immediately.) + * The cleanup procedure is called with esp pointing just BELOW the mark, + * i.e., the mark has already been popped. + * + * The loop operators also push whatever state they need, + * followed by an operator object that handles continuing the loop. + * + * Note that there are many internal looping operators -- for example, + * all the 'show' operators can behave like loops, since they may call out + * to BuildChar procedures. + */ + +/* Macro for marking the execution stack */ +#define make_mark_estack(ep, es_idx, proc)\ + make_tasv(ep, t_null, a_executable, es_idx, opproc, proc) +#define push_mark_estack(es_idx, proc)\ + (++esp, make_mark_estack(esp, es_idx, proc)) +#define r_is_estack_mark(ep)\ + r_has_type_attrs(ep, t_null, a_executable) +#define estack_mark_index(ep) r_size(ep) + +/* Macro for pushing an operator on the execution stack */ +/* to represent a continuation procedure */ +#define make_op_estack(ep, proc)\ + make_oper(ep, 0, proc) +#define push_op_estack(proc)\ + (++esp, make_op_estack(esp, proc)) + +/* Macro to ensure enough room on the execution stack */ +#define check_estack(n)\ + if ( esp > estop - (n) )\ + { int es_code_ = ref_stack_extend(&e_stack, n);\ + if ( es_code_ < 0 ) return es_code_;\ + } + +/* Macro to ensure enough entries on the execution stack */ +#define check_esp(n)\ + if ( esp < esbot + ((n) - 1) )\ + { e_stack.requested = (n); return_error(e_ExecStackUnderflow); } + +/* Define the various kinds of execution stack marks. */ +#define es_other 0 /* internal use */ +#define es_show 1 /* show operators */ +#define es_for 2 /* iteration operators */ +#define es_stopped 3 /* stopped operator */ + +/* Pop a given number of elements off the execution stack, */ +/* executing cleanup procedures as necessary. */ +void pop_estack(P1(uint)); + +/* + * The execution stack is implemented as a linked list of blocks; + * operators that can push or pop an unbounded number of values, or that + * access the entire o-stack, must take this into account. These are: + * exit .stop .instopped countexecstack execstack currentfile + * pop_estack(exit, stop, error recovery) + * gs_show_find(all the show operators) + * In addition, for e-stack entries created by control operators, we must + * ensure that the mark and its data are never separated. We do this + * by ensuring that when splitting the top block, at least N items + * are kept in the new top block above the bottommost retained mark, + * where N is the largest number of data items associated with a mark. + * Finally, in order to avoid specific checks for underflowing a block, + * we put a guard entry at the bottom of each block except the top one + * that contains a procedure that returns an internal "exec stack block + * underflow" error. + */ diff --git a/pstoraster/files.h b/pstoraster/files.h new file mode 100644 index 0000000000..f7c320997b --- /dev/null +++ b/pstoraster/files.h @@ -0,0 +1,142 @@ +/* Copyright (C) 1989, 1995, 1996 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to + anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer to + the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given to + you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises is not affiliated with the Free Software Foundation or + the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, + does not depend on any other GNU software. +*/ + +/* files.h */ +/* Common declarations for zfile.c and zfileio.c */ +/* Requires stream.h */ + +/* + * In many places below, a do {...} while (0) avoids problems with a possible + * enclosing 'if'. + */ + +/* + * File objects store a pointer to a stream in value.pfile. + * A file object is valid if its "size" matches the read_id or write_id + * (as appropriate) in the stream it points to. This arrangement + * allows us to detect closed files reliably, while allowing us to + * reuse closed streams for new files. + */ +#define fptr(pref) (pref)->value.pfile +#define make_file(pref,a,id,s)\ + make_tasv(pref,t_file,a,id,pfile,s) + +/* The stdxxx files. We have to access them through procedures, */ +/* because they might have to be opened when referenced. */ +int zget_stdin(P1(stream **)); +int zget_stdout(P1(stream **)); +int zget_stderr(P1(stream **)); +extern bool gs_stdin_is_interactive; +/* An invalid (closed) file. */ +extern stream *invalid_file_entry; + +/* Macros for checking file validity. */ +#define file_is_valid(svar,op)\ + (svar = fptr(op), (svar->read_id | svar->write_id) == r_size(op)) +#define check_file(svar,op)\ + do\ + { check_type(*(op), t_file);\ + if ( !file_is_valid(svar, op) ) return_error(e_invalidaccess);\ + }\ + while (0) + +/* + * If a file is open for both reading and writing, its read_id, write_id, + * and stream procedures and modes reflect the current mode of use; + * an id check failure will switch it to the other mode. + */ +int file_switch_to_read(P1(const ref *)); +#define check_read_file(svar,op)\ + do\ + { check_read_type(*(op), t_file);\ + check_read_known_file(svar, op, return);\ + }\ + while (0) +#define check_read_known_file(svar,op,error_return)\ + check_read_known_file_else(svar, op, error_return, svar = invalid_file_entry) +/* The do... avoids problems with a possible enclosed 'if'. */ +#define check_read_known_file_else(svar,op,error_return,invalid_action)\ + do\ + { svar = fptr(op);\ + if ( svar->read_id != r_size(op) )\ + { if ( svar->read_id == 0 && svar->write_id == r_size(op) )\ + { int fcode = file_switch_to_read(op);\ + if ( fcode < 0 ) error_return(fcode);\ + }\ + else do { invalid_action; } while (0); /* closed or reopened file */\ + }\ + }\ + while (0) +int file_switch_to_write(P1(const ref *)); +#define check_write_file(svar,op)\ + do\ + { check_write_type(*(op), t_file);\ + check_write_known_file(svar, op, return);\ + }\ + while (0) +#define check_write_known_file(svar,op,error_return)\ + do\ + { svar = fptr(op);\ + if ( svar->write_id != r_size(op) )\ + { int fcode = file_switch_to_write(op);\ + if ( fcode < 0 ) error_return(fcode);\ + }\ + }\ + while (0) + +/* Data exported by zfile.c. */ + /* for zfilter.c and ziodev.c */ +extern const uint file_default_buffer_size; + +/* Procedures exported by zfile.c. */ + /* for gs.c */ +FILE *lib_fopen(P1(const char *)); + /* for gsmain.c */ +int lib_file_open(P6(const char *, uint, byte *, uint, uint *, ref *)); + /* for iccinit.c */ +int file_read_string(P3(const byte *, uint, ref *)); + /* 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)); +#endif + /* for zfilter.c */ +int filter_open(P6(const char *, uint, ref *, const stream_procs _ds *, + const stream_template *, const stream_state *)); + /* for zfileio.c */ +void make_stream_file(P3(ref *, stream *, const char *)); + /* for ziodev.c */ +int file_close_finish(P1(stream *)); +int file_close_disable(P1(stream *)); +int file_close_file(P1(stream *)); + /* for gsmain.c, interp.c */ +int file_close(P1(ref *)); + /* for ziodev.c */ +stream *file_alloc_stream(P2(gs_memory_t *, client_name_t)); + /* for isave.c */ +void file_save(P0()); +/*void file_restore(P1(const alloc_save_t *));*/ + +/* Procedures exported by zfileio.c. */ + /* for ziodev.c */ +int zreadline_from(P5(stream *, byte *, uint, uint *, bool *)); diff --git a/pstoraster/fname.h b/pstoraster/fname.h new file mode 100644 index 0000000000..84e2852eaf --- /dev/null +++ b/pstoraster/fname.h @@ -0,0 +1,38 @@ +/* Copyright (C) 1993 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to + anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer to + the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given to + you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises is not affiliated with the Free Software Foundation or + the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, + does not depend on any other GNU software. +*/ + +/* fname.h */ +/* File name parsing interface */ +/* Requires gxiodev.h */ + +/* Parsed file name type. Note that the file name may be either a */ +/* gs_string (no terminator) or a C string (null terminator). */ +typedef struct parsed_file_name_s { + gx_io_device *iodev; + const char *fname; + uint len; +} parsed_file_name; +int parse_file_name(P2(const ref *, parsed_file_name *)); +int parse_real_file_name(P3(const ref *, parsed_file_name *, client_name_t)); +int terminate_file_name(P2(parsed_file_name *, client_name_t)); +void free_file_name(P2(parsed_file_name *, client_name_t)); diff --git a/pstoraster/gconf.c b/pstoraster/gconf.c new file mode 100644 index 0000000000..1a6641cc3f --- /dev/null +++ b/pstoraster/gconf.c @@ -0,0 +1,126 @@ +/* Copyright (C) 1989, 1995, 1996 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to + anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer to + the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given to + you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises is not affiliated with the Free Software Foundation or + the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, + does not depend on any other GNU software. +*/ + +/* gconf.c */ +/* Configuration tables */ +#include "gx.h" +#include "gscdefs.h" /* interface */ +#include "gconfig.h" /* for #defines */ +/* + * Since we only declare variables of type gx_device *, + * it should be sufficient to define struct gx_device_s as + * an abstract (undefined) structure. However, the VAX VMS compiler + * isn't happy with this, so we have to include the full definition. + */ +#include "gxdevice.h" +#include "gxiodev.h" + +/* + * The makefile generates the file gconfig.h, which consists of + * lines of the form + * device_(gs_xxx_device) + * for each installed device; + * emulator_("emulator") + * for each known emulator; + * init_(gs_xxx_init) + * for each initialization procedure; + * io_device_(gs_iodev_xxx) + * for each known IODevice; + * oper_(xxx_op_defs) + * for each operator option; + * psfile_("gs_xxxx.ps") + * for each optional initialization file. + * + * We include this file multiple times to generate various different + * source structures. (It's a hack, but we haven't come up with anything + * more satisfactory.) + */ + +/* ---------------- Resources (devices, inits, IODevices) ---------------- */ + +/* Declare devices, init procedures, and IODevices as extern. */ +#define device_(dev) extern far_data gx_device dev; +#define init_(proc) extern void proc(P1(gs_memory_t *)); +#define io_device_(iodev) extern gx_io_device iodev; +#include "gconfig.h" +#undef init_ +#undef io_device_ +#undef device_ + +/* Set up the initialization procedure table. */ +extern_gx_init_table(); +#define init_(proc) proc, +void (*gx_init_table[])(P1(gs_memory_t *)) = { +#include "gconfig.h" + 0 +}; +#undef init_ + +/* Set up the IODevice table. The first entry must be %os%, */ +/* since it is the default for files with no explicit device specified. */ +extern_gx_io_device_table(); +extern gx_io_device gs_iodev_os; +#define io_device_(iodev) &iodev, +gx_io_device *gx_io_device_table[] = { + &gs_iodev_os, +#include "gconfig.h" + 0 +}; +#undef io_device_ +uint gx_io_device_table_count = countof(gx_io_device_table) - 1; + +/* Set up the device table. */ +#define device_(dev) &dev, +private const gx_device *gx_device_list[] = { +#include "gconfig.h" + 0 +}; +#undef device_ + +/* + * Allocate structure descriptors for the devices. + * We can't fill in the structure sizes, because we don't know them + * statically, and we also don't know statically which devices are + * forwarders; so we fill all of this in when we need to + * (in gs_copydevice in gsdevice.c). + */ +#define device_(dev) { 0 }, +/* Because of a bug in the Borland C++ 4.5 compiler, */ +/* we can't declare the following far_data but not static. */ +static /*private*/ far_data gs_memory_struct_type_t gx_device_st_list[] = { +#include "gconfig.h" + { 0 } +}; +#undef device_ + +/* Return the list of device prototypes, the list of their structure */ +/* descriptors, and (as the value) the length of the lists. */ +extern_gs_lib_device_list(); +int +gs_lib_device_list(const gx_device ***plist, gs_memory_struct_type_t **pst) +{ if ( plist != 0 ) + *plist = gx_device_list; + if ( pst != 0 ) + *pst = gx_device_st_list; + return countof(gx_device_list) - 1; +} diff --git a/pstoraster/gconfig.h b/pstoraster/gconfig.h new file mode 100644 index 0000000000..643c66bbeb --- /dev/null +++ b/pstoraster/gconfig.h @@ -0,0 +1,192 @@ +/* + * "$Id$" + * + * GNU GhostScript configuration file for the Common UNIX Printing + * System (CUPS). + * + * This file is normally generated by a lot of echogs and genconf + * commands... + * + * Copyright 1997-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + */ + +#include + +#ifdef device_ +device_(gs_cups_device) +device_(gs_nullpage_device) +#endif +#ifdef oper_ +oper_(zfzlib_op_defs) +oper_(zcie_l2_op_defs) +oper_(zcrd_l2_op_defs) +oper_(zfont0_op_defs) +oper_(zchar2_op_defs) +oper_(zfdcte_op_defs) +oper_(zfdctd_op_defs) +oper_(zdevice2_l2_op_defs) +oper_(ziodev2_l2_op_defs) +oper_(zmedia2_l2_op_defs) +#endif +#ifdef io_device_ +io_device_(gs_iodev_null) +io_device_(gs_iodev_ram) +io_device_(gs_iodev_calendar) +#endif +#ifdef psfile_ +psfile_("gs_setpd.ps") +#endif +#ifdef oper_ +oper_(zbseq_l2_op_defs) +#endif +#ifdef psfile_ +psfile_("gs_btokn.ps") +#endif +#ifdef init_ +init_(gs_gscolor1_init) +#endif +#ifdef oper_ +oper_(zcolor1_op_defs) +oper_(zht1_op_defs) +oper_(zupath_l2_op_defs) +oper_(zvmem2_op_defs) +oper_(ireclaim_l2_op_defs) +oper_(zchar2_l2_op_defs) +oper_(zdps1_l2_op_defs) +#endif +#ifdef psfile_ +psfile_("gs_dps1.ps") +#endif +#ifdef oper_ +oper_(zfdecode_op_defs) +oper_(zfilter2_op_defs) +oper_(zarith_op_defs) +oper_(zarray_op_defs) +oper_(zcontrol_op_defs) +oper_(zdict_op_defs) +oper_(zfile_op_defs) +oper_(zfileio_op_defs) +oper_(zfilter_op_defs) +oper_(zfproc_op_defs) +oper_(zgeneric_op_defs) +oper_(ziodev_op_defs) +oper_(zmath_op_defs) +oper_(zmisc_op_defs) +oper_(zpacked_op_defs) +oper_(zrelbit_op_defs) +oper_(zstack_op_defs) +oper_(zstring_op_defs) +oper_(zsysvm_op_defs) +oper_(ztoken_op_defs) +oper_(ztype_op_defs) +oper_(zusparam_op_defs) +oper_(zvmem_op_defs) +oper_(zchar_op_defs) +oper_(zcolor_op_defs) +oper_(zdevice_op_defs) +oper_(zfont_op_defs) +oper_(zfont2_op_defs) +oper_(zgstate_op_defs) +oper_(zht_op_defs) +oper_(zmatrix_op_defs) +oper_(zpaint_op_defs) +oper_(zpath_op_defs) +#endif +#ifdef io_device_ +io_device_(gs_iodev_stdin) +io_device_(gs_iodev_stdout) +io_device_(gs_iodev_stderr) +io_device_(gs_iodev_lineedit) +io_device_(gs_iodev_statementedit) +#endif +#ifdef oper_ +oper_(zfbcp_op_defs) +oper_(zhsb_op_defs) +oper_(zpath1_op_defs) +oper_(zchar1_op_defs) +oper_(zfont1_op_defs) +oper_(zmisc1_op_defs) +#endif +#ifdef psfile_ +psfile_("gs_type1.ps") +#endif +#ifdef emulator_ +emulator_("PostScript") +emulator_("PostScriptLevel1") +#endif +#ifdef oper_ +oper_(zpcolor_l2_op_defs) +oper_(zmisc2_op_defs) +oper_(zcolor2_l2_op_defs) +oper_(zcsindex_l2_op_defs) +oper_(zht2_l2_op_defs) +oper_(zimage2_l2_op_defs) +#endif +#ifdef psfile_ +psfile_("gs_lev2.ps") +psfile_("gs_res.ps") +#endif +#ifdef oper_ +oper_(zcssepr_l2_op_defs) +oper_(zfilterx_op_defs) +#endif +#ifdef emulator_ +emulator_("PostScriptLevel2") +#endif +#ifdef psfile_ +psfile_("gs_mex_e.ps") +psfile_("gs_mro_e.ps") +psfile_("gs_pdf_e.ps") +psfile_("gs_wan_e.ps") +psfile_("gs_pdf.ps") +psfile_("gs_l2img.ps") +psfile_("pdf_base.ps") +psfile_("pdf_draw.ps") +psfile_("pdf_font.ps") +psfile_("pdf_main.ps") +psfile_("pdf_sec.ps") +psfile_("pdf_2ps.ps") +#endif +#ifdef emulator_ +emulator_("PDF") +#endif +#ifdef io_device_ +io_device_(gs_iodev_pipe) +#endif +#ifdef oper_ +oper_(zchar42_op_defs) +oper_(zfont42_op_defs) +#endif +#ifdef psfile_ +psfile_("gs_typ42.ps") +psfile_("gs_ttf.ps") +#endif +#ifdef init_ +init_(gs_climag_init) +init_(gs_clpath_init) +init_(gs_gscolor_init) +init_(gs_roplib_init) +#endif +#define GS_LIB_DEFAULT DATADIR "/ghostscript:" DATADIR "/fonts" +#define GS_DOCDIR DATADIR "/ghostscript" +#define GS_INIT "gs_init.ps" + +/* + * End of "$Id$". + */ diff --git a/pstoraster/gconfigv.h b/pstoraster/gconfigv.h new file mode 100644 index 0000000000..c2f16d45d1 --- /dev/null +++ b/pstoraster/gconfigv.h @@ -0,0 +1,3 @@ +#define USE_ASM (-0) +#define USE_FPU (2-0) +#define EXTEND_NAMES 0 diff --git a/pstoraster/gdebug.h b/pstoraster/gdebug.h new file mode 100644 index 0000000000..aeba8a7aaf --- /dev/null +++ b/pstoraster/gdebug.h @@ -0,0 +1,117 @@ +/* Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to + anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer to + the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given to + you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises is not affiliated with the Free Software Foundation or + the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, + does not depend on any other GNU software. +*/ + +/* gdebug.h */ +/* Debugging machinery definitions */ + +#ifndef gdebug_INCLUDED +# define gdebug_INCLUDED + +/* Define the array of debugging flags, indexed by character code. */ +extern char gs_debug[128]; +#define gs_debug_c(c)\ + ((c)>='a' && (c)<='z' ? gs_debug[c] | gs_debug[(c)^32] : gs_debug[c]) +#ifdef DEBUG +# define gs_if_debug_c(c) gs_debug_c(c) +#else +# define gs_if_debug_c(c) 0 +#endif +/* Define an alias for a specialized debugging flag */ +/* that used to be a separate variable. */ +#define gs_log_errors gs_debug['#'] + +/* If debugging, direct all error output to gs_debug_out. */ +extern FILE *gs_debug_out; +#ifdef DEBUG +#undef dstderr +#define dstderr gs_debug_out +#undef estderr +#define estderr gs_debug_out +#endif + +/* Redefine eprintf_program_name and lprintf_file_and_line as procedures */ +/* so one can set breakpoints on them. */ +#undef eprintf_program_name +extern void eprintf_program_name(P2(FILE *, const char *)); +#undef lprintf_file_and_line +extern void lprintf_file_and_line(P3(FILE *, const char *, int)); + +/* Insert code conditionally if debugging. */ +#ifdef DEBUG +# define do_debug(x) x +#else +# define do_debug(x) +#endif + +/* Debugging printout macros. */ +#ifdef DEBUG +# define if_debug0(c,s)\ + if (gs_debug_c(c)) dprintf(s) +# define if_debug1(c,s,a1)\ + if (gs_debug_c(c)) dprintf1(s,a1) +# define if_debug2(c,s,a1,a2)\ + if (gs_debug_c(c)) dprintf2(s,a1,a2) +# define if_debug3(c,s,a1,a2,a3)\ + if (gs_debug_c(c)) dprintf3(s,a1,a2,a3) +# define if_debug4(c,s,a1,a2,a3,a4)\ + if (gs_debug_c(c)) dprintf4(s,a1,a2,a3,a4) +# define if_debug5(c,s,a1,a2,a3,a4,a5)\ + if (gs_debug_c(c)) dprintf5(s,a1,a2,a3,a4,a5) +# define if_debug6(c,s,a1,a2,a3,a4,a5,a6)\ + if (gs_debug_c(c)) dprintf6(s,a1,a2,a3,a4,a5,a6) +# define if_debug7(c,s,a1,a2,a3,a4,a5,a6,a7)\ + if (gs_debug_c(c)) dprintf7(s,a1,a2,a3,a4,a5,a6,a7) +# define if_debug8(c,s,a1,a2,a3,a4,a5,a6,a7,a8)\ + if (gs_debug_c(c)) dprintf8(s,a1,a2,a3,a4,a5,a6,a7,a8) +# define if_debug9(c,s,a1,a2,a3,a4,a5,a6,a7,a8,a9)\ + if (gs_debug_c(c)) dprintf9(s,a1,a2,a3,a4,a5,a6,a7,a8,a9) +# define if_debug10(c,s,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)\ + if (gs_debug_c(c)) dprintf10(s,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) +# define if_debug11(c,s,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)\ + if (gs_debug_c(c)) dprintf11(s,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11) +# define if_debug12(c,s,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12)\ + if (gs_debug_c(c)) dprintf12(s,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12) +#else +# define if_debug0(c,s) DO_NOTHING +# define if_debug1(c,s,a1) DO_NOTHING +# define if_debug2(c,s,a1,a2) DO_NOTHING +# define if_debug3(c,s,a1,a2,a3) DO_NOTHING +# define if_debug4(c,s,a1,a2,a3,a4) DO_NOTHING +# define if_debug5(c,s,a1,a2,a3,a4,a5) DO_NOTHING +# define if_debug6(c,s,a1,a2,a3,a4,a5,a6) DO_NOTHING +# define if_debug7(c,s,a1,a2,a3,a4,a5,a6,a7) DO_NOTHING +# define if_debug8(c,s,a1,a2,a3,a4,a5,a6,a7,a8) DO_NOTHING +# define if_debug9(c,s,a1,a2,a3,a4,a5,a6,a7,a8,a9) DO_NOTHING +# define if_debug10(c,s,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) DO_NOTHING +# define if_debug11(c,s,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11) DO_NOTHING +# define if_debug12(c,s,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12) DO_NOTHING +#endif + +/* Debugging support procedures in gsmisc.c */ +void debug_dump_bytes(P3(const byte *from, const byte *to, + const char *msg)); +void debug_dump_bitmap(P4(const byte *from, uint raster, uint height, + const char *msg)); +void debug_print_string(P2(const byte *str, uint len)); + +#endif /* gdebug_INCLUDED */ diff --git a/pstoraster/gdevabuf.c b/pstoraster/gdevabuf.c new file mode 100644 index 0000000000..11e5090831 --- /dev/null +++ b/pstoraster/gdevabuf.c @@ -0,0 +1,355 @@ +/* Copyright (C) 1994, 1995, 1996 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to + anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer to + the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given to + you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises is not affiliated with the Free Software Foundation or + the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, + does not depend on any other GNU software. +*/ + +/* gdevabuf.c */ +/* Alpha-buffering memory devices */ +#include "memory_.h" +#include "gx.h" +#include "gserrors.h" +#include "gxdevice.h" +#include "gxdevmem.h" /* semi-public definitions */ +#include "gdevmem.h" /* private definitions */ + +/* ================ Alpha devices ================ */ + +/* + * These devices store 2 or 4 bits of alpha. They are a hybrid of a + * monobit device (for color mapping) and a 2- or 4-bit device (for painting). + * Currently, we only use them for character rasterizing, but they might be + * useful for other things someday. + */ + +/* We can't initialize the device descriptor statically very well, */ +/* so we patch up the image2 or image4 descriptor. */ +private dev_proc_map_rgb_color(mem_alpha_map_rgb_color); +private dev_proc_map_color_rgb(mem_alpha_map_color_rgb); +private dev_proc_map_rgb_alpha_color(mem_alpha_map_rgb_alpha_color); +private dev_proc_get_alpha_bits(mem_alpha_get_alpha_bits); +private dev_proc_copy_alpha(mem_alpha_copy_alpha); + +void +gs_make_mem_alpha_device(gx_device_memory *adev, gs_memory_t *mem, + gx_device *target, int alpha_bits) +{ gs_make_mem_device(adev, gdev_mem_device_for_bits(alpha_bits), + mem, 0, target); + /* This is a black-and-white device ... */ + adev->color_info = gdev_mem_device_for_bits(1)->color_info; + /* ... but it has multiple bits per pixel ... */ + adev->color_info.depth = alpha_bits; + /* ... and different color mapping. */ + set_dev_proc(adev, map_rgb_color, mem_alpha_map_rgb_color); + set_dev_proc(adev, map_color_rgb, mem_alpha_map_color_rgb); + set_dev_proc(adev, map_rgb_alpha_color, mem_alpha_map_rgb_alpha_color); + set_dev_proc(adev, get_alpha_bits, mem_alpha_get_alpha_bits); + set_dev_proc(adev, copy_alpha, mem_alpha_copy_alpha); +} + +/* Reimplement color mapping. */ +private gx_color_index +mem_alpha_map_rgb_color(gx_device *dev, gx_color_value r, gx_color_value g, + gx_color_value b) +{ gx_color_index color = gx_forward_map_rgb_color(dev, r, g, b); + return (color == 0 || color == gx_no_color_index ? color : + (gx_color_index)((1 << mdev->log2_alpha_bits) - 1)); +} +private int +mem_alpha_map_color_rgb(gx_device *dev, gx_color_index color, + gx_color_value prgb[3]) +{ return + gx_forward_map_color_rgb(dev, + (color == 0 ? color : (gx_color_index)1), + prgb); +} +private gx_color_index +mem_alpha_map_rgb_alpha_color(gx_device *dev, gx_color_value r, + gx_color_value g, gx_color_value b, gx_color_value alpha) +{ gx_color_index color = gx_forward_map_rgb_color(dev, r, g, b); + return (color == 0 || color == gx_no_color_index ? color : + (gx_color_index)(alpha >> (gx_color_value_bits - + mdev->log2_alpha_bits))); +} +private int +mem_alpha_get_alpha_bits(gx_device *dev, graphics_object_type type) +{ return 1 << mdev->log2_alpha_bits; +} +/* Implement alpha copying. */ +private int +mem_alpha_copy_alpha(gx_device *dev, const byte *data, int data_x, + int raster, gx_bitmap_id id, int x, int y, int width, int height, + gx_color_index color, int depth) +{ /* Just use copy_color. */ + return (color == 0 ? + (*dev_proc(dev, fill_rectangle))(dev, x, y, width, height, + color) : + (*dev_proc(dev, copy_color))(dev, data, data_x, raster, id, + x, y, width, height)); +} + +/* ================ Alpha-buffer device ================ */ + +/* + * This device converts graphics sampled at a higher resolution to + * alpha values at a lower resolution. It does this by accumulating + * the bits of a band and then converting the band to alphas. + * In order to make this work, the client of the device must promise + * only to visit each band at most once, except possibly for a single + * scan line overlapping the adjacent band, and must promise only to write + * a single color into the output. In particular, this works + * within a single call on gx_fill_path (if the fill loop is constrained + * to process bands of limited height on each pass) or a single masked image + * scanned in Y order, but not across such calls and not for other + * kinds of painting operations. + * + * We implement this device as a subclass of a monobit memory device. + * (We put its state in the definition of gx_device_memory just because + * actual subclassing introduces a lot of needless boilerplate.) + * We only allocate enough bits for one band. The height of the band + * must be a multiple of the Y scale factor; the minimum height + * of the band is twice the Y scale factor. + * + * The bits in storage are actually a sliding window on the true + * oversampled image. To avoid having to copy the bits around when we + * move the window, we adjust the mapping between the client's Y values + * and our own, as follows: + * Client Stored + * ------ ------ + * y0..y0+m-1 n-m..n-1 + * y0+m..y0+n-1 0..n-m-1 + * where n and m are multiples of the Y scale factor and 0 <= m <= n <= + * the height of the band. (In the device structure, m is called + * mapped_start and n is called mapped_height.) This allows us to slide + * the window incrementally in either direction without copying any bits. + */ + +/* Procedures */ +private dev_proc_close_device(mem_abuf_close); +private dev_proc_copy_mono(mem_abuf_copy_mono); +private dev_proc_fill_rectangle(mem_abuf_fill_rectangle); + +/* The device descriptor. */ +private const gx_device_memory far_data mem_alpha_buffer_device = + mem_device("image(alpha buffer)", 0, 1, + gx_forward_map_rgb_color, gx_forward_map_color_rgb, + mem_abuf_copy_mono, gx_default_copy_color, mem_abuf_fill_rectangle, + gx_no_strip_copy_rop); + +/* Make an alpha-buffer memory device. */ +/* We use abuf instead of alpha_buffer because */ +/* gcc under VMS only retains 23 characters of procedure names. */ +void +gs_make_mem_abuf_device(gx_device_memory *adev, gs_memory_t *mem, + gx_device *target, const gs_log2_scale_point *pscale, + int alpha_bits, int mapped_x) +{ gs_make_mem_device(adev, &mem_alpha_buffer_device, mem, 0, target); + adev->max_fill_band = 1 << pscale->y; + adev->log2_scale = *pscale; + adev->log2_alpha_bits = alpha_bits >> 1; /* works for 1,2,4 */ + adev->mapped_x = mapped_x; + set_dev_proc(adev, close_device, mem_abuf_close); +} + +/* Test whether a device is an alpha-buffering device. */ +bool +gs_device_is_abuf(const gx_device *dev) +{ /* We can't just compare the procs, or even an individual proc, */ + /* because we might be tracing. Instead, check the identity of */ + /* the device name. */ + return dev->dname == mem_alpha_buffer_device.dname; +} + +/* Internal routine to flush a block of the buffer. */ +/* A block is a group of scan lines whose initial Y is a multiple */ +/* of the Y scale and whose height is equal to the Y scale. */ +private int +abuf_flush_block(gx_device_memory *adev, int y) +{ gx_device *target = adev->target; + int block_height = 1 << adev->log2_scale.y; + int alpha_bits = 1 << adev->log2_alpha_bits; + int ddepth = + (adev->width >> adev->log2_scale.x) << adev->log2_alpha_bits; + uint draster = bitmap_raster(ddepth); + int buffer_y = y - adev->mapped_y + adev->mapped_start; + byte *bits; + + if ( buffer_y >= adev->height ) + buffer_y -= adev->height; + bits = scan_line_base(adev, buffer_y); + { /* + * Many bits are typically zero. Save time by computing + * an accurate X bounding box before compressing. + * Unfortunately, in order to deal with alpha nibble swapping + * (see gsbitops.c), we can't expand the box only to pixel + * boundaries: + int alpha_mask = -1 << adev->log2_alpha_bits; + * Instead, we must expand it to byte boundaries, + */ + int alpha_mask = ~7; + gs_int_rect bbox; + int width; + + bits_bounding_box(bits, block_height, adev->raster, &bbox); + bbox.p.x &= alpha_mask; + bbox.q.x = (bbox.q.x + ~alpha_mask) & alpha_mask; + width = bbox.q.x - bbox.p.x; + bits_compress_scaled(bits, bbox.p.x, width, block_height, + adev->raster, bits, draster, &adev->log2_scale, + adev->log2_alpha_bits); + return (*dev_proc(target, copy_alpha))(target, + bits, 0, draster, gx_no_bitmap_id, + (adev->mapped_x + bbox.p.x) >> + adev->log2_scale.x, + y >> adev->log2_scale.y, + width >> adev->log2_scale.x, 1, + adev->save_color, alpha_bits); + } +} +/* Flush the entire buffer. */ +private int +abuf_flush(gx_device_memory *adev) +{ int y, code = 0; + int block_height = 1 << adev->log2_scale.y; + for ( y = 0; y < adev->mapped_height; y += block_height ) + if ( (code = abuf_flush_block(adev, adev->mapped_y + y)) < 0 ) + return code; + adev->mapped_height = adev->mapped_start = 0; + return 0; +} + +/* Close the device, flushing the buffer. */ +private int +mem_abuf_close(gx_device *dev) +{ int code = abuf_flush(mdev); + if ( code < 0 ) + return code; + return mem_close(dev); +} + +/* + * Framework for mapping a requested imaging operation to the buffer. + * For now, we assume top-to-bottom transfers and use a very simple algorithm. + */ +typedef struct y_transfer_s { + int y_next; + int height_left; + int transfer_y; + int transfer_height; +} y_transfer; +private void near +y_transfer_init(y_transfer *pyt, gx_device *dev, int ty, int th) +{ int bh = 1 << mdev->log2_scale.y; + if ( ty < mdev->mapped_y || ty > mdev->mapped_y + mdev->mapped_height ) + { abuf_flush(mdev); + mdev->mapped_y = ty & -bh; + mdev->mapped_height = bh; + memset(scan_line_base(mdev, 0), 0, bh * mdev->raster); + } + pyt->y_next = ty; + pyt->height_left = th; + pyt->transfer_height = 0; +} +/* while ( yt.height_left > 0 ) { y_transfer_next(&yt, mdev); ... } */ +private void near +y_transfer_next(y_transfer *pyt, gx_device *dev) +{ int my = mdev->mapped_y, mh = mdev->mapped_height; + int ms = mdev->mapped_start; + int ty = pyt->y_next += pyt->transfer_height; + int th = pyt->height_left; + int bh = 1 << mdev->log2_scale.y; + /* From here on, we know that my <= ty <= my + mh. */ + int tby, tbh; + if ( ty == my + mh ) + { /* Add a new block at my1. */ + if ( mh == mdev->height ) + { abuf_flush_block(mdev, my); + mdev->mapped_y = my += bh; + if ( (mdev->mapped_start = ms += bh) == mh ) + mdev->mapped_start = ms = 0; + } + else + { /* Because we currently never extend backwards, */ + /* we know we can't wrap around in this case. */ + mdev->mapped_height = mh += bh; + } + memset(scan_line_base(mdev, (ms == 0 ? mh : ms) - bh), + 0, bh * mdev->raster); + } + /* Now we know that my <= ty < my + mh. */ + tby = ty - my + ms; + if ( tby < mdev->height ) + { tbh = mdev->height - ms; + if ( tbh > mh ) tbh = mh; + tbh -= tby - ms; + } + else /* wrap around */ + { tby -= mdev->height; + tbh = ms + mh - dev->height - tby; + } + if_debug7('v', "[v]my=%d, mh=%d, ms=%d, ty=%d, th=%d, tby=%d, tbh=%d\n", + my, mh, ms, ty, th, tby, tbh); + if ( tbh > th ) tbh = th; + pyt->height_left = th - tbh; + pyt->transfer_y = tby; + pyt->transfer_height = tbh; +} + +/* Copy a monobit image. */ +private int +mem_abuf_copy_mono(gx_device *dev, + const byte *base, int sourcex, int sraster, gx_bitmap_id id, + int x, int y, int w, int h, gx_color_index zero, gx_color_index one) +{ y_transfer yt; + if ( zero != gx_no_color_index || one == gx_no_color_index ) + return_error(gs_error_undefinedresult); + x -= mdev->mapped_x; + fit_copy_xwh(dev, base, sourcex, sraster, id, x, y, w, h); /* don't limit y */ + mdev->save_color = one; + y_transfer_init(&yt, dev, y, h); + while ( yt.height_left > 0 ) + { y_transfer_next(&yt, dev); + (*dev_proc(&mem_mono_device, copy_mono))(dev, + base + (yt.y_next - y) * sraster, + sourcex, sraster, gx_no_bitmap_id, + x, yt.transfer_y, w, yt.transfer_height, + gx_no_color_index, (gx_color_index)1); + } + return 0; +} + +/* Fill a rectangle. */ +private int +mem_abuf_fill_rectangle(gx_device *dev, int x, int y, int w, int h, + gx_color_index color) +{ y_transfer yt; + x -= mdev->mapped_x; + fit_fill_xyw(dev, x, y, w, h); /* don't limit h */ + /* or check w <= 0, h <= 0 */ + mdev->save_color = color; + y_transfer_init(&yt, dev, y, h); + while ( yt.height_left > 0 ) + { y_transfer_next(&yt, dev); + (*dev_proc(&mem_mono_device, fill_rectangle))(dev, + x, yt.transfer_y, w, yt.transfer_height, + (gx_color_index)1); + } + return 0; +} diff --git a/pstoraster/gdevcups.c b/pstoraster/gdevcups.c new file mode 100644 index 0000000000..6abbbb658d --- /dev/null +++ b/pstoraster/gdevcups.c @@ -0,0 +1,2421 @@ +/* + * "$Id$" + * + * GNU Ghostscript raster output driver for the Common UNIX Printing + * System (CUPS). + * + * Copyright 1993-1999 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Easy Software Products and are protected by Federal + * copyright law. Distribution and use rights are outlined in the file + * "LICENSE.txt" which should have been included with this file. If this + * file is missing or damaged please contact Easy Software Products + * at: + * + * Attn: CUPS Licensing Information + * Easy Software Products + * 44141 Airport View Drive, Suite 204 + * Hollywood, Maryland 20636-3111 USA + * + * Voice: (301) 373-9603 + * EMail: cups-info@cups.org + * WWW: http://www.cups.org + * + * This code and any derivative of it may be used and distributed + * freely under the terms of the GNU General Public License when + * used with GNU Ghostscript or its derivatives. Use of the code + * (or any derivative of it) with software other than GNU + * GhostScript (or its derivatives) is governed by the CUPS license + * agreement. + * + * Contents: + * + * cups_close() - Close the output file. + * cups_get_matrix() - Generate the default page matrix. + * cups_get_params() - Get pagedevice parameters. + * cups_map_color_rgb() - Map a color index to an RGB color. + * cups_map_rgb_color() - Map an RGB color to a color index. We map the + * RGB color to the output colorspace & bits (we + * figure out the format when we output a page). + * cups_open() - Open the output file and initialize things. + * cups_print_pages() - Send one or more pages to the output file. + * cups_put_params() - Set pagedevice parameters. + * cups_set_color_info() - Set the color information structure based on + * the required output. + * cups_print_chunked() - Print a page of chunked pixels. + * cups_print_banded() - Print a page of banded pixels. + * cups_print_planar() - Print a page of planar pixels. + */ + +/* + * Include necessary headers... + */ + +#include "std.h" /* to stop stdlib.h redefining types */ +#include "gdevprn.h" +#include "gsparam.h" + +#include +#include +#include +#include + + +/* + * Macros... + */ + +#define x_dpi (pdev->HWResolution[0]) +#define y_dpi (pdev->HWResolution[1]) +#define cups ((gx_device_cups *)pdev) + +/* + * Macros from ; we can't include because it also + * defines DEBUG, one of our flags to insert various debugging code. + */ + +#ifndef max +# define max(a,b) ((a)<(b) ? (b) : (a)) +#endif /* !max */ + +#ifndef min +# define min(a,b) ((a)>(b) ? (b) : (a)) +#endif /* !min */ + +#ifndef abs +# define abs(x) ((x)>=0 ? (x) : -(x)) +#endif /* !abs */ + + +/* + * Procedures + */ + +private dev_proc_close_device(cups_close); +private dev_proc_get_initial_matrix(cups_get_matrix); +private int cups_get_params(gx_device *, gs_param_list *); +private dev_proc_map_color_rgb(cups_map_color_rgb); +private dev_proc_map_cmyk_color(cups_map_cmyk_color); +private dev_proc_map_rgb_color(cups_map_rgb_color); +private dev_proc_open_device(cups_open); +private int cups_print_pages(gx_device_printer *, FILE *, int); +private int cups_put_params(gx_device *, gs_param_list *); +private void cups_set_color_info(gx_device *); + +/* + * The device descriptors... + */ + +typedef struct gx_device_cups_s +{ + gx_device_common; /* Standard GhostScript device stuff */ + gx_prn_device_common; /* Standard printer device stuff */ + int page; /* Page number */ + cups_raster_t *stream; /* Raster stream */ + ppd_file_t *ppd; /* PPD file for this printer */ + cups_page_header_t header; /* PostScript page device info */ +} gx_device_cups; + +private gx_device_procs cups_procs = +{ + cups_open, + cups_get_matrix, + gx_default_sync_output, + gdev_prn_output_page, + cups_close, + cups_map_rgb_color, + cups_map_color_rgb, + NULL, /* fill_rectangle */ + NULL, /* tile_rectangle */ + NULL, /* copy_mono */ + NULL, /* copy_color */ + NULL, /* draw_line */ + gx_default_get_bits, + cups_get_params, + cups_put_params, + NULL, + NULL, /* get_xfont_procs */ + NULL, /* get_xfont_device */ + NULL, /* map_rgb_alpha_color */ + gx_page_device_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 */ + NULL, /* strip_tile_rectangle */ + NULL /* strip_copy_rop */ +}; + +gx_device_cups gs_cups_device = +{ + prn_device_body_copies(gx_device_cups, cups_procs, "cups", 85, 110, 100, 100, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, cups_print_pages), + 0, /* page */ + NULL, /* stream */ + NULL, /* ppd */ + { /* header */ + "", /* MediaClass */ + "", /* MediaColor */ + "", /* MediaType */ + "", /* OutputType */ + 0, /* AdvanceDistance */ + CUPS_ADVANCE_NONE, /* AdvanceMedia */ + CUPS_FALSE, /* Collate */ + CUPS_CUT_NONE, /* CutMedia */ + CUPS_FALSE, /* Duplex */ + { 100, 100 }, /* HWResolution */ + { 0, 0, 612, 792 }, /* ImagingBoundingBox */ + CUPS_FALSE, /* InsertSheet */ + CUPS_JOG_NONE, /* Jog */ + CUPS_EDGE_TOP, /* LeadingEdge */ + { 0, 0 }, /* Margins */ + CUPS_FALSE, /* ManualFeed */ + 0, /* MediaPosition */ + 0, /* MediaWeight */ + CUPS_FALSE, /* MirrorPrint */ + CUPS_FALSE, /* NegativePrint */ + 1, /* NumCopies */ + CUPS_ORIENT_0, /* Orientation */ + CUPS_FALSE, /* OutputFaceUp */ + { 612, 792 }, /* PageSize */ + CUPS_FALSE, /* Separations */ + CUPS_FALSE, /* TraySwitch */ + CUPS_FALSE, /* Tumble */ + 850, /* cupsWidth */ + 1100, /* cupsHeight */ + 0, /* cupsMediaType */ + 1, /* cupsBitsPerColor */ + 1, /* cupsBitsPerPixel */ + 107, /* cupsBytesPerLine */ + CUPS_ORDER_CHUNKED, /* cupsColorOrder */ + CUPS_CSPACE_KCMY, /* cupsColorSpace */ + 0, /* cupsCompression */ + 0, /* cupsRowCount */ + 0, /* cupsRowFeed */ + 0 /* cupsRowStep */ + } +}; + +/* + * Color lookup tables... + */ + +static gx_color_value lut_color_rgb[256]; +static unsigned char lut_rgb_color[gx_max_color_value + 1]; +static int cupsHaveProfile = 0; +static int cupsMatrix[3][3][gx_max_color_value + 1]; +static int cupsDensity[gx_max_color_value + 1]; + + +/* + * Local functions... + */ + +static void cups_print_chunked(gx_device_printer *, unsigned char *); +static void cups_print_banded(gx_device_printer *, unsigned char *, + unsigned char *, int); +static void cups_print_planar(gx_device_printer *, unsigned char *, + unsigned char *, int); + +/*static void cups_set_margins(gx_device *);*/ + + +/* + * 'cups_close()' - Close the output file. + */ + +private int +cups_close(gx_device *pdev) /* I - Device info */ +{ +#ifdef DEBUG + fprintf(stderr, "DEBUG: cups_close(%08x)\n", pdev); +#endif /* DEBUG */ + + if (cups->stream != NULL) + { + cupsRasterClose(cups->stream); + cups->stream = NULL; + } + +#if 0 /* Can't do this here because put_params() might close the device */ + if (cups->ppd != NULL) + { + ppdClose(cups->ppd); + cups->ppd = NULL; + } +#endif /* 0 */ + + return (gdev_prn_close(pdev)); +} + + +/* + * 'cups_get_matrix()' - Generate the default page matrix. + */ + +private void +cups_get_matrix(gx_device *pdev, /* I - Device info */ + gs_matrix *pmat) /* O - Physical transform matrix */ +{ +#ifdef DEBUG + fprintf(stderr, "DEBUG: cups_get_matrix(%08x, %08x)\n", pdev, pmat); +#endif /* DEBUG */ + + /* + * Set the raster width and height... + */ + + cups->header.cupsWidth = cups->width; + cups->header.cupsHeight = cups->height; + + /* + * Set the transform matrix... + */ + + pmat->xx = (float)cups->header.HWResolution[0] / 72.0; + pmat->xy = 0.0; + pmat->yx = 0.0; + pmat->yy = -(float)cups->header.HWResolution[1] / 72.0; + pmat->tx = -(float)cups->header.HWResolution[0] * pdev->HWMargins[0] / 72.0; + pmat->ty = (float)cups->header.HWResolution[1] * + ((float)cups->header.PageSize[1] - pdev->HWMargins[3]) / 72.0; + +#ifdef DEBUG + fprintf(stderr, "DEBUG: width = %d, height = %d\n", cups->width, + cups->height); + fprintf(stderr, "DEBUG: PageSize = [ %d %d ], HWResolution = [ %d %d ]\n", + cups->header.PageSize[0], cups->header.PageSize[1], + cups->header.HWResolution[0], cups->header.HWResolution[1]); + fprintf(stderr, "DEBUG: matrix = [ %.3f %.3f %.3f %.3f %.3f %.3f ]\n", + pmat->xx, pmat->xy, pmat->yx, pmat->yy, pmat->tx, pmat->ty); +#endif /* DEBUG */ +} + + +/* + * 'cups_get_params()' - Get pagedevice parameters. + */ + +private int /* O - Error status */ +cups_get_params(gx_device *pdev, /* I - Device info */ + gs_param_list *plist) /* I - Parameter list */ +{ + int code; /* Return code */ + + +#ifdef DEBUG + fprintf(stderr, "DEBUG: cups_get_params(%08x, %08x)\n", pdev, plist); +#endif /* DEBUG */ + + /* + * First process the "standard" page device parameters... + */ + + if ((code = gdev_prn_get_params(pdev, plist)) < 0) + return (code); + + /* + * Then write the CUPS-specific parameters... + */ + + if ((code = param_write_int(plist, "cupsWidth", + (int *)&(cups->header.cupsWidth))) < 0) + return (code); + + if ((code = param_write_int(plist, "cupsHeight", + (int *)&(cups->header.cupsHeight))) < 0) + return (code); + + if ((code = param_write_int(plist, "cupsMediaType", + (int *)&(cups->header.cupsMediaType))) < 0) + return (code); + + if ((code = param_write_int(plist, "cupsBitsPerColor", + (int *)&(cups->header.cupsBitsPerColor))) < 0) + return (code); + + if ((code = param_write_int(plist, "cupsBitsPerPixel", + (int *)&(cups->header.cupsBitsPerPixel))) < 0) + return (code); + + if ((code = param_write_int(plist, "cupsBytesPerLine", + (int *)&(cups->header.cupsBytesPerLine))) < 0) + return (code); + + if ((code = param_write_int(plist, "cupsColorOrder", + (int *)&(cups->header.cupsColorOrder))) < 0) + return (code); + + if ((code = param_write_int(plist, "cupsColorSpace", + (int *)&(cups->header.cupsColorSpace))) < 0) + return (code); + + if ((code = param_write_int(plist, "cupsCompression", + (int *)&(cups->header.cupsCompression))) < 0) + return (code); + + if ((code = param_write_int(plist, "cupsRowCount", + (int *)&(cups->header.cupsRowCount))) < 0) + return (code); + + if ((code = param_write_int(plist, "cupsRowFeed", + (int *)&(cups->header.cupsRowFeed))) < 0) + return (code); + + if ((code = param_write_int(plist, "cupsRowStep", + (int *)&(cups->header.cupsRowStep))) < 0) + return (code); + + return (0); +} + + +/* + * 'cups_map_color_rgb()' - Map a color index to an RGB color. + */ + +private int +cups_map_color_rgb(gx_device *pdev, /* I - Device info */ + gx_color_index color, /* I - Color index */ + gx_color_value prgb[3]) /* O - RGB values */ +{ + unsigned char c0, c1, c2, c3; /* Color index components */ + gx_color_value k, divk; /* Black & divisor */ + + +#ifdef DEBUG + fprintf(stderr, "DEBUG: cups_map_color_rgb(%08x, %d, %08x)\n", pdev, + color, prgb); +#endif /* DEBUG */ + + /* + * Setup the color info data as needed... + */ + + if (pdev->color_info.num_components == 0) + cups_set_color_info(pdev); + +#ifdef DEBUG + fprintf(stderr, "DEBUG: COLOR %08x = ", color); +#endif /* DEBUG */ + + /* + * Extract the color components from the color index... + */ + + switch (cups->header.cupsBitsPerColor) + { + case 1 : + c3 = color & 1; + color >>= 1; + c2 = color & 1; + color >>= 1; + c1 = color & 1; + color >>= 1; + c0 = color; + break; + case 2 : + c3 = color & 3; + color >>= 2; + c2 = color & 3; + color >>= 2; + c2 = color & 3; + color >>= 2; + c0 = color; + break; + case 4 : + c3 = color & 15; + color >>= 4; + c2 = color & 15; + color >>= 4; + c1 = color & 15; + color >>= 4; + c0 = color; + break; + case 8 : + c3 = color & 255; + color >>= 8; + c2 = color & 255; + color >>= 8; + c1 = color & 255; + color >>= 8; + c0 = color; + break; + } + + /* + * Convert the color components to RGB... + */ + + switch (cups->header.cupsColorSpace) + { + case CUPS_CSPACE_K : + prgb[0] = + prgb[1] = + prgb[2] = lut_color_rgb[c3]; + break; + + case CUPS_CSPACE_W : + prgb[0] = + prgb[1] = + prgb[2] = lut_color_rgb[c3]; + break; + + case CUPS_CSPACE_RGB : + prgb[0] = lut_color_rgb[c1]; + prgb[1] = lut_color_rgb[c2]; + prgb[2] = lut_color_rgb[c3]; + break; + + case CUPS_CSPACE_CMY : + prgb[0] = lut_color_rgb[c1]; + prgb[1] = lut_color_rgb[c2]; + prgb[2] = lut_color_rgb[c3]; + break; + + case CUPS_CSPACE_YMC : + prgb[0] = lut_color_rgb[c3]; + prgb[1] = lut_color_rgb[c2]; + prgb[2] = lut_color_rgb[c1]; + break; + + case CUPS_CSPACE_KCMY : + k = lut_color_rgb[c0]; + divk = gx_max_color_value - k; + if (divk == 0) + { + prgb[0] = 0; + prgb[1] = 0; + prgb[2] = 0; + } + else + { + prgb[0] = gx_max_color_value + divk - + gx_max_color_value * c1 / divk; + prgb[1] = gx_max_color_value + divk - + gx_max_color_value * c2 / divk; + prgb[2] = gx_max_color_value + divk - + gx_max_color_value * c3 / divk; + } + break; + + case CUPS_CSPACE_CMYK : + k = lut_color_rgb[c3]; + divk = gx_max_color_value - k; + if (divk == 0) + { + prgb[0] = 0; + prgb[1] = 0; + prgb[2] = 0; + } + else + { + prgb[0] = gx_max_color_value + divk - + gx_max_color_value * c0 / divk; + prgb[1] = gx_max_color_value + divk - + gx_max_color_value * c1 / divk; + prgb[2] = gx_max_color_value + divk - + gx_max_color_value * c2 / divk; + } + break; + + case CUPS_CSPACE_YMCK : + k = lut_color_rgb[c3]; + divk = gx_max_color_value - k; + if (divk == 0) + { + prgb[0] = 0; + prgb[1] = 0; + prgb[2] = 0; + } + else + { + prgb[0] = gx_max_color_value + divk - + gx_max_color_value * c2 / divk; + prgb[1] = gx_max_color_value + divk - + gx_max_color_value * c1 / divk; + prgb[2] = gx_max_color_value + divk - + gx_max_color_value * c0 / divk; + } + break; + } + +#ifdef DEBUG + fprintf(stderr, "%d,%d,%d\n", prgb[0], prgb[1], prgb[2]); +#endif /* DEBUG */ + + return (0); +} + + +/* + * 'cups_map_rgb_color()' - Map an RGB color to a color index. We map the + * RGB color to the output colorspace & bits (we + * figure out the format when we output a page). + */ + +private gx_color_index /* O - Color index */ +cups_map_rgb_color(gx_device *pdev, /* I - Device info */ + gx_color_value r, /* I - Red value */ + gx_color_value g, /* I - Green value */ + gx_color_value b) /* I - Blue value */ +{ + gx_color_index i; /* Temporary index */ + gx_color_value ic, im, iy, ik; /* Integral CMYKcm values */ + float divk, /* Black "divisor" */ + diff; /* Average color difference */ + int tc, tm, ty, tk; /* Temporary color values */ + + +#ifdef DEBUG + fprintf(stderr, "DEBUG: cups_map_rgb_color(%08x, %d, %d, %d)\n", pdev, r, g, b); +#endif /* DEBUG */ + + /* + * Setup the color info data as needed... + */ + + if (pdev->color_info.num_components == 0) + cups_set_color_info(pdev); + + /* + * Do color correction as needed... + */ + + if (cupsHaveProfile) + { + /* + * Compute CMYK values... + */ + + ic = gx_max_color_value - r; + im = gx_max_color_value - g; + iy = gx_max_color_value - b; + ik = min(ic, min(im, iy)); + ic -= ik; + im -= ik; + iy -= ik; + + /* + * Color correct CMY... + */ + + tc = cupsMatrix[0][0][ic] + + cupsMatrix[0][1][im] + + cupsMatrix[0][2][iy] + + ik; + tm = cupsMatrix[1][0][ic] + + cupsMatrix[1][1][im] + + cupsMatrix[1][2][iy] + + ik; + ty = cupsMatrix[2][0][ic] + + cupsMatrix[2][1][im] + + cupsMatrix[2][2][iy] + + ik; + + /* + * Density correct combined CMYK... + */ + + if (tc < 0) + r = gx_max_color_value; + else if (tc > gx_max_color_value) + r = gx_max_color_value - cupsDensity[gx_max_color_value]; + else + r = gx_max_color_value - cupsDensity[tc]; + + if (tm < 0) + g = gx_max_color_value; + else if (tm > gx_max_color_value) + g = gx_max_color_value - cupsDensity[gx_max_color_value]; + else + g = gx_max_color_value - cupsDensity[tm]; + + if (ty < 0) + b = gx_max_color_value; + else if (ty > gx_max_color_value) + b = gx_max_color_value - cupsDensity[gx_max_color_value]; + else + b = gx_max_color_value - cupsDensity[ty]; + } + + /* + * Convert the RGB color to a color index... + */ + + switch (cups->header.cupsColorSpace) + { + case CUPS_CSPACE_W : + i = lut_rgb_color[(r * 31 + g * 61 + b * 8) / 100]; + break; + + case CUPS_CSPACE_RGB : + ic = lut_rgb_color[r]; + im = lut_rgb_color[g]; + iy = lut_rgb_color[b]; + + switch (cups->header.cupsBitsPerColor) + { + case 1 : + i = (((ic << 1) | im) << 1) | iy; + break; + case 2 : + i = (((ic << 2) | im) << 2) | iy; + break; + case 4 : + i = (((ic << 4) | im) << 4) | iy; + break; + case 8 : + i = (((ic << 8) | im) << 8) | iy; + break; + } + break; + + case CUPS_CSPACE_K : + i = lut_rgb_color[gx_max_color_value - (r * 31 + g * 61 + b * 8) / 100]; + break; + + case CUPS_CSPACE_CMY : + if (cups->header.cupsBitsPerColor == 1) + { + ic = lut_rgb_color[gx_max_color_value - r]; + im = lut_rgb_color[gx_max_color_value - g]; + iy = lut_rgb_color[gx_max_color_value - b]; + } + else + { + ic = gx_max_color_value - r; + im = gx_max_color_value - g; + iy = gx_max_color_value - b; + ik = min(ic, min(im, iy)); + + ic = lut_rgb_color[(gx_color_value)((float)(gx_max_color_value - g / 4) / + (float)gx_max_color_value * (float)(ic - ik)) + ik]; + im = lut_rgb_color[(gx_color_value)((float)(gx_max_color_value - b / 4) / + (float)gx_max_color_value * (float)(im - ik)) + ik]; + iy = lut_rgb_color[(gx_color_value)((float)(gx_max_color_value - r / 4) / + (float)gx_max_color_value * (float)(iy - ik)) + ik]; + } + + switch (cups->header.cupsBitsPerColor) + { + case 1 : + i = (((ic << 1) | im) << 1) | iy; + break; + case 2 : + i = (((ic << 2) | im) << 2) | iy; + break; + case 4 : + i = (((ic << 4) | im) << 4) | iy; + break; + case 8 : + i = (((ic << 8) | im) << 8) | iy; + break; + } + break; + + case CUPS_CSPACE_YMC : + if (cups->header.cupsBitsPerColor == 1) + { + ic = lut_rgb_color[gx_max_color_value - r]; + im = lut_rgb_color[gx_max_color_value - g]; + iy = lut_rgb_color[gx_max_color_value - b]; + } + else + { + ic = gx_max_color_value - r; + im = gx_max_color_value - g; + iy = gx_max_color_value - b; + ik = min(ic, min(im, iy)); + + ic = lut_rgb_color[(gx_color_value)((float)(gx_max_color_value - g / 4) / + (float)gx_max_color_value * (float)(ic - ik)) + ik]; + im = lut_rgb_color[(gx_color_value)((float)(gx_max_color_value - b / 4) / + (float)gx_max_color_value * (float)(im - ik)) + ik]; + iy = lut_rgb_color[(gx_color_value)((float)(gx_max_color_value - r / 4) / + (float)gx_max_color_value * (float)(iy - ik)) + ik]; + } + + switch (cups->header.cupsBitsPerColor) + { + case 1 : + i = (((iy << 1) | im) << 1) | ic; + break; + case 2 : + i = (((iy << 2) | im) << 2) | ic; + break; + case 4 : + i = (((iy << 4) | im) << 4) | ic; + break; + case 8 : + i = (((iy << 8) | im) << 8) | ic; + break; + } + break; + + case CUPS_CSPACE_CMYK : + ic = gx_max_color_value - r; + im = gx_max_color_value - g; + iy = gx_max_color_value - b; + ik = min(ic, min(im, iy)); + + if (ik > 0) + { + diff = 1.0 - (float)(max(ic, max(im, iy)) - ik) / + (float)gx_max_color_value; + ik = (int)(diff * (float)ik); + } + + if (ik == gx_max_color_value) + { + ik = lut_rgb_color[ik]; + ic = 0; + im = 0; + iy = 0; + } + else if (cups->header.cupsBitsPerColor == 1) + { + ic = lut_rgb_color[ic - ik]; + im = lut_rgb_color[im - ik]; + iy = lut_rgb_color[iy - ik]; + ik = lut_rgb_color[ik]; + } + else + { + divk = (float)gx_max_color_value / (float)(gx_max_color_value - ik); + tc = (float)(ic - ik) * divk; + tm = (float)(im - ik) * divk; + ty = (float)(iy - ik) * divk; + + if (tc >= gx_max_color_value) + ic = lut_rgb_color[gx_max_color_value]; + else + ic = lut_rgb_color[tc]; + + if (tm >= gx_max_color_value) + im = lut_rgb_color[gx_max_color_value]; + else + im = lut_rgb_color[tm]; + + if (ty >= gx_max_color_value) + iy = lut_rgb_color[gx_max_color_value]; + else + iy = lut_rgb_color[ty]; + + ik = lut_rgb_color[ik]; + } + + switch (cups->header.cupsBitsPerColor) + { + case 1 : + i = (((((ic << 1) | im) << 1) | iy) << 1) | ik; + break; + case 2 : + i = (((((ic << 2) | im) << 2) | iy) << 2) | ik; + break; + case 4 : + i = (((((ic << 4) | im) << 4) | iy) << 4) | ik; + break; + case 8 : + i = (((((ic << 8) | im) << 8) | iy) << 8) | ik; + break; + } + + if (gs_log_errors > 1) + fprintf(stderr, "DEBUG: CMY (%d,%d,%d) -> CMYK %08.8x (%d,%d,%d,%d)\n", + r, g, b, i, ic, im, iy, ik); + break; + + case CUPS_CSPACE_YMCK : + ic = gx_max_color_value - r; + im = gx_max_color_value - g; + iy = gx_max_color_value - b; + ik = min(ic, min(im, iy)); + + if (ik > 0) + { + diff = 1.0 - (float)(max(ic, max(im, iy)) - ik) / + (float)gx_max_color_value; + ik = (int)(diff * (float)ik); + } + + if (ik == gx_max_color_value) + { + ik = lut_rgb_color[ik]; + ic = 0; + im = 0; + iy = 0; + } + else if (cups->header.cupsBitsPerColor == 1) + { + ic = lut_rgb_color[ic - ik]; + im = lut_rgb_color[im - ik]; + iy = lut_rgb_color[iy - ik]; + ik = lut_rgb_color[ik]; + } + else + { + divk = (float)gx_max_color_value / (float)(gx_max_color_value - ik); + tc = (float)(ic - ik) * divk; + tm = (float)(im - ik) * divk; + ty = (float)(iy - ik) * divk; + + if (tc >= gx_max_color_value) + ic = lut_rgb_color[gx_max_color_value]; + else + ic = lut_rgb_color[tc]; + + if (tm >= gx_max_color_value) + im = lut_rgb_color[gx_max_color_value]; + else + im = lut_rgb_color[tm]; + + if (ty >= gx_max_color_value) + iy = lut_rgb_color[gx_max_color_value]; + else + iy = lut_rgb_color[ty]; + + ik = lut_rgb_color[ik]; + } + + switch (cups->header.cupsBitsPerColor) + { + case 1 : + i = (((((iy << 1) | im) << 1) | ic) << 1) | ik; + break; + case 2 : + i = (((((iy << 2) | im) << 2) | ic) << 2) | ik; + break; + case 4 : + i = (((((iy << 4) | im) << 4) | ic) << 4) | ik; + break; + case 8 : + i = (((((iy << 8) | im) << 8) | ic) << 8) | ik; + break; + } + break; + + case CUPS_CSPACE_KCMYcm : + if (cups->header.cupsBitsPerColor == 1) + { + ic = gx_max_color_value - r; + im = gx_max_color_value - g; + iy = gx_max_color_value - b; + ik = min(ic, min(im, iy)); + + if (ik > 0) + { + diff = 1.0 - (float)(max(ic, max(im, iy)) - ik) / (float)ik; + ik = (int)(diff * (float)ik); + } + + ic = lut_rgb_color[ic - ik]; + im = lut_rgb_color[im - ik]; + iy = lut_rgb_color[iy - ik]; + ik = lut_rgb_color[ik]; + if (ik) + i = 32; + else if (ic && im) + i = 3; + else if (ic && iy) + i = 6; + else if (im && iy) + i = 12; + else if (ic) + i = 16; + else if (im) + i = 8; + else if (iy) + i = 4; + else + i = 0; + break; + } + + case CUPS_CSPACE_KCMY : + ic = gx_max_color_value - r; + im = gx_max_color_value - g; + iy = gx_max_color_value - b; + ik = min(ic, min(im, iy)); + + if (ik > 0) + { + diff = 1.0 - (float)(max(ic, max(im, iy)) - ik) / + (float)gx_max_color_value; + ik = (int)(diff * (float)ik); + } + + if (ik == gx_max_color_value) + { + ik = lut_rgb_color[ik]; + ic = 0; + im = 0; + iy = 0; + } + else if (cups->header.cupsBitsPerColor == 1) + { + ic = lut_rgb_color[ic - ik]; + im = lut_rgb_color[im - ik]; + iy = lut_rgb_color[iy - ik]; + ik = lut_rgb_color[ik]; + } + else + { + divk = (float)gx_max_color_value / (float)(gx_max_color_value - ik); + tc = (float)(ic - ik) * divk; + tm = (float)(im - ik) * divk; + ty = (float)(iy - ik) * divk; + + if (tc >= gx_max_color_value) + ic = lut_rgb_color[gx_max_color_value]; + else + ic = lut_rgb_color[tc]; + + if (tm >= gx_max_color_value) + im = lut_rgb_color[gx_max_color_value]; + else + im = lut_rgb_color[tm]; + + if (ty >= gx_max_color_value) + iy = lut_rgb_color[gx_max_color_value]; + else + iy = lut_rgb_color[ty]; + + ik = lut_rgb_color[ik]; + } + + switch (cups->header.cupsBitsPerColor) + { + case 1 : + i = (((((ik << 1) | ic) << 1) | im) << 1) | iy; + break; + case 2 : + i = (((((ik << 2) | ic) << 2) | im) << 2) | iy; + break; + case 4 : + i = (((((ik << 4) | ic) << 4) | im) << 4) | iy; + break; + case 8 : + i = (((((ik << 8) | ic) << 8) | im) << 8) | iy; + break; + } + break; + } + +#ifdef DEBUG + fprintf(stderr, "DEBUG: RGB %d,%d,%d = %08x\n", r, g, b, i); +#endif /* DEBUG */ + + return (i); +} + + +/* + * 'cups_open()' - Open the output file and initialize things. + */ + +private int /* O - Error status */ +cups_open(gx_device *pdev) /* I - Device info */ +{ + int code; /* Return status */ + + +#ifdef DEBUG + fprintf(stderr, "DEBUG: cups_open(%08x)\n", pdev); +#endif /* DEBUG */ + + if (cups->page == 0) + { + fputs("INFO: Processing page 1...\n", stderr); + cups->page = 1; + } + + if (pdev->color_info.num_components == 0) + cups_set_color_info(pdev); + + if ((code = gdev_prn_open(pdev)) != 0) + return (code); + + if (cups->ppd == NULL) + cups->ppd = ppdOpenFile(getenv("PPD")); + + return (0); +} + + +/* + * 'cups_print_pages()' - Send one or more pages to the output file. + */ + +private int /* O - 0 if everything is OK */ +cups_print_pages(gx_device_printer *pdev, /* I - Device info */ + FILE *fp, /* I - Output file */ + int num_copies) /* I - Number of copies */ +{ + int copy; /* Copy number */ + int srcbytes; /* Byte width of scanline */ + int x, y; /* Current position in image */ + unsigned char *src, /* Scanline data */ + *dst; /* Bitmap data */ + + +#ifdef DEBUG + fprintf(stderr, "DEBUG: cups_print_pages(%08x, %08x, %d)\n", pdev, fp, + num_copies); +#endif /* DEBUG */ + + /* + * Figure out the number of bytes per line... + */ + + switch (cups->header.cupsColorOrder) + { + case CUPS_ORDER_CHUNKED : + cups->header.cupsBytesPerLine = (cups->header.cupsBitsPerPixel * + cups->header.cupsWidth + 7) / 8; + break; + + case CUPS_ORDER_BANDED : + cups->header.cupsBytesPerLine = (cups->header.cupsBitsPerPixel * + cups->header.cupsWidth + 7) / 8 * + cups->color_info.num_components; + break; + + case CUPS_ORDER_PLANAR : + cups->header.cupsBytesPerLine = (cups->header.cupsBitsPerPixel * + cups->header.cupsWidth + 7) / 8; + break; + } + + /* + * Compute the width of a scanline and allocate input/output buffers... + */ + + srcbytes = gdev_prn_raster(pdev); + src = (unsigned char *)gs_malloc(srcbytes, 1, "cups_print_pages"); + + if (src == NULL) /* can't allocate input buffer */ + return_error(gs_error_VMerror); + + if (cups->header.cupsColorOrder != CUPS_ORDER_CHUNKED) + { + /* + * Need an output buffer, too... + */ + + dst = (unsigned char *)gs_malloc(cups->header.cupsBytesPerLine, 1, + "cups_print_pages"); + + if (dst == NULL) /* can't allocate working area */ + return_error(gs_error_VMerror); + } + else + dst = NULL; + + /* + * See if the stream has been initialized yet... + */ + + if (cups->stream == NULL) + { + if (fp == NULL) + cups->stream = cupsRasterOpen(1, CUPS_RASTER_WRITE); + else + cups->stream = cupsRasterOpen(fileno(fp), CUPS_RASTER_WRITE); + + if (cups->stream == NULL) + { + perror("ERROR: Unable to open raster stream - "); + gs_exit(0); + } + } + + /* + * Output a page of graphics... + */ + + if (cups->ppd != NULL && !cups->ppd->manual_copies) + { + cups->header.NumCopies = num_copies; + num_copies = 1; + } + +#ifdef DEBUG + fprintf(stderr, "DEBUG: cupsWidth = %d, cupsHeight = %d, cupsBytesPerLine = %d\n", + cups->header.cupsWidth, cups->header.cupsHeight, + cups->header.cupsBytesPerLine); +#endif /* DEBUG */ + + for (copy = num_copies; copy > 0; copy --) + { + cupsRasterWriteHeader(cups->stream, &(cups->header)); + + if (pdev->color_info.num_components == 1) + cups_print_chunked(pdev, src); + else + switch (cups->header.cupsColorOrder) + { + case CUPS_ORDER_CHUNKED : + cups_print_chunked(pdev, src); + break; + case CUPS_ORDER_BANDED : + cups_print_banded(pdev, src, dst, srcbytes); + break; + case CUPS_ORDER_PLANAR : + cups_print_planar(pdev, src, dst, srcbytes); + break; + } + } + + /* + * Free temporary storage and return... + */ + + gs_free((char *)src, srcbytes, 1, "cups_print_pages"); + if (dst) + gs_free((char *)dst, cups->header.cupsBytesPerLine, 1, "cups_print_pages"); + + cups->page ++; + fprintf(stderr, "INFO: Processing page %d...\n", cups->page); + + return (0); +} + + +/* + * 'cups_put_params()' - Set pagedevice parameters. + */ + +private int /* O - Error status */ +cups_put_params(gx_device *pdev, /* I - Device info */ + gs_param_list *plist) /* I - Parameter list */ +{ + int i; /* Looping var */ + float margins[4]; /* Physical margins of print */ + ppd_size_t *size; /* Page size */ + int olddepth; /* Old depth value */ + int code; /* Error code */ + int intval; /* Integer value */ + bool boolval; /* Boolean value */ + float floatval; /* Floating point value */ + gs_param_string stringval; /* String value */ + gs_param_float_array arrayval; /* Float array value */ + + +#ifdef DEBUG + fprintf(stderr, "DEBUG: cups_put_params(%08x, %08x)\n", pdev, plist); +#endif /* DEBUG */ + + /* + * Process other options for CUPS... + */ + +#define stringoption(name, sname) \ + if ((code = param_read_string(plist, sname, &stringval)) < 0) \ + { \ + param_signal_error(plist, sname, code); \ + return (code); \ + } \ + else if (code == 0) \ + { \ + strncpy(cups->header.name, (const char *)stringval.data, \ + stringval.size); \ + cups->header.name[stringval.size] = '\0'; \ + } + +#define intoption(name, sname, type) \ + if ((code = param_read_int(plist, sname, &intval)) < 0) \ + { \ + param_signal_error(plist, sname, code); \ + return (code); \ + } \ + else if (code == 0) \ + cups->header.name = (type)intval; + +#define floatoption(name, sname) \ + if ((code = param_read_float(plist, sname, &floatval)) < 0) \ + { \ + param_signal_error(plist, sname, code); \ + return (code); \ + } \ + else if (code == 0) \ + cups->header.name = (unsigned)floatval; + +#define booloption(name, sname) \ + if ((code = param_read_bool(plist, sname, &boolval)) < 0) \ + { \ + if ((code = param_read_null(plist, sname)) < 0) \ + { \ + param_signal_error(plist, sname, code); \ + return (code); \ + } \ + if (code == 0) \ + cups->header.name = CUPS_FALSE; \ + } \ + else if (code == 0) \ + cups->header.name = (cups_bool_t)boolval; + +#define arrayoption(name, sname, count) \ + if ((code = param_read_float_array(plist, sname, &arrayval)) < 0) \ + { \ + if ((code = param_read_null(plist, sname)) < 0) \ + { \ + param_signal_error(plist, sname, code); \ + return (code); \ + } \ + if (code == 0) \ + for (i = 0; i < count; i ++) \ + cups->header.name[i] = 0; \ + } \ + else if (code == 0) \ + { \ + for (i = 0; i < count; i ++) \ + cups->header.name[i] = (unsigned)arrayval.data[i]; \ + } + + stringoption(MediaClass, "MediaClass") + stringoption(MediaColor, "MediaColor") + stringoption(MediaType, "MediaType") + stringoption(OutputType, "OutputType") + floatoption(AdvanceDistance, "AdvanceDistance") + intoption(AdvanceMedia, "AdvanceMedia", cups_adv_t) + booloption(Collate, "Collate") + intoption(CutMedia, "CutMedia", cups_cut_t) + booloption(Duplex, "Duplex") + arrayoption(ImagingBoundingBox, "ImagingBoundingBox", 4) + booloption(InsertSheet, "InsertSheet") + intoption(Jog, "Jog", cups_jog_t) + intoption(LeadingEdge, "LeadingEdge", cups_edge_t) + arrayoption(Margins, "Margins", 2) + booloption(ManualFeed, "ManualFeed") + intoption(MediaPosition, "cupsMediaPosition", unsigned) + floatoption(MediaWeight, "MediaWeight") + booloption(MirrorPrint, "MirrorPrint") + booloption(NegativePrint, "NegativePrint") + intoption(NumCopies, "NumCopies", unsigned) + intoption(Orientation, "Orientation", cups_orient_t) + booloption(OutputFaceUp, "OutputFaceUp") + booloption(Separations, "Separations") + booloption(TraySwitch, "TraySwitch") + booloption(Tumble, "Tumble") + intoption(cupsWidth, "cupsWidth", unsigned) + intoption(cupsHeight, "cupsHeight", unsigned) + intoption(cupsMediaType, "cupsMediaType", unsigned) + intoption(cupsBitsPerColor, "cupsBitsPerColor", unsigned) + intoption(cupsBitsPerPixel, "cupsBitsPerPixel", unsigned) + intoption(cupsBytesPerLine, "cupsBytesPerLine", unsigned) + intoption(cupsColorOrder, "cupsColorOrder", cups_order_t) + intoption(cupsColorSpace, "cupsColorSpace", cups_cspace_t) + intoption(cupsCompression, "cupsCompression", unsigned) + intoption(cupsRowCount, "cupsRowCount", unsigned) + intoption(cupsRowFeed, "cupsRowFeed", unsigned) + intoption(cupsRowStep, "cupsRowStep", unsigned) + + /* + * Then process standard page device options... + */ + + if ((code = gdev_prn_put_params(pdev, plist)) < 0) + return (code); + + cups->header.HWResolution[0] = pdev->HWResolution[0]; + cups->header.HWResolution[1] = pdev->HWResolution[1]; + + cups->header.PageSize[0] = pdev->MediaSize[0]; + cups->header.PageSize[1] = pdev->MediaSize[1]; + + /* + * Check for a change in color depth... + */ + + olddepth = pdev->color_info.depth; + cups_set_color_info(pdev); + + if (olddepth != pdev->color_info.depth && pdev->is_open) + gs_closedevice(pdev); + + /* + * Compute the page margins... + */ + + if (cups->ppd != NULL) + { + /* + * Set the margins from the PPD file... + */ + + for (i = cups->ppd->num_sizes, size = cups->ppd->sizes; + i > 0; + i --, size ++) + if (size->width == cups->header.PageSize[0] && + size->length == cups->header.PageSize[1]) + break; + + if (i == 0) + { + /* + * Pull margins from custom page size (0 or whatever is defined + * by the PPD file... + */ + + margins[0] = cups->ppd->custom_margins[0] / 72.0; + margins[1] = cups->ppd->custom_margins[1] / 72.0; + margins[2] = cups->ppd->custom_margins[2] / 72.0; + margins[3] = cups->ppd->custom_margins[3] / 72.0; + } + else + { + /* + * Pull the margins from the size entry; since the margins are not + * like the bounding box we have to adjust the top and right values + * accordingly. + */ + + margins[0] = size->left / 72.0; + margins[1] = size->bottom / 72.0; + margins[2] = (size->width - size->right) / 72.0; + margins[3] = (size->length - size->top) / 72.0; + } + } + else + { + /* + * Set default margins of 0.0... + */ + + memset(margins, 0, sizeof(margins)); + } + +#ifdef DEBUG + fprintf(stderr, "DEBUG: ppd = %08x\n", cups->ppd); + fprintf(stderr, "DEBUG: MediaSize = [ %.3f %.3f ]\n", + pdev->MediaSize[0], pdev->MediaSize[1]); + fprintf(stderr, "DEBUG: margins = [ %.3f %.3f %.3f %.3f ]\n", + margins[0], margins[1], margins[2], margins[3]); + fprintf(stderr, "DEBUG: HWResolution = [ %.3f %.3f ]\n", + pdev->HWResolution[0], pdev->HWResolution[1]); + fprintf(stderr, "DEBUG: width = %d, height = %d\n", + pdev->width, pdev->height); + fprintf(stderr, "DEBUG: HWMargins = [ %.3f %.3f %.3f %.3f ]\n", + pdev->HWMargins[0], pdev->HWMargins[1], + pdev->HWMargins[2], pdev->HWMargins[3]); +#endif /* DEBUG */ + + /* + * Set the margins and update the bitmap size... + */ + + gx_device_set_margins(pdev, margins, false); + + if ((code = gdev_prn_put_params(pdev, plist)) < 0) + return (code); + + return (0); +} + + +/* + * 'cups_set_color_info()' - Set the color information structure based on + * the required output. + */ + +private void +cups_set_color_info(gx_device *pdev) /* I - Device info */ +{ + int i, j, k; /* Looping vars */ + float d, g; /* Density and gamma correction */ + char resolution[41]; /* Resolution string */ + ppd_profile_t *profile; /* Color profile information */ + + +#ifdef DEBUG + fprintf(stderr, "DEBUG: cups_set_color_info(%08x)\n", pdev); +#endif /* DEBUG */ + + switch (cups->header.cupsColorSpace) + { + default : + case CUPS_CSPACE_W : + case CUPS_CSPACE_K : + cups->header.cupsBitsPerPixel = cups->header.cupsBitsPerColor; + cups->color_info.depth = cups->header.cupsBitsPerPixel; + cups->color_info.num_components = 1; + break; + + case CUPS_CSPACE_CMY : + case CUPS_CSPACE_YMC : + case CUPS_CSPACE_RGB : + if (cups->header.cupsColorOrder != CUPS_ORDER_CHUNKED) + cups->header.cupsBitsPerPixel = cups->header.cupsBitsPerColor; + else if (cups->header.cupsBitsPerColor < 8) + cups->header.cupsBitsPerPixel = 4 * cups->header.cupsBitsPerColor; + else + cups->header.cupsBitsPerPixel = 3 * cups->header.cupsBitsPerColor; + + if (cups->header.cupsBitsPerColor < 8) + cups->color_info.depth = 4 * cups->header.cupsBitsPerColor; + else + cups->color_info.depth = 3 * cups->header.cupsBitsPerColor; + + cups->color_info.num_components = 3; + break; + + case CUPS_CSPACE_KCMYcm : + if (cups->header.cupsBitsPerColor == 1) + { + cups->header.cupsBitsPerPixel = 8; + cups->color_info.depth = 8; + cups->color_info.num_components = 6; + break; + } + + case CUPS_CSPACE_CMYK : + case CUPS_CSPACE_YMCK : + case CUPS_CSPACE_KCMY : + if (cups->header.cupsColorOrder != CUPS_ORDER_CHUNKED) + cups->header.cupsBitsPerPixel = cups->header.cupsBitsPerColor; + else + cups->header.cupsBitsPerPixel = 4 * cups->header.cupsBitsPerColor; + + cups->color_info.depth = 4 * cups->header.cupsBitsPerColor; + cups->color_info.num_components = 4; + break; + } + + if (cups->header.cupsColorSpace != CUPS_CSPACE_W && + cups->header.cupsColorSpace != CUPS_CSPACE_K) + { + cups->color_info.max_gray = (1 << cups->header.cupsBitsPerColor) - 1; + cups->color_info.max_color = (1 << cups->header.cupsBitsPerColor) - 1; + cups->color_info.dither_grays = (1 << cups->header.cupsBitsPerColor); + cups->color_info.dither_colors = (1 << cups->header.cupsBitsPerColor); + } + else + { + cups->color_info.max_gray = (1 << cups->header.cupsBitsPerColor) - 1; + cups->color_info.max_color = 0; + cups->color_info.dither_grays = (1 << cups->header.cupsBitsPerColor); + cups->color_info.dither_colors = 0; + } + + /* + * Compute the lookup tables... + */ + + for (i = 0; i <= gx_max_color_value; i ++) + lut_rgb_color[i] = cups->color_info.max_gray * i / gx_max_color_value; + + for (i = 0; i < cups->color_info.dither_grays; i ++) + lut_color_rgb[i] = gx_max_color_value * i / cups->color_info.max_gray; + +#ifdef DEBUG + fprintf(stderr, "DEBUG: num_components = %d, depth = %d\n", + cups->color_info.num_components, cups->color_info.depth); + fprintf(stderr, "DEBUG: cupsColorSpace = %d, cupsColorOrder = %d\n", + cups->header.cupsColorSpace, cups->header.cupsColorOrder); + fprintf(stderr, "DEBUG: cupsBitsPerPixel = %d, cupsBitsPerColor = %d\n", + cups->header.cupsBitsPerPixel, cups->header.cupsBitsPerColor); + fprintf(stderr, "DEBUG: max_gray = %d, dither_grays = %d\n", + cups->color_info.max_gray, cups->color_info.dither_grays); + fprintf(stderr, "DEBUG: max_color = %d, dither_colors = %d\n", + cups->color_info.max_color, cups->color_info.dither_colors); +#endif /* DEBUG */ + + /* + * Set the color profile as needed... + */ + + cupsHaveProfile = 0; + + if (cups->ppd != NULL && cups->header.cupsBitsPerColor == 8) + { + /* + * Find the appropriate color profile... + */ + + if (pdev->HWResolution[0] != pdev->HWResolution[1]) + sprintf(resolution, "%.0fx%.0fdpi", pdev->HWResolution[0], + pdev->HWResolution[1]); + else + sprintf(resolution, "%.0fdpi", pdev->HWResolution[0]); + + for (i = 0, profile = cups->ppd->profiles; + i < cups->ppd->num_profiles; + i ++, profile ++) + if ((strcmp(profile->resolution, resolution) == 0 || + profile->resolution[0] == '-') && + (strcmp(profile->media_type, cups->header.MediaType) == 0 || + profile->media_type[0] == '-')) + break; + + /* + * If we found a color profile, use it! + */ + + if (i < cups->ppd->num_profiles) + { +#ifdef DEBUG + fputs("DEBUG: Using color profile!\n", stderr); +#endif /* DEBUG */ + + cupsHaveProfile = 1; + + for (i = 0; i < 3; i ++) + for (j = 0; j < 3; j ++) + for (k = 0; k <= gx_max_color_value; k ++) + { + cupsMatrix[i][j][k] = (int)((float)k * profile->matrix[i][j] + 0.5); + +#ifdef DEBUG + if ((k & 4095) == 0) + fprintf(stderr, "DEBUG: cupsMatrix[%d][%d][%d] = %d\n", + i, j, k, cupsMatrix[i][j][k]); +#endif /* DEBUG */ + } + + d = profile->density; + g = 1.0 / profile->density; + + for (k = 0; k <= gx_max_color_value; k ++) + { + cupsDensity[k] = (int)((float)gx_max_color_value * d * + pow((float)k / (float)gx_max_color_value, g) + + 0.5); +#ifdef DEBUG + if ((k & 4095) == 0) + fprintf(stderr, "DEBUG: cupsDensity[%d] = %d\n", k, cupsDensity[k]); +#endif /* DEBUG */ + } + } + } +} + + +/* + * 'cups_print_chunked()' - Print a page of chunked pixels. + */ + +static void +cups_print_chunked(gx_device_printer *pdev, /* I - Printer device */ + unsigned char *src) /* I - Scanline buffer */ +{ + int y; /* Looping var */ + unsigned char *srcptr; /* Pointer to data */ + + + /* + * Loop through the page bitmap and write chunked pixels (the format + * is identical to GhostScript's... + */ + + for (y = 0; y < cups->height; y ++) + { + /* + * Grab the scanline data... + */ + + if (gdev_prn_get_bits((gx_device_printer *)pdev, y, src, &srcptr) < 0) + { + fprintf(stderr, "ERROR: Unable to get scanline %d!\n", y); + gs_exit(1); + } + + /* + * Write the scanline data to the raster stream... + */ + + cupsRasterWritePixels(cups->stream, srcptr, cups->header.cupsBytesPerLine); + } +} + + +/* + * 'cups_print_banded()' - Print a page of banded pixels. + */ + +static void +cups_print_banded(gx_device_printer *pdev, /* I - Printer device */ + unsigned char *src, /* I - Scanline buffer */ + unsigned char *dst, /* I - Bitmap buffer */ + int srcbytes) /* I - Number of bytes in src */ +{ + int x; /* Looping var */ + int y; /* Looping var */ + int bandbytes; /* Bytes per band */ + unsigned char bit; /* Current bit */ + unsigned char temp; /* Temporary variable */ + unsigned char *srcptr; /* Pointer to data */ + unsigned char *cptr, *mptr, *yptr, *kptr; /* Pointer to components */ + unsigned char *lcptr, *lmptr; /* ... */ + + + /* + * Loop through the page bitmap and write banded pixels... We have + * to separate each chunked color as needed... + */ + + bandbytes = cups->header.cupsBytesPerLine / pdev->color_info.num_components; + + for (y = 0; y < cups->height; y ++) + { + /* + * Grab the scanline data... + */ + + if (gdev_prn_get_bits((gx_device_printer *)pdev, y, src, &srcptr) < 0) + { + fprintf(stderr, "ERROR: Unable to get scanline %d!\n", y); + gs_exit(1); + } + + /* + * Separate the chunked colors into their components... + */ + + if (srcptr[0] == 0 && memcmp(srcptr, srcptr + 1, srcbytes - 1) == 0) + memset(dst, 0, cups->header.cupsBytesPerLine); + else + switch (cups->header.cupsBitsPerColor) + { + case 1 : + memset(dst, 0, cups->header.cupsBytesPerLine); + + switch (cups->header.cupsColorSpace) + { + case CUPS_CSPACE_RGB : + case CUPS_CSPACE_CMY : + case CUPS_CSPACE_YMC : + for (x = cups->width, cptr = dst, mptr = cptr + bandbytes, + yptr = mptr + bandbytes, bit = 128; + x > 0; + x --, srcptr ++) + { + if (*srcptr & 0x40) + *cptr |= bit; + if (*srcptr & 0x20) + *mptr |= bit; + if (*srcptr & 0x10) + *yptr |= bit; + + bit >>= 1; + x --; + if (x == 0) + break; + + if (*srcptr & 0x4) + *cptr |= bit; + if (*srcptr & 0x2) + *mptr |= bit; + if (*srcptr & 0x1) + *yptr |= bit; + + if (bit > 1) + bit >>= 1; + else + { + cptr ++; + mptr ++; + yptr ++; + bit = 128; + } + } + break; + case CUPS_CSPACE_CMYK : + case CUPS_CSPACE_YMCK : + case CUPS_CSPACE_KCMY : + for (x = cups->width, cptr = dst, mptr = cptr + bandbytes, + yptr = mptr + bandbytes, kptr = yptr + bandbytes, + bit = 128; + x > 0; + x --, srcptr ++) + { + if (*srcptr & 0x80) + *cptr |= bit; + if (*srcptr & 0x40) + *mptr |= bit; + if (*srcptr & 0x20) + *yptr |= bit; + if (*srcptr & 0x10) + *kptr |= bit; + + bit >>= 1; + x --; + if (x == 0) + break; + + if (*srcptr & 0x8) + *cptr |= bit; + if (*srcptr & 0x4) + *mptr |= bit; + if (*srcptr & 0x2) + *yptr |= bit; + if (*srcptr & 0x1) + *kptr |= bit; + + if (bit > 1) + bit >>= 1; + else + { + cptr ++; + mptr ++; + yptr ++; + kptr ++; + bit = 128; + } + } + break; + case CUPS_CSPACE_KCMYcm : + for (x = cups->width, cptr = dst, mptr = cptr + bandbytes, + yptr = mptr + bandbytes, kptr = yptr + bandbytes, + lcptr = kptr + bandbytes, lmptr = lcptr + bandbytes, + bit = 128; + x > 0; + x --, srcptr ++) + { + if (*srcptr & 0x20) + *cptr |= bit; + if (*srcptr & 0x10) + *mptr |= bit; + if (*srcptr & 0x08) + *yptr |= bit; + if (*srcptr & 0x04) + *kptr |= bit; + if (*srcptr & 0x02) + *lcptr |= bit; + if (*srcptr & 0x01) + *lmptr |= bit; + + if (bit > 1) + bit >>= 1; + else + { + cptr ++; + mptr ++; + yptr ++; + kptr ++; + lcptr ++; + lmptr ++; + bit = 128; + } + } + break; + } + break; + + case 2 : + memset(dst, 0, cups->header.cupsBytesPerLine); + + switch (cups->header.cupsColorSpace) + { + case CUPS_CSPACE_RGB : + case CUPS_CSPACE_CMY : + case CUPS_CSPACE_YMC : + for (x = cups->width, cptr = dst, mptr = cptr + bandbytes, + yptr = mptr + bandbytes, bit = 0xc0; + x > 0; + x --, srcptr ++) + switch (bit) + { + case 0xc0 : + if (temp = *srcptr & 0x30) + *cptr |= temp << 2; + if (temp = *srcptr & 0x0c) + *mptr |= temp << 4; + if (temp = *srcptr & 0x03) + *yptr |= temp << 6; + + bit = 0x30; + break; + case 0x30 : + if (temp = *srcptr & 0x30) + *cptr |= temp; + if (temp = *srcptr & 0x0c) + *mptr |= temp << 2; + if (temp = *srcptr & 0x03) + *yptr |= temp << 4; + + bit = 0x0c; + break; + case 0x0c : + if (temp = *srcptr & 0x30) + *cptr |= temp >> 2; + if (temp = *srcptr & 0x0c) + *mptr |= temp; + if (temp = *srcptr & 0x03) + *yptr |= temp << 2; + + bit = 0x03; + break; + case 0x03 : + if (temp = *srcptr & 0x30) + *cptr |= temp >> 4; + if (temp = *srcptr & 0x0c) + *mptr |= temp >> 2; + if (temp = *srcptr & 0x03) + *yptr |= temp; + + bit = 0xc0; + cptr ++; + mptr ++; + yptr ++; + break; + } + break; + case CUPS_CSPACE_CMYK : + case CUPS_CSPACE_YMCK : + case CUPS_CSPACE_KCMY : + for (x = cups->width, cptr = dst, mptr = cptr + bandbytes, + yptr = mptr + bandbytes, kptr = yptr + bandbytes, + bit = 0xc0; + x > 0; + x --, srcptr ++) + switch (bit) + { + case 0xc0 : + if (temp = *srcptr & 0xc0) + *cptr |= temp; + if (temp = *srcptr & 0x30) + *mptr |= temp << 2; + if (temp = *srcptr & 0x0c) + *yptr |= temp << 4; + if (temp = *srcptr & 0x03) + *kptr |= temp << 6; + + bit = 0x30; + break; + case 0x30 : + if (temp = *srcptr & 0xc0) + *cptr |= temp >> 2; + if (temp = *srcptr & 0x30) + *mptr |= temp; + if (temp = *srcptr & 0x0c) + *yptr |= temp << 2; + if (temp = *srcptr & 0x03) + *kptr |= temp << 4; + + bit = 0x0c; + break; + case 0x0c : + if (temp = *srcptr & 0xc0) + *cptr |= temp >> 4; + if (temp = *srcptr & 0x30) + *mptr |= temp >> 2; + if (temp = *srcptr & 0x0c) + *yptr |= temp; + if (temp = *srcptr & 0x03) + *kptr |= temp << 2; + + bit = 0x03; + break; + case 0x03 : + if (temp = *srcptr & 0xc0) + *cptr |= temp >> 6; + if (temp = *srcptr & 0x30) + *mptr |= temp >> 4; + if (temp = *srcptr & 0x0c) + *yptr |= temp >> 2; + if (temp = *srcptr & 0x03) + *kptr |= temp; + + bit = 0xc0; + cptr ++; + mptr ++; + yptr ++; + kptr ++; + break; + } + break; + } + break; + + case 4 : + memset(dst, 0, cups->header.cupsBytesPerLine); + + switch (cups->header.cupsColorSpace) + { + case CUPS_CSPACE_RGB : + case CUPS_CSPACE_CMY : + case CUPS_CSPACE_YMC : + for (x = cups->width, cptr = dst, mptr = cptr + bandbytes, + yptr = mptr + bandbytes, bit = 0xf0; + x > 0; + x --, srcptr += 2) + switch (bit) + { + case 0xf0 : + if (temp = srcptr[0] & 0x0f) + *cptr |= temp << 4; + if (temp = srcptr[1] & 0xf0) + *mptr |= temp; + if (temp = srcptr[1] & 0x0f) + *yptr |= temp << 4; + + bit = 0x0f; + break; + case 0x0f : + if (temp = srcptr[0] & 0x0f) + *cptr |= temp; + if (temp = srcptr[1] & 0xf0) + *mptr |= temp >> 4; + if (temp = srcptr[1] & 0x0f) + *yptr |= temp; + + bit = 0xf0; + cptr ++; + mptr ++; + yptr ++; + kptr ++; + break; + } + break; + case CUPS_CSPACE_CMYK : + case CUPS_CSPACE_YMCK : + case CUPS_CSPACE_KCMY : + case CUPS_CSPACE_KCMYcm : + for (x = cups->width, cptr = dst, mptr = cptr + bandbytes, + yptr = mptr + bandbytes, kptr = yptr + bandbytes, + bit = 0xf0; + x > 0; + x --, srcptr += 2) + switch (bit) + { + case 0xf0 : + if (temp = srcptr[0] & 0xf0) + *cptr |= temp; + if (temp = srcptr[0] & 0x0f) + *mptr |= temp << 4; + if (temp = srcptr[1] & 0xf0) + *yptr |= temp; + if (temp = srcptr[1] & 0x0f) + *kptr |= temp << 4; + + bit = 0x0f; + break; + case 0x0f : + if (temp = srcptr[0] & 0xf0) + *cptr |= temp >> 4; + if (temp = srcptr[0] & 0x0f) + *mptr |= temp; + if (temp = srcptr[1] & 0xf0) + *yptr |= temp >> 4; + if (temp = srcptr[1] & 0x0f) + *kptr |= temp; + + bit = 0xf0; + cptr ++; + mptr ++; + yptr ++; + kptr ++; + break; + } + break; + } + break; + + case 8 : + switch (cups->header.cupsColorSpace) + { + case CUPS_CSPACE_RGB : + case CUPS_CSPACE_CMY : + case CUPS_CSPACE_YMC : + for (x = cups->width, cptr = dst, mptr = cptr + bandbytes, + yptr = mptr + bandbytes; + x > 0; + x --) + { + *cptr++ = *srcptr++; + *mptr++ = *srcptr++; + *yptr++ = *srcptr++; + } + break; + case CUPS_CSPACE_CMYK : + case CUPS_CSPACE_YMCK : + case CUPS_CSPACE_KCMY : + case CUPS_CSPACE_KCMYcm : + for (x = cups->width, cptr = dst, mptr = cptr + bandbytes, + yptr = mptr + bandbytes, kptr = yptr + bandbytes; + x > 0; + x --) + { + *cptr++ = *srcptr++; + *mptr++ = *srcptr++; + *yptr++ = *srcptr++; + *kptr++ = *srcptr++; + } + break; + } + break; + } + + /* + * Write the bitmap data to the raster stream... + */ + + cupsRasterWritePixels(cups->stream, dst, cups->header.cupsBytesPerLine); + } +} + + +/* + * 'cups_print_planar()' - Print a page of planar pixels. + */ + +static void +cups_print_planar(gx_device_printer *pdev, /* I - Printer device */ + unsigned char *src, /* I - Scanline buffer */ + unsigned char *dst, /* I - Bitmap buffer */ + int srcbytes) /* I - Number of bytes in src */ +{ + int x; /* Looping var */ + int y; /* Looping var */ + int z; /* Looping var */ + unsigned char srcbit; /* Current source bit */ + unsigned char dstbit; /* Current destination bit */ + unsigned char temp; /* Temporary variable */ + unsigned char *srcptr; /* Pointer to data */ + unsigned char *dstptr; /* Pointer to bitmap */ + + + /* + * Loop through the page bitmap and write planar pixels... We have + * to separate each chunked color as needed... + */ + + for (z = 0; z < pdev->color_info.num_components; z ++) + for (y = 0; y < cups->height; y ++) + { + /* + * Grab the scanline data... + */ + + if (gdev_prn_get_bits((gx_device_printer *)pdev, y, src, &srcptr) < 0) + { + fprintf(stderr, "ERROR: Unable to get scanline %d!\n", y); + gs_exit(1); + } + + /* + * Pull the individual color planes out of the pixels... + */ + + if (srcptr[0] == 0 && memcmp(srcptr, srcptr + 1, srcbytes - 1) == 0) + memset(dst, 0, cups->header.cupsBytesPerLine); + else + switch (cups->header.cupsBitsPerColor) + { + case 1 : + memset(dst, 0, cups->header.cupsBytesPerLine); + + switch (cups->header.cupsColorSpace) + { + case CUPS_CSPACE_RGB : + case CUPS_CSPACE_CMY : + case CUPS_CSPACE_YMC : + for (dstptr = dst, x = cups->width, srcbit = 64 >> z, + dstbit = 128; + x > 0; + x --) + { + if (*srcptr & srcbit) + *dstptr |= dstbit; + + if (srcbit >= 16) + srcbit >>= 4; + else + { + srcbit = 64 >> z; + srcptr ++; + } + + if (dstbit > 1) + dstbit >>= 1; + else + { + dstbit = 128; + dstptr ++; + } + } + break; + case CUPS_CSPACE_CMYK : + case CUPS_CSPACE_YMCK : + case CUPS_CSPACE_KCMY : + for (dstptr = dst, x = cups->width, srcbit = 128 >> z, + dstbit = 128; + x > 0; + x --) + { + if (*srcptr & srcbit) + *dstptr |= dstbit; + + if (srcbit >= 16) + srcbit >>= 4; + else + { + srcbit = 128 >> z; + srcptr ++; + } + + if (dstbit > 1) + dstbit >>= 1; + else + { + dstbit = 128; + dstptr ++; + } + } + break; + case CUPS_CSPACE_KCMYcm : + for (dstptr = dst, x = cups->width, srcbit = 32 >> z, + dstbit = 128; + x > 0; + x --, srcptr ++) + { + if (*srcptr & srcbit) + *dstptr |= dstbit; + + if (dstbit > 1) + dstbit >>= 1; + else + { + dstbit = 128; + dstptr ++; + } + } + break; + } + break; + + case 2 : + memset(dst, 0, cups->header.cupsBytesPerLine); + + switch (cups->header.cupsColorSpace) + { + case CUPS_CSPACE_RGB : + case CUPS_CSPACE_CMY : + case CUPS_CSPACE_YMC : + for (dstptr = dst, x = cups->width, srcbit = 48 >> (z * 2), + dstbit = 0xc0; + x > 0; + x --, srcptr ++) + { + if (temp = *srcptr & srcbit) + { + if (srcbit == dstbit) + *dstptr |= temp; + else + { + switch (srcbit) + { + case 0x30 : + temp >>= 4; + break; + case 0x0c : + temp >>= 2; + break; + } + + switch (dstbit) + { + case 0xc0 : + *dstptr |= temp << 6; + break; + case 0x30 : + *dstptr |= temp << 4; + break; + case 0x0c : + *dstptr |= temp << 2; + break; + case 0x03 : + *dstptr |= temp; + break; + } + } + } + + if (dstbit > 0x03) + dstbit >>= 2; + else + { + dstbit = 0xc0; + dstptr ++; + } + } + break; + case CUPS_CSPACE_CMYK : + case CUPS_CSPACE_YMCK : + case CUPS_CSPACE_KCMY : + case CUPS_CSPACE_KCMYcm : + for (dstptr = dst, x = cups->width, srcbit = 192 >> (z * 2), + dstbit = 0xc0; + x > 0; + x --, srcptr ++) + { + if (temp = *srcptr & srcbit) + { + if (srcbit == dstbit) + *dstptr |= temp; + else + { + switch (srcbit) + { + case 0xc0 : + temp >>= 6; + break; + case 0x30 : + temp >>= 4; + break; + case 0x0c : + temp >>= 2; + break; + } + + switch (dstbit) + { + case 0xc0 : + *dstptr |= temp << 6; + break; + case 0x30 : + *dstptr |= temp << 4; + break; + case 0x0c : + *dstptr |= temp << 2; + break; + case 0x03 : + *dstptr |= temp; + break; + } + } + } + + if (dstbit > 0x03) + dstbit >>= 2; + else + { + dstbit = 0xc0; + dstptr ++; + } + } + break; + } + break; + + case 4 : + memset(dst, 0, cups->header.cupsBytesPerLine); + + switch (cups->header.cupsColorSpace) + { + case CUPS_CSPACE_RGB : + case CUPS_CSPACE_CMY : + case CUPS_CSPACE_YMC : + if (z > 0) + srcptr ++; + + if (z == 1) + srcbit = 0xf0; + else + srcbit = 0x0f; + + for (dstptr = dst, x = cups->width, dstbit = 0xf0; + x > 0; + x --, srcptr += 2) + { + if (temp = *srcptr & srcbit) + { + if (srcbit == dstbit) + *dstptr |= temp; + else + { + if (srcbit == 0xf0) + temp >>= 4; + + if (dstbit == 0xf0) + *dstptr |= temp << 4; + else + *dstptr |= temp; + } + } + + if (dstbit == 0xf0) + dstbit = 0x0f; + else + { + dstbit = 0xf0; + dstptr ++; + } + } + break; + case CUPS_CSPACE_CMYK : + case CUPS_CSPACE_YMCK : + case CUPS_CSPACE_KCMY : + case CUPS_CSPACE_KCMYcm : + if (z > 1) + srcptr ++; + + if (z & 1) + srcbit = 0x0f; + else + srcbit = 0xf0; + + for (dstptr = dst, x = cups->width, dstbit = 0xf0; + x > 0; + x --, srcptr += 2) + { + if (temp = *srcptr & srcbit) + { + if (srcbit == dstbit) + *dstptr |= temp; + else + { + if (srcbit == 0xf0) + temp >>= 4; + + if (dstbit == 0xf0) + *dstptr |= temp << 4; + else + *dstptr |= temp; + } + } + + if (dstbit == 0xf0) + dstbit = 0x0f; + else + { + dstbit = 0xf0; + dstptr ++; + } + } + break; + } + break; + + case 8 : + for (srcptr += z, dstptr = dst, x = cups->header.cupsBytesPerLine; + x > 0; + srcptr += pdev->color_info.num_components, x --) + *dstptr++ = *srcptr; + break; + } + + /* + * Write the bitmap data to the raster stream... + */ + + cupsRasterWritePixels(cups->stream, dst, cups->header.cupsBytesPerLine); + } +} + + +/* + * End of "$Id$". + */ diff --git a/pstoraster/gdevddrw.c b/pstoraster/gdevddrw.c new file mode 100644 index 0000000000..85536350aa --- /dev/null +++ b/pstoraster/gdevddrw.c @@ -0,0 +1,470 @@ +/* Copyright (C) 1989, 1995, 1996 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to + anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer to + the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given to + you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises is not affiliated with the Free Software Foundation or + the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, + does not depend on any other GNU software. +*/ + +/* gdevddrw.c */ +/* Default polygon and image drawing device procedures */ +#include "math_.h" +#include "gx.h" +#include "gpcheck.h" +#include "gserrors.h" +#include "gxfixed.h" +#include "gxmatrix.h" +#include "gxdcolor.h" +#include "gxdevice.h" + +/* ---------------- Polygon and line drawing ---------------- */ + +/* Define the 'remainder' analogue of fixed_mult_quo. */ +private fixed +fixed_mult_rem(fixed a, fixed b, fixed c) +{ double prod = (double)a * b; + return (fixed)(prod - floor(prod / c) * c); +} + +/* + * Fill a trapezoid. Requires: + * {left,right}->start.y <= ybot <= ytop <= {left,right}->end.y. + * Lines where left.x >= right.x will not be drawn. Thanks to Paul Haeberli + * for an early floating point version of this algorithm. + */ +typedef struct trap_line_s { + int di; fixed df; /* dx/dy ratio = di + df/h */ + fixed ldi, ldf; /* increment per scan line = ldi + ldf/h */ + fixed x, xf; /* current value */ + fixed h; +} trap_line; +int +gx_default_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 fixed ymin = fixed_pixround(ybot) + fixed_half; + const fixed ymax = fixed_pixround(ytop); + if ( ymin >= ymax ) return 0; /* no scan lines to sample */ + { int iy = fixed2int_var(ymin); + const int iy1 = fixed2int_var(ymax); + trap_line l, r; + int rxl, rxr, ry; + const fixed + x0l = left->start.x, x1l = left->end.x, + x0r = right->start.x, x1r = right->end.x, + dxl = x1l - x0l, dxr = x1r - x0r; + const fixed /* partial pixel offset to first line to sample */ + ysl = ymin - left->start.y, + ysr = ymin - right->start.y; + fixed fxl; + bool fill_direct = color_writes_pure(pdevc, lop); + gx_color_index cindex; + dev_proc_fill_rectangle((*fill_rect)); + int max_rect_height = 1; /* max height to do fill as rectangle */ + int code; + + if_debug2('z', "[z]y=[%d,%d]\n", iy, iy1); + + if ( fill_direct ) + cindex = pdevc->colors.pure, + fill_rect = dev_proc(dev, fill_rectangle); + l.h = left->end.y - left->start.y; + r.h = right->end.y - right->start.y; + l.x = x0l + (fixed_half - fixed_epsilon); + r.x = x0r + (fixed_half - fixed_epsilon); + ry = iy; + +#define fill_trap_rect(x,y,w,h)\ + (fill_direct ?\ + (swap_axes ? (*fill_rect)(dev, y, x, h, w, cindex) :\ + (*fill_rect)(dev, x, y, w, h, cindex)) :\ + swap_axes ? gx_fill_rectangle_device_rop(y, x, h, w, pdevc, dev, lop) :\ + gx_fill_rectangle_device_rop(x, y, w, h, pdevc, dev, lop)) + + /* Compute the dx/dy ratios. */ + /* dx# = dx#i + (dx#f / h#). */ +#define compute_dx(tl, d, ys)\ + if ( d >= 0 )\ + { if ( d < tl.h ) tl.di = 0, tl.df = d;\ + else tl.di = (int)(d / tl.h), tl.df = d - tl.di * tl.h,\ + tl.x += ys * tl.di;\ + }\ + else\ + { if ( (tl.df = d + tl.h) >= 0 /* d >= -tl.h */ ) tl.di = -1, tl.x -= ys;\ + else tl.di = (int)-((tl.h - 1 - d) / tl.h), tl.df = d - tl.di * tl.h,\ + tl.x += ys * tl.di;\ + } + + /* Compute the x offsets at the first scan line to sample. */ + /* We need to be careful in computing ys# * dx#f {/,%} h# */ + /* because the multiplication may overflow. We know that */ + /* all the quantities involved are non-negative, and that */ + /* ys# is usually than 1 (as a fixed, of course); this gives us */ + /* a cheap conservative check for overflow in the multiplication. */ +#define ymult_limit (max_fixed / fixed_1) +#define ymult_quo(ys, tl)\ + (ys < fixed_1 && tl.df < ymult_limit ? ys * tl.df / tl.h :\ + fixed_mult_quo(ys, tl.df, tl.h)) + + /* + * It's worth checking for dxl == dxr, since this is the case + * for parallelograms (including stroked lines). + * Also check for left or right vertical edges. + */ + if ( fixed_floor(l.x) == fixed_pixround(x1l) ) + { /* Left edge is vertical, we don't need to increment. */ + l.di = 0, l.df = 0; + fxl = 0; + } + else + { compute_dx(l, dxl, ysl); + fxl = ymult_quo(ysl, l); + l.x += fxl; + } + if ( fixed_floor(r.x) == fixed_pixround(x1r) ) + { /* Right edge is vertical. If both are vertical, */ + /* we have a rectangle. */ + if ( l.di == 0 && l.df == 0 ) + max_rect_height = max_int; + else + r.di = 0, r.df = 0; + } + /* The test for fxl != 0 is required because the right edge */ + /* might cross some pixel centers even if the left edge doesn't. */ + else if ( dxr == dxl && fxl != 0 ) + { if ( l.di == 0 ) + r.di = 0, r.df = l.df; + else /* too hard to do adjustments right */ + compute_dx(r, dxr, ysr); + if ( ysr == ysl && r.h == l.h ) + r.x += fxl; + else + r.x += ymult_quo(ysr, r); + } + else + { compute_dx(r, dxr, ysr); + r.x += ymult_quo(ysr, r); + } + rxl = fixed2int_var(l.x); + rxr = fixed2int_var(r.x); + + /* + * Take a shortcut if we're only sampling a single scan line, + * or if we have a rectangle. + */ + if ( iy1 - iy <= max_rect_height ) + { iy = iy1; + if_debug2('z', "[z]rectangle, x=[%d,%d]\n", rxl, rxr); + goto last; + } + + /* Compute one line's worth of dx/dy. */ + /* dx# * fixed_1 = ld#i + (ld#f / h#). */ +#define compute_ldx(tl, ys)\ + if ( tl.df < ymult_limit )\ + { if ( tl.df == 0 ) /* vertical edge, worth checking for */\ + tl.ldi = int2fixed(tl.di),\ + tl.ldf = 0,\ + tl.xf = -tl.h;\ + else\ + tl.ldi = int2fixed(tl.di) + int2fixed(tl.df) / tl.h,\ + tl.ldf = int2fixed(tl.df) % tl.h,\ + tl.xf = (ys < fixed_1 ? ys * tl.df % tl.h :\ + fixed_mult_rem(ys, tl.df, tl.h)) - tl.h;\ + }\ + else\ + tl.ldi = int2fixed(tl.di) + fixed_mult_quo(fixed_1, tl.df, tl.h),\ + tl.ldf = fixed_mult_rem(fixed_1, tl.df, tl.h),\ + tl.xf = fixed_mult_rem(ys, tl.df, tl.h) - tl.h + compute_ldx(l, ysl); + if ( dxr == dxl && ysr == ysl && r.h == l.h ) + r.ldi = l.ldi, r.ldf = l.ldf, r.xf = l.xf; + else + { compute_ldx(r, ysr); + } +#undef compute_ldx + + while ( ++iy != iy1 ) + { int ixl, ixr; +#define step_line(tl)\ + tl.x += tl.ldi;\ + if ( (tl.xf += tl.ldf) >= 0 ) tl.xf -= tl.h, tl.x++; + step_line(l); + step_line(r); +#undef step_line + ixl = fixed2int_var(l.x); + ixr = fixed2int_var(r.x); + if ( ixl != rxl || ixr != rxr ) + { code = fill_trap_rect(rxl, ry, rxr - rxl, iy - ry); + if ( code < 0 ) goto xit; + rxl = ixl, rxr = ixr, ry = iy; + } + } +last: code = fill_trap_rect(rxl, ry, rxr - rxl, iy - ry); +xit: if ( code < 0 && fill_direct ) + return_error(code); + return_if_interrupt(); + return code; + } +} + +/* Fill a parallelogram whose points are p, p+a, p+b, and p+a+b. */ +/* We should swap axes to get best accuracy, but we don't. */ +/* We must be very careful to follow the center-of-pixel rule in all cases. */ +int +gx_default_fill_parallelogram(gx_device *dev, + fixed px, fixed py, fixed ax, fixed ay, fixed bx, fixed by, + const gx_device_color *pdevc, gs_logical_operation_t lop) +{ fixed t; + fixed qx, qy, ym; + dev_proc_fill_trapezoid((*fill_trapezoid)); + gs_fixed_edge left, right; + int code; + + /* Ensure ay >= 0, by >= 0. */ + if ( ay < 0 ) + px += ax, py += ay, ax = -ax, ay = -ay; + if ( by < 0 ) + px += bx, py += by, bx = -bx, by = -by; + qx = px + ax + bx; + /* Make a special fast check for rectangles. */ + if ( (ay | bx) == 0 || (by | ax) == 0 ) + { /* If a point falls exactly on the middle of a pixel, */ + /* we must round it down, not up. */ + int rx = fixed2int_pixround(px); + int ry = fixed2int_pixround(py); + /* Exactly one of (ax,bx) and one of (ay,by) is non-zero. */ + int w = fixed2int_pixround(qx) - rx; + if ( w < 0 ) rx += w, w = -w; + return gx_fill_rectangle_device_rop(rx, ry, w, + fixed2int_pixround(py + ay + by) - ry, + pdevc, dev, lop); + } + /* Not a rectangle. Ensure ax <= bx. */ +#define swap(r, s) (t = r, r = s, s = t) + if ( ax > bx ) + swap(ax, bx), swap(ay, by); + fill_trapezoid = dev_proc(dev, fill_trapezoid); + qy = py + ay + by; + left.start.x = right.start.x = px; + left.start.y = right.start.y = py; + left.end.x = px + ax; + left.end.y = py + ay; + right.end.x = px + bx; + right.end.y = py + by; +#define rounded_same(p1, p2)\ + (fixed_pixround(p1) == fixed_pixround(p2)) + if ( ay < by ) + { if ( !rounded_same(py, left.end.y) ) + { code = (*fill_trapezoid)(dev, &left, &right, py, left.end.y, + false, pdevc, lop); + if ( code < 0 ) + return code; + } + left.start = left.end; + left.end.x = qx, left.end.y = qy; + ym = right.end.y; + if ( !rounded_same(left.start.y, ym) ) + { code = (*fill_trapezoid)(dev, &left, &right, left.start.y, ym, + false, pdevc, lop); + if ( code < 0 ) + return code; + } + right.start = right.end; + right.end.x = qx, right.end.y = qy; + } + else + { if ( !rounded_same(py, right.end.y) ) + { code = (*fill_trapezoid)(dev, &left, &right, py, right.end.y, + false, pdevc, lop); + if ( code < 0 ) + return code; + } + right.start = right.end; + right.end.x = qx, right.end.y = qy; + ym = left.end.y; + if ( !rounded_same(right.start.y, ym) ) + { code = (*fill_trapezoid)(dev, &left, &right, right.start.y, ym, + false, pdevc, lop); + if ( code < 0 ) + return code; + } + left.start = left.end; + left.end.x = qx, left.end.y = 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 +} + +/* Fill a triangle whose points are p, p+a, and p+b. */ +/* We should swap axes to get best accuracy, but we don't. */ +int +gx_default_fill_triangle(gx_device *dev, + fixed px, fixed py, fixed ax, fixed ay, fixed bx, fixed by, + const gx_device_color *pdevc, gs_logical_operation_t lop) +{ fixed t; + fixed ym; + dev_proc_fill_trapezoid((*fill_trapezoid)) = + dev_proc(dev, fill_trapezoid); + gs_fixed_edge left, right; + int code; + + /* Ensure ay >= 0, by >= 0. */ + if ( ay < 0 ) + px += ax, py += ay, bx -= ax, by -= ay, ax = -ax, ay = -ay; + if ( by < 0 ) + px += bx, py += by, ax -= bx, ay -= by, bx = -bx, by = -by; + /* Ensure ax <= bx. */ +#define swap(r, s) (t = r, r = s, s = t) + if ( ax > bx ) + swap(ax, bx), swap(ay, by); +#undef swap + left.start.y = right.start.y = py; + /* Make a special check for a flat bottom or top, */ + /* which we can handle with a single call on fill_trapezoid. */ + if ( ay < by ) + { right.end.x = px + bx, right.end.y = py + by; + if ( ay == 0 ) + { if ( ax < 0 ) + left.start.x = px + ax, right.start.x = px; + else + left.start.x = px, right.start.x = px + ax; + left.end.x = right.end.x, left.end.y = right.end.y; + ym = py; + } + else + { left.start.x = right.start.x = px; + left.end.x = px + ax, left.end.y = py + ay; + code = (*fill_trapezoid)(dev, &left, &right, py, left.end.y, + false, pdevc, lop); + if ( code < 0 ) + return code; + left.start = left.end; + left.end = right.end; + ym = left.start.x; + } + } + else if ( by < ay ) + { left.end.x = px + ax, left.end.y = py + by; + if ( by == 0 ) + { if ( bx < 0 ) + left.start.x = px + bx, right.start.x = px; + else + left.start.x = px, right.start.x = px + bx; + right.end.x = left.end.x, right.end.y = left.end.y; + ym = py; + } + else + { left.start.x = right.start.x = px; + right.end.x = px + bx, right.end.y = py + by; + code = (*fill_trapezoid)(dev, &left, &right, py, right.end.y, + false, pdevc, lop); + if ( code < 0 ) + return code; + right.start = right.end; + right.end = left.end; + ym = right.start.x; + } + } + else /* ay == by */ + { left.start.x = right.start.x = px; + left.end.x = px + ax, left.end.y = py + ay; + right.end.x = px + bx, right.end.y = py + by; + ym = py; + } + return (*fill_trapezoid)(dev, &left, &right, ym, right.end.y, + false, pdevc, lop); +} + +/* Draw a one-pixel-wide line. */ +int +gx_default_draw_thin_line(gx_device *dev, + fixed fx0, fixed fy0, fixed fx1, fixed fy1, + const gx_device_color *pdevc, gs_logical_operation_t lop) +{ int ix = fixed2int_var(fx0); + int iy = fixed2int_var(fy0); + int itox = fixed2int_var(fx1); + int itoy = fixed2int_var(fy1); + + return_if_interrupt(); + if ( itoy == iy ) /* horizontal line */ + { return (ix <= itox ? + gx_fill_rectangle_device_rop(ix, iy, itox - ix + 1, 1, + pdevc, dev, lop) : + gx_fill_rectangle_device_rop(itox, iy, ix - itox + 1, 1, + pdevc, dev, lop) + ); + } + if ( itox == ix ) /* vertical line */ + { return (iy <= itoy ? + gx_fill_rectangle_device_rop(ix, iy, 1, itoy - iy + 1, + pdevc, dev, lop) : + gx_fill_rectangle_device_rop(ix, itoy, 1, iy - itoy + 1, + pdevc, dev, lop) + ); + } + if ( color_writes_pure(pdevc, lop) && + (*dev_proc(dev, draw_line))(dev, ix, iy, itox, itoy, + pdevc->colors.pure) >= 0 + ) + return 0; + { fixed h = fy1 - fy0; + fixed w = fx1 - fx0; + fixed tf; + 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), + h = -h; + right.start.x = (left.start.x = fx0 - fixed_half) + fixed_1; + right.end.x = (left.end.x = fx1 - fixed_half) + fixed_1; + left.start.y = right.start.y = fy0; + left.end.y = right.end.y = fy1; + swap_axes = false; + } + else + { if ( w < 0 ) + fswap(fx0, fx1), fswap(fy0, fy1), + w = -w; + right.start.x = (left.start.x = fy0 - fixed_half) + fixed_1; + right.end.x = (left.end.x = fy1 - fixed_half) + fixed_1; + left.start.y = right.start.y = fx0; + left.end.y = right.end.y = fx1; + swap_axes = true; + } + return (*dev_proc(dev, fill_trapezoid))(dev, &left, &right, + left.start.y, left.end.y, + swap_axes, pdevc, lop); +#undef fswap + } +} + +/* Stub out the obsolete procedure. */ +int +gx_default_draw_line(gx_device *dev, + int x0, int y0, int x1, int y1, gx_color_index color) +{ return -1; +} diff --git a/pstoraster/gdevdflt.c b/pstoraster/gdevdflt.c new file mode 100644 index 0000000000..27bcc9a3b6 --- /dev/null +++ b/pstoraster/gdevdflt.c @@ -0,0 +1,878 @@ +/* Copyright (C) 1995, 1996 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to + anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer to + the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given to + you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises is not affiliated with the Free Software Foundation or + the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, + does not depend on any other GNU software. +*/ + +/* gdevdflt.c */ +/* Default device implementation */ +#include "gx.h" +#include "gpcheck.h" +#include "gserrors.h" +#include "gxdevice.h" +#include "gxdevmem.h" +#include "gxcpath.h" + +/* ---------------- Default device procedures ---------------- */ + +/* Define the default implementations of RasterOp procedures. */ +/* If the RasterOp option is linked in, it initializes these */ +/* to different values. */ +dev_proc_copy_rop((*gx_default_copy_rop_proc)) = gx_no_copy_rop; +dev_proc_copy_rop((*gx_forward_copy_rop_proc)) = gx_no_copy_rop; +dev_proc_strip_copy_rop((*gx_default_strip_copy_rop_proc)) = gx_no_strip_copy_rop; +dev_proc_strip_copy_rop((*gx_forward_strip_copy_rop_proc)) = gx_no_strip_copy_rop; + +/* Fill in NULL procedures in a device procedure record. */ +void +gx_device_fill_in_procs(register gx_device *dev) +{ gx_device_set_procs(dev); + fill_dev_proc(dev, open_device, gx_default_open_device); + fill_dev_proc(dev, get_initial_matrix, gx_default_get_initial_matrix); + fill_dev_proc(dev, sync_output, gx_default_sync_output); + fill_dev_proc(dev, output_page, gx_default_output_page); + fill_dev_proc(dev, close_device, gx_default_close_device); + fill_dev_proc(dev, map_rgb_color, gx_default_map_rgb_color); + fill_dev_proc(dev, map_color_rgb, gx_default_map_color_rgb); + /* NOT fill_rectangle */ + fill_dev_proc(dev, tile_rectangle, gx_default_tile_rectangle); + fill_dev_proc(dev, copy_mono, gx_default_copy_mono); + fill_dev_proc(dev, copy_color, gx_default_copy_color); + fill_dev_proc(dev, draw_line, gx_default_draw_line); + fill_dev_proc(dev, get_bits, gx_default_get_bits); + fill_dev_proc(dev, get_params, gx_default_get_params); + fill_dev_proc(dev, put_params, gx_default_put_params); + fill_dev_proc(dev, map_cmyk_color, gx_default_map_cmyk_color); + fill_dev_proc(dev, get_xfont_procs, gx_default_get_xfont_procs); + fill_dev_proc(dev, get_xfont_device, gx_default_get_xfont_device); + fill_dev_proc(dev, map_rgb_alpha_color, gx_default_map_rgb_alpha_color); + fill_dev_proc(dev, get_page_device, gx_default_get_page_device); + fill_dev_proc(dev, get_alpha_bits, gx_default_get_alpha_bits); + fill_dev_proc(dev, copy_alpha, gx_default_copy_alpha); + fill_dev_proc(dev, get_band, gx_default_get_band); + fill_dev_proc(dev, copy_rop, gx_default_copy_rop_proc); + fill_dev_proc(dev, fill_path, gx_default_fill_path); + fill_dev_proc(dev, stroke_path, gx_default_stroke_path); + fill_dev_proc(dev, fill_mask, gx_default_fill_mask); + fill_dev_proc(dev, fill_trapezoid, gx_default_fill_trapezoid); + fill_dev_proc(dev, fill_parallelogram, gx_default_fill_parallelogram); + fill_dev_proc(dev, fill_triangle, gx_default_fill_triangle); + fill_dev_proc(dev, draw_thin_line, gx_default_draw_thin_line); + fill_dev_proc(dev, begin_image, gx_default_begin_image); + fill_dev_proc(dev, image_data, gx_default_image_data); + fill_dev_proc(dev, end_image, gx_default_end_image); + fill_dev_proc(dev, strip_tile_rectangle, gx_default_strip_tile_rectangle); + fill_dev_proc(dev, strip_copy_rop, gx_default_strip_copy_rop_proc); +} + +int +gx_default_open_device(gx_device *dev) +{ return 0; +} + +/* Get the initial matrix for a device with inverted Y. */ +/* This includes essentially all printers and displays. */ +void +gx_default_get_initial_matrix(gx_device *dev, register gs_matrix *pmat) +{ pmat->xx = dev->HWResolution[0] / 72.0; /* x_pixels_per_inch */ + pmat->xy = 0; + pmat->yx = 0; + pmat->yy = dev->HWResolution[1] / -72.0; /* y_pixels_per_inch */ + /****** tx/y is WRONG for devices with ******/ + /****** arbitrary initial matrix ******/ + pmat->tx = 0; + pmat->ty = dev->height; +} +/* Get the initial matrix for a device with upright Y. */ +/* This includes just a few printers and window systems. */ +void +gx_upright_get_initial_matrix(gx_device *dev, register gs_matrix *pmat) +{ pmat->xx = dev->HWResolution[0] / 72.0; /* x_pixels_per_inch */ + pmat->xy = 0; + pmat->yx = 0; + pmat->yy = dev->HWResolution[1] / 72.0; /* y_pixels_per_inch */ + /****** tx/y is WRONG for devices with ******/ + /****** arbitrary initial matrix ******/ + pmat->tx = 0; + pmat->ty = 0; +} + +int +gx_default_sync_output(gx_device *dev) +{ return 0; +} + +int +gx_default_output_page(gx_device *dev, int num_copies, int flush) +{ return (*dev_proc(dev, sync_output))(dev); +} + +int +gx_default_close_device(gx_device *dev) +{ return 0; +} + +/* By default, implement tile_rectangle using strip_tile_rectangle. */ +int +gx_default_tile_rectangle(gx_device *dev, const gx_tile_bitmap *tile, + int x, int y, int w, int h, gx_color_index color0, gx_color_index color1, + int px, int py) +{ gx_strip_bitmap tiles; + *(gx_tile_bitmap *)&tiles = *tile; + tiles.shift = tiles.rep_shift = 0; + return (*dev_proc(dev, strip_tile_rectangle)) + (dev, &tiles, x, y, w, h, color0, color1, px, py); +} + +/* Implement copy_mono by filling lots of small rectangles. */ +/* This is very inefficient, but it works as a default. */ +int +gx_default_copy_mono(gx_device *dev, const byte *data, + int dx, int raster, gx_bitmap_id id, int x, int y, int w, int h, + gx_color_index zero, gx_color_index one) +{ byte invert; + gx_color_index color; + dev_proc_fill_rectangle((*fill)); + const byte *row; + int iy; + + fit_copy(dev, data, dx, raster, id, x, y, w, h); + fill = dev_proc(dev, fill_rectangle); + if ( one != gx_no_color_index ) + { invert = 0; + color = one; + if ( zero != gx_no_color_index ) + { int code = (*fill)(dev, x, y, w, h, zero); + if ( code < 0 ) + return code; + } + } + else + { invert = 0xff; + color = zero; + } + for ( row = data, iy = 0; iy < h; row += raster, iy++ ) + { int ix; + for ( ix = 0; ix < w; ) + { int i0; +#define row_bit(i) ((row[(i) >> 3] ^ invert) & (0x80 >> ((i) & 7))) + while ( ix < w && row_bit(ix + dx) == 0 ) + ix++; + for ( i0 = ix; ix < w && row_bit(ix + dx) != 0; ) + ix++; + if ( ix > i0 ) + { int code = (*fill)(dev, i0 + x, iy + y, ix - i0, 1, color); + if ( code < 0 ) + return code; + } +#undef row_bit + } + } + return 0; +} + +/* Implement copy_color by filling lots of small rectangles. */ +/* This is very inefficient, but it works as a default. */ +int +gx_default_copy_color(gx_device *dev, const byte *data, + int dx, int raster, gx_bitmap_id id, + int x, int y, int w, int h) +{ int depth = dev->color_info.depth; + byte mask; + dev_proc_fill_rectangle((*fill)); + const byte *row; + int iy; + + if ( depth == 1 ) + return (*dev_proc(dev, copy_mono))(dev, data, dx, raster, id, + x, y, w, h, + (gx_color_index)0, (gx_color_index)1); + fit_copy(dev, data, dx, raster, id, x, y, w, h); + fill = dev_proc(dev, fill_rectangle); + mask = (byte)((1 << depth) - 1); + for ( row = data, iy = 0; iy < h; row += raster, ++iy ) + { int ix; + gx_color_index c0 = gx_no_color_index; + const byte *ptr = row + ((dx * depth) >> 3); + int i0; + + for ( i0 = ix = 0; ix < w; ++ix ) + { gx_color_index color; + + if ( depth >= 8 ) + { color = *ptr++; + switch ( depth ) + { + case 32: color = (color << 8) + *ptr++; + case 24: color = (color << 8) + *ptr++; + case 16: color = (color << 8) + *ptr++; + } + } + else + { uint dbit = (-(ix + dx + 1) * depth) & 7; + color = (*ptr >> dbit) & mask; + if ( dbit == 0 ) + ptr++; + } + if ( color != c0 ) + { if ( ix > i0 ) + { int code = (*fill) + (dev, i0 + x, iy + y, ix - i0, 1, c0); + if ( code < 0 ) + return code; + } + c0 = color; + i0 = ix; + } + } + if ( ix > i0 ) + { int code = (*fill)(dev, i0 + x, iy + y, ix - i0, 1, c0); + if ( code < 0 ) + return code; + } + } + return 0; +} + +int +gx_default_get_bits(gx_device *dev, int y, byte *data, byte **actual_data) +{ return_error(gs_error_unknownerror); +} + +gx_xfont_procs * +gx_default_get_xfont_procs(gx_device *dev) +{ return NULL; +} + +gx_device * +gx_default_get_xfont_device(gx_device *dev) +{ return dev; +} + +gx_device * +gx_default_get_page_device(gx_device *dev) +{ return NULL; +} +gx_device * +gx_page_device_get_page_device(gx_device *dev) +{ return dev; +} + +int +gx_default_get_alpha_bits(gx_device *dev, graphics_object_type type) +{ return 1; +} + +int +gx_no_copy_alpha(gx_device *dev, const byte *data, int data_x, + int raster, gx_bitmap_id id, int x, int y, int width, int height, + gx_color_index color, int depth) +{ return_error(gs_error_unknownerror); +} + +int +gx_default_copy_alpha(gx_device *dev, const byte *data, int data_x, + int raster, gx_bitmap_id id, int x, int y, int width, int height, + gx_color_index color, int depth) +{ /* This might be called with depth = 1.... */ + if ( depth == 1 ) + return (*dev_proc(dev, copy_mono))(dev, data, data_x, raster, id, + x, y, width, height, + gx_no_color_index, color); + /* + * Simulate alpha by weighted averaging of RGB values. + * This is very slow, but functionally correct. + */ + { const byte *row; + gs_memory_t *mem = &gs_memory_default; /* dev might not have one */ + int bpp = dev->color_info.depth; + uint in_size = gx_device_raster(dev, false); + byte *lin; + uint out_size; + byte *lout; + int code = 0; + gx_color_value color_rgb[3]; + int ry; + + fit_copy(dev, data, data_x, raster, id, x, y, width, height); + row = data; + out_size = bitmap_raster(width * bpp); + lin = gs_alloc_bytes(mem, in_size, "copy_alpha(lin)"); + lout = gs_alloc_bytes(mem, out_size, "copy_alpha(lout)"); + if ( lin == 0 || lout == 0 ) + { code = gs_note_error(gs_error_VMerror); + goto out; + } + (*dev_proc(dev, map_color_rgb))(dev, color, color_rgb); + for ( ry = y; ry < y + height; row += raster, ++ry ) + { byte *line; + int sx, rx; + declare_line_accum(lout, bpp, x); + + code = (*dev_proc(dev, get_bits))(dev, ry, lin, &line); + if ( code < 0 ) + break; + for ( sx = data_x, rx = x; sx < data_x + width; ++sx, ++rx ) + { gx_color_index previous = gx_no_color_index; + gx_color_index composite; + int alpha2, alpha; + + if ( depth == 2 ) /* map 0 - 3 to 0 - 15 */ + alpha = ((row[sx >> 2] >> ((3 - (sx & 3)) << 1)) & 3) * 5; + else + alpha2 = row[sx >> 1], + alpha = (sx & 1 ? alpha2 & 0xf : alpha2 >> 4); +blend: if ( alpha == 15 ) + { /* Just write the new color. */ + composite = color; + } + else + { if ( previous == gx_no_color_index ) + { /* Extract the old color. */ + if ( bpp < 8 ) + { const uint bit = rx * bpp; + const byte *src = line + (bit >> 3); + previous = + (*src >> (8 - (bit + bpp))) & + ((1 << bpp) - 1); + } + else + { const byte *src = line + (rx * (bpp >> 3)); + previous = 0; + switch ( bpp >> 3 ) + { + case 4: + previous += (gx_color_index)*src++ << 24; + case 3: + previous += (gx_color_index)*src++ << 16; + case 2: + previous += (gx_color_index)*src++ << 8; + case 1: + previous += *src++; + } + } + } + if ( alpha == 0 ) + { /* Just write the old color. */ + composite = previous; + } + else + { /* Blend RGB values. */ + gx_color_value rgb[3]; + + (*dev_proc(dev, map_color_rgb))(dev, previous, rgb); +#if arch_ints_are_short +# define b_int long +#else +# define b_int int +#endif +#define make_shade(old, clr, alpha, amax) \ + (old) + (((b_int)(clr) - (b_int)(old)) * (alpha) / (amax)) + rgb[0] = make_shade(rgb[0], color_rgb[0], alpha, 15); + rgb[1] = make_shade(rgb[1], color_rgb[1], alpha, 15); + rgb[2] = make_shade(rgb[2], color_rgb[2], alpha, 15); +#undef b_int +#undef make_shade + composite = + (*dev_proc(dev, map_rgb_color))(dev, rgb[0], + rgb[1], rgb[2]); + if ( composite == gx_no_color_index ) + { /* The device can't represent this color. */ + /* Move the alpha value towards 0 or 1. */ + if ( alpha == 7 ) /* move 1/2 towards 1 */ + ++alpha; + alpha = (alpha & 8) | (alpha >> 1); + goto blend; + } + } + } + line_accum(composite, bpp); + } + line_accum_copy(dev, lout, bpp, x, rx, raster, ry); + } +out: gs_free_object(mem, lout, "copy_alpha(lout)"); + gs_free_object(mem, lin, "copy_alpha(lin)"); + return code; + } +} + +int +gx_default_get_band(gx_device *dev, int y, int *band_start) +{ return 0; +} + +int +gx_no_copy_rop(gx_device *dev, + const byte *sdata, int sourcex, uint sraster, gx_bitmap_id id, + const gx_color_index *scolors, + const gx_tile_bitmap *texture, const gx_color_index *tcolors, + int x, int y, int width, int height, + int phase_x, int phase_y, gs_logical_operation_t lop) +{ return_error(gs_error_unknownerror); /* not implemented */ +} +int +gx_default_copy_rop(gx_device *dev, + const byte *sdata, int sourcex, uint sraster, gx_bitmap_id id, + const gx_color_index *scolors, + const gx_tile_bitmap *texture, const gx_color_index *tcolors, + int x, int y, int width, int height, + int phase_x, int phase_y, gs_logical_operation_t lop) +{ return (*gx_default_copy_rop_proc) + (dev, sdata, sourcex, sraster, id, scolors, texture, tcolors, + x, y, width, height, phase_x, phase_y, lop); +} + +int +gx_default_fill_mask(gx_device *orig_dev, + const byte *data, int dx, int raster, gx_bitmap_id id, + int x, int y, int w, int h, + const gx_drawing_color *pdcolor, int depth, + gs_logical_operation_t lop, const gx_clip_path *pcpath) +{ gx_device *dev; + gx_device_clip cdev; + gx_color_index colors[2]; + gx_strip_bitmap *tile; + + if ( gx_dc_is_pure(pdcolor) ) + { tile = 0; + colors[0] = gx_no_color_index; + colors[1] = gx_dc_pure_color(pdcolor); + } + else if ( gx_dc_is_binary_halftone(pdcolor) ) + { tile = gx_dc_binary_tile(pdcolor); + colors[0] = gx_dc_binary_color0(pdcolor); + colors[1] = gx_dc_binary_color1(pdcolor); + } + else + return_error(gs_error_unknownerror); /* not implemented */ + if ( pcpath != 0 ) + { gx_make_clip_path_device(&cdev, pcpath); + cdev.target = orig_dev; + dev = (gx_device *)&cdev; + (*dev_proc(dev, open_device))(dev); + } + else + dev = orig_dev; + if ( depth > 1 ) + { /****** CAN'T DO ROP OR HALFTONE WITH ALPHA ******/ + return (*dev_proc(dev, copy_alpha)) + (dev, data, dx, raster, id, x, y, w, h, colors[1], depth); + } + if ( lop != lop_default ) + { gx_color_index scolors[2]; + + scolors[0] = 1; + scolors[1] = 0; + return (*dev_proc(dev, strip_copy_rop)) + (dev, data, dx, raster, id, scolors, tile, colors, + x, y, w, h, + gx_dc_phase(pdcolor).x, gx_dc_phase(pdcolor).y, lop); + } + if ( tile == 0 ) + { return (*dev_proc(dev, copy_mono)) + (dev, data, dx, raster, id, x, y, w, h, + gx_no_color_index, colors[1]); + } + /* + * Use the same approach as the default copy_mono (above). We + * should really clip to the intersection of the bounding boxes of + * the device and the clipping path, but it's too much work. + */ + fit_copy(orig_dev, data, dx, raster, id, x, y, w, h); + { dev_proc_strip_tile_rectangle((*tile_proc)) = + dev_proc(dev, strip_tile_rectangle); + const byte *row; + int iy; + + for ( row = data, iy = 0; iy < h; row += raster, iy++ ) + { int ix; + for ( ix = 0; ix < w; ) + { int i0; +#define row_bit(i) (row[(i) >> 3] & (0x80 >> ((i) & 7))) + while ( ix < w && row_bit(ix + dx) == 0 ) + ix++; + for ( i0 = ix; ix < w && row_bit(ix + dx) != 0; ) + ix++; + if ( ix > i0 ) + { int code = (*tile_proc) + (dev, tile, i0 + x, iy + y, ix - i0, 1, + colors[0], colors[1], + gx_dc_phase(pdcolor).x, gx_dc_phase(pdcolor).y); + if ( code < 0 ) + return code; + } +#undef row_bit + } + } + } + return 0; +} + +/* Default implementation of strip_tile_rectangle */ +int +gx_default_strip_tile_rectangle(gx_device *dev, const gx_strip_bitmap *tiles, + int x, int y, int w, int h, gx_color_index color0, gx_color_index color1, + int px, int py) +{ /* Fill the rectangle in chunks. */ + int width = tiles->size.x; + int height = tiles->size.y; + int raster = tiles->raster; + int rwidth = tiles->rep_width; + int rheight = tiles->rep_height; + int shift = tiles->shift; + int xoff = + (shift == 0 ? px : + px + (y + py) / rheight * tiles->rep_shift); + int irx = ((rwidth & (rwidth - 1)) == 0 ? /* power of 2 */ + (x + xoff) & (rwidth - 1) : + (x + xoff) % rwidth); + int ry = ((rheight & (rheight - 1)) == 0 ? /* power of 2 */ + (y + py) & (rheight - 1) : + (y + py) % rheight); + int icw = width - irx; + int ch = height - ry; + byte *row = tiles->data + ry * raster; + dev_proc_copy_mono((*proc_mono)); + dev_proc_copy_color((*proc_color)); + int code; + +#ifdef DEBUG +if ( gs_debug_c('t') ) + { int ptx, pty; + const byte *ptp = tiles->data; + dprintf3("[t]tile %dx%d raster=%d;", + tiles->size.x, tiles->size.y, tiles->raster); + dprintf6(" x,y=%d,%d w,h=%d,%d p=%d,%d\n", + x, y, w, h, px, py); + for ( pty = 0; pty < tiles->size.y; pty++ ) + { dprintf(" "); + for ( ptx = 0; ptx < tiles->raster; ptx++ ) + dprintf1("%3x", *ptp++); + } + dputc('\n'); + } +#endif + + /* + * We should really make the following check before doing + * all the computations above, but since we expect devices + * to implement strip_tile_rectangle rather than tile_rectangle, + * the check will rarely succeed. + */ + if ( dev_proc(dev, tile_rectangle) != gx_default_tile_rectangle ) + { if ( shift == 0 ) + { /* + * Temporarily patch the tile_rectangle procedure in the + * device so we don't get into a recursion loop if the + * device has a tile_rectangle procedure that conditionally + * calls the strip_tile_rectangle procedure. + */ + dev_proc_tile_rectangle((*tile_proc)) = + dev_proc(dev, tile_rectangle); + int code; + + set_dev_proc(dev, tile_rectangle, gx_default_tile_rectangle); + code = (*tile_proc) + (dev, (const gx_tile_bitmap *)tiles, x, y, w, h, + color0, color1, px, py); + set_dev_proc(dev, tile_rectangle, tile_proc); + return code; + } + /* We should probably optimize this case too, for the benefit */ + /* of window systems, but we don't yet. */ + } + + if ( color0 == gx_no_color_index && color1 == gx_no_color_index ) + proc_color = dev_proc(dev, copy_color); + else + proc_color = 0, proc_mono = dev_proc(dev, copy_mono); + +/****** SHOULD ALSO PASS id IF COPYING A FULL TILE ******/ +#define real_copy_tile(srcx, tx, ty, tw, th)\ + code =\ + (proc_color != 0 ?\ + (*proc_color)(dev, row, srcx, raster, gx_no_bitmap_id, tx, ty, tw, th) :\ + (*proc_mono)(dev, row, srcx, raster, gx_no_bitmap_id, tx, ty, tw, th, color0, color1));\ + if ( code < 0 ) return_error(code);\ + return_if_interrupt() +#ifdef DEBUG +#define copy_tile(sx, tx, ty, tw, th)\ + if ( gs_debug_c('t') )\ + dprintf5(" copy sx=%d x=%d y=%d w=%d h=%d\n",\ + sx, tx, ty, tw, th);\ + real_copy_tile(sx, tx, ty, tw, th) +#else +#define copy_tile(sx, tx, ty, tw, th)\ + real_copy_tile(sx, tx, ty, tw, th) +#endif + if ( ch >= h ) + { /* Shallow operation */ + if ( icw >= w ) + { /* Just one (partial) tile to transfer. */ + copy_tile(irx, x, y, w, h); + } + else + { int ex = x + w; + int fex = ex - width; + int cx = x + icw; + + copy_tile(irx, x, y, icw, h); + while ( cx <= fex ) + { copy_tile(0, cx, y, width, h); + cx += width; + } + if ( cx < ex ) + { copy_tile(0, cx, y, ex - cx, h); + } + } + } + else if ( icw >= w && shift == 0 ) + { /* Narrow operation, no shift */ + int ey = y + h; + int fey = ey - height; + int cy = y + ch; + + copy_tile(irx, x, y, w, ch); + row = tiles->data; + do + { ch = (cy > fey ? ey - cy : height); + copy_tile(irx, x, cy, w, ch); + } + while ( (cy += ch) < ey ); + } + else + { /* Full operation. If shift != 0, some scan lines */ + /* may be narrow. We could test shift == 0 in advance */ + /* and use a slightly faster loop, but right now */ + /* we don't bother. */ + int ex = x + w, ey = y + h; + int fex = ex - width, fey = ey - height; + int cx, cy; + + for ( cy = y; ; ) + { if ( icw >= w ) + { copy_tile(irx, x, cy, w, ch); + } + else + { copy_tile(irx, x, cy, icw, ch); + cx = x + icw; + while ( cx <= fex ) + { copy_tile(0, cx, cy, width, ch); + cx += width; + } + if ( cx < ex ) + { copy_tile(0, cx, cy, ex - cx, ch); + } + } + if ( (cy += ch) >= ey ) break; + ch = (cy > fey ? ey - cy : height); + if ( (irx += shift) >= rwidth ) + irx -= rwidth; + icw = width - irx; + row = tiles->data; + } + } +#undef copy_tile +#undef real_copy_tile + return 0; +} + +int +gx_no_strip_copy_rop(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) +{ return_error(gs_error_unknownerror); /* not implemented */ +} +int +gx_default_strip_copy_rop(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) +{ return (*gx_default_strip_copy_rop_proc) + (dev, sdata, sourcex, sraster, id, scolors, textures, tcolors, + x, y, width, height, phase_x, phase_y, lop); +} + +/* The following is not really a device procedure. See gxdevice.h. */ + +/* Create an ordinary memory device for page or band buffering. */ +int +gx_default_make_buffer_device(gx_device_memory *mdev, + gx_device *target, gs_memory_t *mem, bool for_band) +{ const gx_device_memory *mdproto = + gdev_mem_device_for_bits(target->color_info.depth); + + if ( mdproto == 0 ) + return_error(gs_error_rangecheck); + if ( target == (gx_device *)mdev ) + mdev->std_procs = mdproto->std_procs; + else + gs_make_mem_device(mdev, mdproto, mem, (for_band ? 1 : 0), + (target == (gx_device *)mdev ? 0 : target)); + return 0; +} + +/* ---------------- Default per-instance procedures ---------------- */ + +int +gx_default_install(gx_device *dev, gs_state *pgs) +{ return 0; +} + +int +gx_default_begin_page(gx_device *dev, gs_state *pgs) +{ return 0; +} + +int +gx_default_end_page(gx_device *dev, int reason, gs_state *pgs) +{ return (reason != 2 ? 1 : 0); +} + +/* ---------------- Unaligned copy operations ---------------- */ + +/* + * Implementing unaligned operations in terms of the standard aligned + * operations requires adjusting the bitmap origin and/or the raster + * to be aligned. Adjusting the origin is simple, but non-portable, + * since there is no portable way to determine the alignment of a pointer. + * Adjusting the raster requires doing the operation one scan line at a time. + */ + +int +gx_copy_mono_unaligned(gx_device *dev, const byte *data, + int dx, int raster, gx_bitmap_id id, int x, int y, int w, int h, + gx_color_index zero, gx_color_index one) +{ dev_proc_copy_mono((*copy_mono)) = dev_proc(dev, copy_mono); + uint offset = (uint)(data - (const byte *)0) & (align_bitmap_mod - 1); + int step = raster & (align_bitmap_mod - 1); + + /* Adjust the origin. */ + data -= offset; + dx += offset << 3; + + /* Adjust the raster. */ + if ( !step ) + { /* No adjustment needed. */ + return (*copy_mono)(dev, data, dx, raster, id, + x, y, w, h, zero, one); + } + + /* Do the transfer one scan line at a time. */ + { const byte *p = data; + int d = dx; + int code = 0; + int i; + + for ( i = 0; i < h && code >= 0; + ++i, p += raster - step, d += step << 3 + ) + code = (*copy_mono)(dev, p, d, raster, gx_no_bitmap_id, + x, y + i, w, 1, zero, one); + return code; + } +} + +int +gx_copy_color_unaligned(gx_device *dev, const byte *data, + int data_x, int raster, gx_bitmap_id id, + int x, int y, int width, int height) +{ dev_proc_copy_color((*copy_color)) = dev_proc(dev, copy_color); + int depth = dev->color_info.depth; + uint offset = (uint)(data - (const byte *)0) & (align_bitmap_mod - 1); + int step = raster & (align_bitmap_mod - 1); + + /* + * Adjust the origin. + * We have to do something very special for 24-bit data, + * because that is the only depth that doesn't divide + * align_bitmap_mod exactly. In particular, we need to find + * M*B + R == 0 mod 3, where M is align_bitmap_mod, R is the + * offset value just calculated, and B is an integer unknown; + * the new value of offset will be M*B + R. + */ + if ( depth == 24 ) + offset += (offset % 3) * + (align_bitmap_mod * (3 - (align_bitmap_mod % 3))); + data -= offset; + data_x += (offset << 3) / depth; + + /* Adjust the raster. */ + if ( !step ) + { /* No adjustment needed. */ + return (*copy_color)(dev, data, data_x, raster, id, + x, y, width, height); + } + + /* Do the transfer one scan line at a time. */ + { const byte *p = data; + int d = data_x; + int dstep = (step << 3) / depth; + int code = 0; + int i; + + for ( i = 0; i < height && code >= 0; + ++i, p += raster - step, d += dstep + ) + code = (*copy_color)(dev, p, d, raster, gx_no_bitmap_id, + x, y + i, width, 1); + return code; + } +} + +int +gx_copy_alpha_unaligned(gx_device *dev, const byte *data, int data_x, + int raster, gx_bitmap_id id, int x, int y, int width, int height, + gx_color_index color, int depth) +{ dev_proc_copy_alpha((*copy_alpha)) = dev_proc(dev, copy_alpha); + uint offset = (uint)(data - (const byte *)0) & (align_bitmap_mod - 1); + int step = raster & (align_bitmap_mod - 1); + + /* Adjust the origin. */ + data -= offset; + data_x += (offset << 3) / depth; + + /* Adjust the raster. */ + if ( !step ) + { /* No adjustment needed. */ + return (*copy_alpha)(dev, data, data_x, raster, id, + x, y, width, height, color, depth); + } + + /* Do the transfer one scan line at a time. */ + { const byte *p = data; + int d = data_x; + int dstep = (step << 3) / depth; + int code = 0; + int i; + + for ( i = 0; i < height && code >= 0; + ++i, p += raster - step, d += dstep + ) + code = (*copy_alpha)(dev, p, d, raster, gx_no_bitmap_id, + x, y + i, width, 1, color, depth); + return code; + } +} diff --git a/pstoraster/gdevemap.c b/pstoraster/gdevemap.c new file mode 100644 index 0000000000..939a83c9d7 --- /dev/null +++ b/pstoraster/gdevemap.c @@ -0,0 +1,64 @@ +/* Copyright (C) 1993 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to + anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer to + the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given to + you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises is not affiliated with the Free Software Foundation or + the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, + does not depend on any other GNU software. +*/ + +/* gdevemap.c */ +/* Mappings between StandardEncoding and ISOLatin1Encoding */ +#include "std.h" + +const byte far_data gs_map_std_to_iso[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 173, 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, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 161, 162, 163, 0, 165, 0, 167, 164, 0, 0, 171, 0, 0, 0, 0, + 0, 0, 0, 0, 183, 0, 182, 0, 0, 0, 0, 187, 0, 0, 0, 191, + 0, 145, 180, 147, 148, 175, 150, 151, 168, 0, 154, 184, 0, 157, 158, 159, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 198, 0, 170, 0, 0, 0, 0, 0, 216, 0, 186, 0, 0, 0, 0, + 0, 230, 0, 0, 0, 144, 0, 0, 0, 248, 0, 223, 0, 0, 0, 0 +}; + +const byte far_data gs_map_iso_to_std[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 0, 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, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 245, 193, 194, 195, 196, 197, 198, 199, 200, 0, 202, 203, 0, 205, 206, 207, + 32, 161, 162, 163, 168, 165, 0, 167, 200, 0, 227, 171, 0, 45, 0, 197, + 0, 0, 0, 0, 194, 0, 182, 180, 203, 0, 235, 187, 0, 0, 0, 191, + 0, 0, 0, 0, 0, 0, 225, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 233, 0, 0, 0, 0, 0, 0, 251, + 0, 0, 0, 0, 0, 0, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, 0, 0, 0, 0, 0 +}; diff --git a/pstoraster/gdevht.h b/pstoraster/gdevht.h new file mode 100644 index 0000000000..77bf5f28b7 --- /dev/null +++ b/pstoraster/gdevht.h @@ -0,0 +1,47 @@ +/* Copyright (C) 1995 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to + anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer to + the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given to + you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises is not affiliated with the Free Software Foundation or + the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, + does not depend on any other GNU software. +*/ + +/* gdevht.h */ +/* Definitions for halftoning device */ +/* Requires gxdevice.h */ +#include "gzht.h" + +/* + * A halftoning device converts between a non-halftoned device color space + * (e.g., 8-bit gray) and a halftoned space (e.g., 1-bit black and white). + * Currently, the target space must not exceed 8 bits per pixel, so that + * we can pack two target colors and a halftone level into a gx_color_index. + */ +#define ht_target_max_depth 8 +#define ht_level_depth (sizeof(gx_color_index) * 8 - ht_target_max_depth * 2) +typedef struct gx_device_ht_s { + gx_device_forward_common; + /* Following are set before opening. */ + const gx_device_halftone *dev_ht; + gs_int_point ht_phase; /* halftone phase from gstate */ + /* Following are computed when device is opened. */ + gs_int_point phase; /* halftone tile offset */ +} gx_device_ht; + +/* Macro for casting gx_device argument */ +#define htdev ((gx_device_ht *)dev) diff --git a/pstoraster/gdevm1.c b/pstoraster/gdevm1.c new file mode 100644 index 0000000000..f0787d56b3 --- /dev/null +++ b/pstoraster/gdevm1.c @@ -0,0 +1,689 @@ +/* Copyright (C) 1989, 1995, 1996 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to + anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer to + the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given to + you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises is not affiliated with the Free Software Foundation or + the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, + does not depend on any other GNU software. +*/ + +/* gdevm1.c */ +/* Monobit "memory" (stored bitmap) device */ +#include "memory_.h" +#include "gx.h" +#include "gxdevice.h" +#include "gxdevmem.h" /* semi-public definitions */ +#include "gdevmem.h" /* private definitions */ + +extern dev_proc_strip_copy_rop(mem_mono_strip_copy_rop); /* in gdevmrop.c */ + +/* Optionally, use the slow RasterOp implementations for testing. */ +/*#define USE_COPY_ROP*/ + +#ifdef USE_COPY_ROP +#include "gsrop.h" +#endif + +/* ================ 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 far_data mem_mono_device = + mem_full_alpha_device("image1", 0, 1, mem_open, + mem_mono_map_rgb_color, mem_mono_map_color_rgb, + mem_mono_copy_mono, gx_default_copy_color, mem_mono_fill_rectangle, + mem_get_bits, gx_default_map_cmyk_color, gx_no_copy_alpha, + mem_mono_strip_tile_rectangle, mem_mono_strip_copy_rop); + +/* Map color to/from RGB. This may be inverted. */ +private gx_color_index +mem_mono_map_rgb_color(gx_device *dev, gx_color_value r, gx_color_value g, + gx_color_value b) +{ return (gx_default_w_b_map_rgb_color(dev, r, g, b) ^ + mdev->palette.data[0]) & 1; +} +private int +mem_mono_map_color_rgb(gx_device *dev, gx_color_index color, + gx_color_value prgb[3]) +{ return gx_default_w_b_map_color_rgb(dev, + (color ^ mdev->palette.data[0]) & 1, + prgb); +} + +/* Fill a rectangle with a color. */ +private int +mem_mono_fill_rectangle(gx_device *dev, int x, int y, int w, int h, + gx_color_index color) +{ +#ifdef USE_COPY_ROP + return mem_mono_copy_rop(dev, NULL, 0, 0, gx_no_bitmap_id, NULL, + NULL, NULL, + x, y, w, h, 0, 0, + (color ? rop3_1 : rop3_0)); +#else + fit_fill(dev, x, y, w, h); + bits_fill_rectangle(scan_line_base(mdev, y), x, mdev->raster, + -(mono_fill_chunk)color, w, h); + return 0; +#endif +} + +/* Convert x coordinate to byte offset in scan line. */ +#define x_to_byte(x) ((x) >> 3) + +/* Copy a monochrome bitmap. */ +#undef mono_masks +#define mono_masks mono_copy_masks + +/* Fetch a chunk from the source. */ +/* The source data are always stored big-endian. */ +/* Note that the macros always cast cptr, */ +/* so it doesn't matter what the type of cptr is. */ +/* cshift = chunk_bits - shift. */ +#undef chunk +#if arch_is_big_endian +# define chunk uint +# define cfetch_right(cptr, shift, cshift)\ + (cfetch_aligned(cptr) >> shift) +# define cfetch_left(cptr, shift, cshift)\ + (cfetch_aligned(cptr) << shift) +/* Fetch a chunk that straddles a chunk boundary. */ +# define cfetch2(cptr, cskew, skew)\ + (cfetch_left(cptr, cskew, skew) +\ + cfetch_right((const chunk *)(cptr) + 1, skew, cskew)) +#else /* little-endian */ +# define chunk bits16 +private const bits16 right_masks2[9] = { + 0xffff, 0x7f7f, 0x3f3f, 0x1f1f, 0x0f0f, 0x0707, 0x0303, 0x0101, 0x0000 +}; +private const bits16 left_masks2[9] = { + 0xffff, 0xfefe, 0xfcfc, 0xf8f8, 0xf0f0, 0xe0e0, 0xc0c0, 0x8080, 0x0000 +}; +# define ccont(cptr, off) (((const chunk *)(cptr))[off]) +# define cfetch_right(cptr, shift, cshift)\ + ((shift) < 8 ?\ + ((ccont(cptr, 0) >> (shift)) & right_masks2[shift]) +\ + (ccont(cptr, 0) << (cshift)) :\ + ((chunk)*(const byte *)(cptr) << (cshift)) & 0xff00) +# define cfetch_left(cptr, shift, cshift)\ + ((shift) < 8 ?\ + ((ccont(cptr, 0) << (shift)) & left_masks2[shift]) +\ + (ccont(cptr, 0) >> (cshift)) :\ + ((ccont(cptr, 0) & 0xff00) >> (cshift)) & 0xff) +/* Fetch a chunk that straddles a chunk boundary. */ +/* We can avoid testing the shift amount twice */ +/* by expanding the cfetch_left/right macros in-line. */ +# define cfetch2(cptr, cskew, skew)\ + ((cskew) < 8 ?\ + ((ccont(cptr, 0) << (cskew)) & left_masks2[cskew]) +\ + (ccont(cptr, 0) >> (skew)) +\ + (((chunk)(((const byte *)(cptr))[2]) << (cskew)) & 0xff00) :\ + (((ccont(cptr, 0) & 0xff00) >> (skew)) & 0xff) +\ + ((ccont(cptr, 1) >> (skew)) & right_masks2[skew]) +\ + (ccont(cptr, 1) << (cskew))) +#endif +/* Since source and destination are both always big-endian, */ +/* fetching an aligned chunk never requires byte swapping. */ +# define cfetch_aligned(cptr)\ + (*(const chunk *)(cptr)) + +/* copy_function and copy_shift get added together for dispatch */ +typedef enum { + copy_or = 0, copy_store, copy_and, copy_funny +} copy_function; +/* copy_right/left is not an enum, because compilers complain about */ +/* an enumeration clash when these are added to a copy_function. */ +#define copy_right ((copy_function)0) +#define copy_left ((copy_function)4) +typedef struct { + short invert; + ushort op; /* copy_function */ +} copy_mode; +/* Map from to copy_mode. */ +#define cm(i,op) { i, (ushort)op } +private copy_mode copy_modes[9] = { + cm(-1, copy_funny), /* NN */ + cm(-1, copy_and), /* N0 */ + cm(0, copy_or), /* N1 */ + cm(0, copy_and), /* 0N */ + cm(0, copy_funny), /* 00 */ + cm(0, copy_store), /* 01 */ + cm(-1, copy_or), /* 1N */ + cm(-1, copy_store), /* 10 */ + cm(0, copy_funny), /* 11 */ +}; +private int +mem_mono_copy_mono(gx_device *dev, + const byte *base, int sourcex, int sraster, gx_bitmap_id id, + int x, int y, int w, int h, gx_color_index zero, gx_color_index one) +{ +#ifdef USE_COPY_ROP + return mem_mono_copy_rop(dev, base, sourcex, sraster, id, NULL, + NULL, NULL, + x, y, w, h, 0, 0, + ((zero == gx_no_color_index ? rop3_D : + zero == 0 ? rop3_0 : rop3_1) & ~rop3_S) | + ((one == gx_no_color_index ? rop3_D : + one == 0 ? rop3_0 : rop3_1) & rop3_S)); +#else /* !USE_COPY_ROP */ + register const byte *bptr; /* actually chunk * */ + int dbit, wleft; + uint mask; + copy_mode mode; +#define function (copy_function)(mode.op) + declare_scan_ptr_as(dbptr, byte *); +#define optr ((chunk *)dbptr) + register int skew; + register uint invert; + fit_copy(dev, base, sourcex, sraster, id, x, y, w, h); +#if gx_no_color_index_value != -1 /* hokey! */ + if ( zero == gx_no_color_index ) zero = -1; + if ( one == gx_no_color_index ) one = -1; +#endif +#define izero (int)zero +#define ione (int)one + mode = copy_modes[izero + izero + izero + ione + 4]; +#undef izero +#undef ione + invert = (uint)(int)mode.invert; /* load register */ + setup_rect_as(dbptr, byte *); + bptr = base + ((sourcex & ~chunk_align_bit_mask) >> 3); + dbit = x & chunk_align_bit_mask; + skew = dbit - (sourcex & chunk_align_bit_mask); +/* Macros for writing partial chunks. */ +/* The destination pointer is always named optr, */ +/* and must be declared as chunk *. */ +/* cinvert may be temporarily redefined. */ +#define cinvert(bits) ((bits) ^ invert) +#define write_or_masked(bits, mask, off)\ + optr[off] |= (cinvert(bits) & mask) +#define write_store_masked(bits, mask, off)\ + optr[off] = ((optr[off] & ~mask) | (cinvert(bits) & mask)) +#define write_and_masked(bits, mask, off)\ + optr[off] &= (cinvert(bits) | ~mask) +/* Macros for writing full chunks. */ +#define write_or(bits) *optr |= cinvert(bits) +#define write_store(bits) *optr = cinvert(bits) +#define write_and(bits) *optr &= cinvert(bits) +/* Macro for incrementing to next chunk. */ +#define next_x_chunk\ + bptr += chunk_bytes; dbptr += chunk_bytes +/* Common macro for the end of each scan line. */ +#define end_y_loop(sdelta, ddelta)\ + if ( --h == 0 ) break;\ + bptr += sdelta; dbptr += ddelta + if ( (wleft = w + dbit - chunk_bits) <= 0 ) + { /* The entire operation fits in one (destination) chunk. */ + set_mono_thin_mask(mask, w, dbit); +#define write_single(wr_op, src)\ + for ( ; ; )\ + { wr_op(src, mask, 0);\ + end_y_loop(sraster, draster);\ + } +#define write1_loop(src)\ + switch ( function ) {\ + case copy_or: write_single(write_or_masked, src); break;\ + case copy_store: write_single(write_store_masked, src); break;\ + case copy_and: write_single(write_and_masked, src); break;\ + default: goto funny;\ + } + if ( skew >= 0 ) /* single -> single, right/no shift */ + { if ( skew == 0 ) /* no shift */ + { write1_loop(cfetch_aligned(bptr)); + } + else /* right shift */ + { int cskew = chunk_bits - skew; + write1_loop(cfetch_right(bptr, skew, cskew)); + } + } + else if ( wleft <= skew ) /* single -> single, left shift */ + { int cskew = chunk_bits + skew; + skew = -skew; + write1_loop(cfetch_left(bptr, skew, cskew)); + } + else /* double -> single */ + { int cskew = -skew; + skew += chunk_bits; + write1_loop(cfetch2(bptr, cskew, skew)); + } +#undef write1_loop +#undef write_single + } + else if ( wleft <= skew ) + { /* 1 source chunk -> 2 destination chunks. */ + /* This is an important special case for */ + /* both characters and halftone tiles. */ + uint rmask; + int cskew = chunk_bits - skew; + set_mono_left_mask(mask, dbit); + set_mono_right_mask(rmask, wleft); +#undef cinvert +#define cinvert(bits) (bits) /* pre-inverted here */ +#if arch_is_big_endian /* no byte swapping */ +# define write_1to2(wr_op)\ + for ( ; ; )\ + { register uint bits = cfetch_aligned(bptr) ^ invert;\ + wr_op(bits >> skew, mask, 0);\ + wr_op(bits << cskew, rmask, 1);\ + end_y_loop(sraster, draster);\ + } +#else /* byte swapping */ +# define write_1to2(wr_op)\ + for ( ; ; )\ + { wr_op(cfetch_right(bptr, skew, cskew) ^ invert, mask, 0);\ + wr_op(cfetch_left(bptr, cskew, skew) ^ invert, rmask, 1);\ + end_y_loop(sraster, draster);\ + } +#endif + switch ( function ) + { + case copy_or: write_1to2(write_or_masked); break; + case copy_store: write_1to2(write_store_masked); break; + case copy_and: write_1to2(write_and_masked); break; + default: goto funny; + } +#undef cinvert +#define cinvert(bits) ((bits) ^ invert) +#undef write_1to2 + } + else + { /* More than one source chunk and more than one */ + /* destination chunk are involved. */ + uint rmask; + int words = (wleft & ~chunk_bit_mask) >> 3; + uint sskip = sraster - words; + uint dskip = draster - words; + register uint bits; + set_mono_left_mask(mask, dbit); + set_mono_right_mask(rmask, wleft & chunk_bit_mask); + if ( skew == 0 ) /* optimize the aligned case */ + { +#define write_aligned(wr_op, wr_op_masked)\ + for ( ; ; )\ + { int count = wleft;\ + /* Do first partial chunk. */\ + wr_op_masked(cfetch_aligned(bptr), mask, 0);\ + /* Do full chunks. */\ + while ( (count -= chunk_bits) >= 0 )\ + { next_x_chunk; wr_op(cfetch_aligned(bptr)); }\ + /* Do last chunk */\ + if ( count > -chunk_bits )\ + { wr_op_masked(cfetch_aligned(bptr + chunk_bytes), rmask, 1); }\ + end_y_loop(sskip, dskip);\ + } + switch ( function ) + { + case copy_or: + write_aligned(write_or, write_or_masked); + break; + case copy_store: + write_aligned(write_store, write_store_masked); + break; + case copy_and: + write_aligned(write_and, write_and_masked); + break; + default: + goto funny; + } +#undef write_aligned + } + else /* not aligned */ + { int ccase = + (skew >= 0 ? copy_right : + ((bptr += chunk_bytes), copy_left)) + + (int)function; + int cskew = -skew & chunk_bit_mask; + skew &= chunk_bit_mask; + for ( ; ; ) + { int count = wleft; +#define prefetch_right\ + bits = cfetch_right(bptr, skew, cskew) +#define prefetch_left\ + bits = cfetch2(bptr - chunk_bytes, cskew, skew) +#define write_unaligned(wr_op, wr_op_masked)\ + wr_op_masked(bits, mask, 0);\ + /* Do full chunks. */\ + while ( count >= chunk_bits )\ + { bits = cfetch2(bptr, cskew, skew);\ + next_x_chunk; wr_op(bits); count -= chunk_bits;\ + }\ + /* Do last chunk */\ + if ( count > 0 )\ + { bits = cfetch_left(bptr, cskew, skew);\ + if ( count > skew ) bits += cfetch_right(bptr + chunk_bytes, skew, cskew);\ + wr_op_masked(bits, rmask, 1);\ + } + switch ( ccase ) + { + case copy_or + copy_left: + prefetch_left; goto uor; + case copy_or + copy_right: + prefetch_right; +uor: write_unaligned(write_or, write_or_masked); + break; + case copy_store + copy_left: + prefetch_left; goto ustore; + case copy_store + copy_right: + prefetch_right; +ustore: write_unaligned(write_store, write_store_masked); + break; + case copy_and + copy_left: + prefetch_left; goto uand; + case copy_and + copy_right: + prefetch_right; +uand: write_unaligned(write_and, write_and_masked); + break; + default: + goto funny; + } + end_y_loop(sskip, dskip); +#undef write_unaligned +#undef prefetch_left +#undef prefetch_right + } + } + } +#undef end_y_loop +#undef next_x_chunk + return 0; + /* Handle the funny cases that aren't supposed to happen. */ +funny: return (invert ? -1 : mem_mono_fill_rectangle(dev, x, y, w, h, zero)); +#undef optr +#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. */ +private int +mem_mono_strip_tile_rectangle(gx_device *dev, + register const gx_strip_bitmap *tiles, + int tx, int y, int tw, int th, gx_color_index color0, gx_color_index color1, + int px, int py) +{ +#ifdef USE_COPY_ROP + return mem_mono_strip_copy_rop(dev, NULL, 0, 0, tile->id, NULL, + tiles, NULL, + tx, y, tw, th, px, py, + ((color0 == gx_no_color_index ? rop3_D : + color0 == 0 ? rop3_0 : rop3_1) & ~rop3_T) | + ((color1 == gx_no_color_index ? rop3_D : + color1 == 0 ? rop3_0 : rop3_1) & rop3_T)); +#else /* !USE_COPY_ROP */ + register uint invert; + int sraster; + uint tile_bits_size; + const byte *base; + const byte *end; + int x, rw, w, h; + register const byte *bptr; /* actually chunk * */ + int dbit, wleft; + uint mask; + byte *dbase; + declare_scan_ptr_as(dbptr, byte *); +#define optr ((chunk *)dbptr) + register int skew; + + /* This implementation doesn't handle strips yet. */ + if ( color0 != (color1 ^ 1) || tiles->shift != 0 ) + return gx_default_strip_tile_rectangle(dev, tiles, tx, y, tw, th, + color0, color1, px, py); + fit_fill(dev, tx, y, tw, th); + invert = -(uint)color0; + sraster = tiles->raster; + base = tiles->data + ((y + py) % tiles->rep_height) * sraster; + tile_bits_size = tiles->size.y * sraster; + end = tiles->data + tile_bits_size; +#undef end_y_loop +#define end_y_loop(sdelta, ddelta)\ + if ( --h == 0 ) break;\ + if ( end - bptr <= sdelta ) /* wrap around */\ + bptr -= tile_bits_size;\ + bptr += sdelta; dbptr += ddelta + draster = mdev->raster; + dbase = scan_line_base(mdev, y); + x = tx; + rw = tw; + /* + * The outermost loop here works horizontally, one iteration per + * copy of the tile. Note that all iterations except the first + * have sourcex = 0. + */ + { int sourcex = (x + px) % tiles->rep_width; + w = tiles->size.x - sourcex; + bptr = base + ((sourcex & ~chunk_align_bit_mask) >> 3); + dbit = x & chunk_align_bit_mask; + skew = dbit - (sourcex & chunk_align_bit_mask); + } +outer: if ( w > rw ) + w = rw; + h = th; + dbptr = dbase + ((x >> 3) & -chunk_align_bytes); + if ( (wleft = w + dbit - chunk_bits) <= 0 ) + { /* The entire operation fits in one (destination) chunk. */ + set_mono_thin_mask(mask, w, dbit); +#define write1_loop(src)\ + for ( ; ; )\ + { write_store_masked(src, mask, 0);\ + end_y_loop(sraster, draster);\ + } + if ( skew >= 0 ) /* single -> single, right/no shift */ + { if ( skew == 0 ) /* no shift */ + { write1_loop(cfetch_aligned(bptr)); + } + else /* right shift */ + { int cskew = chunk_bits - skew; + write1_loop(cfetch_right(bptr, skew, cskew)); + } + } + else if ( wleft <= skew ) /* single -> single, left shift */ + { int cskew = chunk_bits + skew; + skew = -skew; + write1_loop(cfetch_left(bptr, skew, cskew)); + } + else /* double -> single */ + { int cskew = -skew; + skew += chunk_bits; + write1_loop(cfetch2(bptr, cskew, skew)); + } +#undef write1_loop + } + else if ( wleft <= skew ) + { /* 1 source chunk -> 2 destination chunks. */ + /* This is an important special case for */ + /* both characters and halftone tiles. */ + uint rmask; + int cskew = chunk_bits - skew; + set_mono_left_mask(mask, dbit); + set_mono_right_mask(rmask, wleft); +#if arch_is_big_endian /* no byte swapping */ +#undef cinvert +#define cinvert(bits) (bits) /* pre-inverted here */ + for ( ; ; ) + { register uint bits = cfetch_aligned(bptr) ^ invert; + write_store_masked(bits >> skew, mask, 0); + write_store_masked(bits << cskew, rmask, 1); + end_y_loop(sraster, draster); + } +#undef cinvert +#define cinvert(bits) ((bits) ^ invert) +#else /* byte swapping */ + for ( ; ; ) + { write_store_masked(cfetch_right(bptr, skew, cskew), mask, 0); + write_store_masked(cfetch_left(bptr, cskew, skew), rmask, 1); + end_y_loop(sraster, draster); + } +#endif + } + else + { /* More than one source chunk and more than one */ + /* destination chunk are involved. */ + uint rmask; + int words = (wleft & ~chunk_bit_mask) >> 3; + uint sskip = sraster - words; + uint dskip = draster - words; + register uint bits; +#define next_x_chunk\ + bptr += chunk_bytes; dbptr += chunk_bytes + + set_mono_right_mask(rmask, wleft & chunk_bit_mask); + if ( skew == 0 ) /* optimize the aligned case */ + { if ( dbit == 0 ) + mask = 0; + else + set_mono_left_mask(mask, dbit); + for ( ; ; ) + { int count = wleft; + /* Do first partial chunk. */ + if ( mask ) + write_store_masked(cfetch_aligned(bptr), mask, 0); + else + write_store(cfetch_aligned(bptr)); + /* Do full chunks. */ + while ( (count -= chunk_bits) >= 0 ) + { next_x_chunk; + write_store(cfetch_aligned(bptr)); + } + /* Do last chunk */ + if ( count > -chunk_bits ) + { write_store_masked(cfetch_aligned(bptr + chunk_bytes), rmask, 1); + } + end_y_loop(sskip, dskip); + } + } + else /* not aligned */ + { bool case_right = + (skew >= 0 ? true : + ((bptr += chunk_bytes), false)); + int cskew = -skew & chunk_bit_mask; + + skew &= chunk_bit_mask; + set_mono_left_mask(mask, dbit); + for ( ; ; ) + { int count = wleft; + if ( case_right ) + bits = cfetch_right(bptr, skew, cskew); + else + bits = cfetch2(bptr - chunk_bytes, cskew, skew); + write_store_masked(bits, mask, 0); + /* Do full chunks. */ + while ( count >= chunk_bits ) + { bits = cfetch2(bptr, cskew, skew); + next_x_chunk; + write_store(bits); + count -= chunk_bits; + } + /* Do last chunk */ + if ( count > 0 ) + { bits = cfetch_left(bptr, cskew, skew); + if ( count > skew ) + bits += cfetch_right(bptr + chunk_bytes, skew, cskew); + write_store_masked(bits, rmask, 1); + } + end_y_loop(sskip, dskip); + } + } + } +#undef end_y_loop +#undef next_x_chunk +#undef optr + if ( (rw -= w) > 0 ) + { x += w; + w = tiles->size.x; + bptr = base; + skew = dbit = x & chunk_align_bit_mask; + goto outer; + } + return 0; +#endif /* !USE_COPY_ROP */ +} + +#endif /**************** ****************/ + +/* ================ "Word"-oriented device ================ */ + +/* Note that on a big-endian machine, this is the same as the */ +/* standard byte-oriented-device. */ + +#if !arch_is_big_endian + +/* Procedures */ +private dev_proc_copy_mono(mem1_word_copy_mono); +private dev_proc_fill_rectangle(mem1_word_fill_rectangle); +#define mem1_word_strip_tile_rectangle gx_default_strip_tile_rectangle + +/* Here is the device descriptor. */ +const gx_device_memory far_data mem_mono_word_device = + mem_full_alpha_device("image1w", 0, 1, mem_open, + mem_mono_map_rgb_color, mem_mono_map_color_rgb, + mem1_word_copy_mono, gx_default_copy_color, mem1_word_fill_rectangle, + mem_word_get_bits, gx_default_map_cmyk_color, gx_no_copy_alpha, + mem1_word_strip_tile_rectangle, gx_no_strip_copy_rop); + +/* Fill a rectangle with a color. */ +private int +mem1_word_fill_rectangle(gx_device *dev, int x, int y, int w, int h, + gx_color_index color) +{ byte *base; + uint raster; + fit_fill(dev, x, y, w, h); + base = scan_line_base(mdev, y); + raster = mdev->raster; + mem_swap_byte_rect(base, raster, x, w, h, true); + bits_fill_rectangle(base, x, raster, -(mono_fill_chunk)color, w, h); + mem_swap_byte_rect(base, raster, x, w, h, true); + return 0; +} + +/* Copy a bitmap. */ +private int +mem1_word_copy_mono(gx_device *dev, + const byte *base, int sourcex, int sraster, gx_bitmap_id id, + int x, int y, int w, int h, gx_color_index zero, gx_color_index one) +{ byte *row; + uint raster; + bool store; + fit_copy(dev, base, sourcex, sraster, id, x, y, w, h); + row = scan_line_base(mdev, y); + raster = mdev->raster; + store = (zero != gx_no_color_index && one != gx_no_color_index); + mem_swap_byte_rect(row, raster, x, w, h, store); + mem_mono_copy_mono(dev, base, sourcex, sraster, id, + x, y, w, h, zero, one); + mem_swap_byte_rect(row, raster, x, w, h, false); + return 0; +} + +#endif /* !arch_is_big_endian */ diff --git a/pstoraster/gdevm16.c b/pstoraster/gdevm16.c new file mode 100644 index 0000000000..149a72129e --- /dev/null +++ b/pstoraster/gdevm16.c @@ -0,0 +1,154 @@ +/* Copyright (C) 1994, 1996 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to + anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer to + the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given to + you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises is not affiliated with the Free Software Foundation or + the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, + does not depend on any other GNU software. +*/ + +/* gdevm16.c */ +/* 16-bit-per-pixel "memory" (stored bitmap) device */ +#include "memory_.h" +#include "gx.h" +#include "gxdevice.h" +#include "gxdevmem.h" /* semi-public definitions */ +#include "gdevmem.h" /* private definitions */ + +#undef chunk +#define chunk byte + +/* The 16 bits are divided 5 for red, 6 for green, and 5 for blue. */ +/* Note that the bits must always be kept in big-endian order. */ + +/* Procedures */ +declare_mem_map_procs(mem_true16_map_rgb_color, mem_true16_map_color_rgb); +declare_mem_procs(mem_true16_copy_mono, mem_true16_copy_color, mem_true16_fill_rectangle); + +/* The device descriptor. */ +const gx_device_memory far_data mem_true16_device = + mem_device("image16", 16, 0, + mem_true16_map_rgb_color, mem_true16_map_color_rgb, + mem_true16_copy_mono, mem_true16_copy_color, mem_true16_fill_rectangle, + gx_no_strip_copy_rop); + +/* Map a r-g-b color to a color index. */ +private gx_color_index +mem_true16_map_rgb_color(gx_device *dev, gx_color_value r, gx_color_value g, + gx_color_value b) +{ return ((r >> (gx_color_value_bits - 5)) << 11) + + ((g >> (gx_color_value_bits - 6)) << 5) + + (b >> (gx_color_value_bits - 5)); +} + +/* Map a color index to a r-g-b color. */ +private int +mem_true16_map_color_rgb(gx_device *dev, gx_color_index color, + gx_color_value prgb[3]) +{ ushort value = color >> 11; + prgb[0] = ((value << 11) + (value << 6) + (value << 1) + (value >> 4)) >> (16 - gx_color_value_bits); + value = (color >> 6) & 0x7f; + prgb[1] = ((value << 10) + (value << 4) + (value >> 2)) >> (16 - gx_color_value_bits); + value = color & 0x3f; + prgb[2] = ((value << 11) + (value << 6) + (value << 1) + (value >> 4)) >> (16 - gx_color_value_bits); + return 0; +} + +/* Convert x coordinate to byte offset in scan line. */ +#undef x_to_byte +#define x_to_byte(x) ((x) << 1) + +/* Fill a rectangle with a color. */ +private int +mem_true16_fill_rectangle(gx_device *dev, + int x, int y, int w, int h, gx_color_index color) +{ +#if arch_is_big_endian +# define color16 ((ushort)color) +#else + ushort color16 = ((uint)(byte)color << 8) + ((ushort)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); + } + return 0; +#undef color16 +} + +/* Copy a monochrome bitmap. */ +private int +mem_true16_copy_mono(gx_device *dev, + const byte *base, int sourcex, int sraster, gx_bitmap_id id, + int x, int y, int w, int h, gx_color_index zero, gx_color_index one) +{ +#if arch_is_big_endian +# define zero16 ((ushort)zero) +# define one16 ((ushort)one) +#else + ushort zero16 = ((uint)(byte)zero << 8) + ((ushort)zero >> 8); + ushort one16 = ((uint)(byte)one << 8) + ((ushort)one >> 8); +#endif + const byte *line; + int first_bit; + declare_scan_ptr(dest); + fit_copy(dev, base, sourcex, sraster, id, x, y, w, h); + setup_rect(dest); + line = base + (sourcex >> 3); + first_bit = 0x80 >> (sourcex & 7); + while ( h-- > 0 ) + { register ushort *pptr = (ushort *)dest; + const byte *sptr = line; + register int sbyte = *sptr++; + register int bit = first_bit; + int count = w; + do + { if ( sbyte & bit ) + { if ( one != gx_no_color_index ) + *pptr = one16; + } + else + { if ( zero != gx_no_color_index ) + *pptr = zero16; + } + if ( (bit >>= 1) == 0 ) + bit = 0x80, sbyte = *sptr++; + pptr++; + } + while ( --count > 0 ); + line += sraster; + inc_ptr(dest, draster); + } + return 0; +#undef zero16 +#undef one16 +} + +/* Copy a color bitmap. */ +private int +mem_true16_copy_color(gx_device *dev, + const byte *base, int sourcex, int sraster, gx_bitmap_id id, + int x, int y, int w, int h) +{ fit_copy(dev, base, sourcex, sraster, id, x, y, w, h); + mem_copy_byte_rect(mdev, base, sourcex, sraster, x, y, w, h); + return 0; +} diff --git a/pstoraster/gdevm2.c b/pstoraster/gdevm2.c new file mode 100644 index 0000000000..f68ccea72c --- /dev/null +++ b/pstoraster/gdevm2.c @@ -0,0 +1,244 @@ +/* Copyright (C) 1994, 1995, 1996 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to + anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer to + the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given to + you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises is not affiliated with the Free Software Foundation or + the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, + does not depend on any other GNU software. +*/ + +/* gdevm2.c */ +/* 2-bit-per-pixel "memory" (stored bitmap) device */ +#include "memory_.h" +#include "gx.h" +#include "gxdevice.h" +#include "gxdevmem.h" /* semi-public definitions */ +#include "gdevmem.h" /* private definitions */ + +/**************** NOTE: copy_rop only works for gray scale ****************/ +extern dev_proc_strip_copy_rop(mem_gray_strip_copy_rop); + +/* ================ Standard (byte-oriented) device ================ */ + +#undef chunk +#define chunk byte +#define fpat(byt) mono_fill_make_pattern(byt) + +/* Procedures */ +declare_mem_procs(mem_mapped2_copy_mono, mem_mapped2_copy_color, mem_mapped2_fill_rectangle); + +/* The device descriptor. */ +const gx_device_memory far_data mem_mapped2_device = + mem_device("image2", 2, 0, + mem_mapped_map_rgb_color, mem_mapped_map_color_rgb, + mem_mapped2_copy_mono, mem_mapped2_copy_color, mem_mapped2_fill_rectangle, + mem_gray_strip_copy_rop); + +/* Convert x coordinate to byte offset in scan line. */ +#undef x_to_byte +#define x_to_byte(x) ((x) >> 2) + +/* Define the 2-bit fill patterns. */ +static const mono_fill_chunk tile_patterns[4] = +{ fpat(0x00), fpat(0x55), fpat(0xaa), fpat(0xff) +}; + +/* Fill a rectangle with a color. */ +private int +mem_mapped2_fill_rectangle(gx_device *dev, + int x, int y, int w, int h, gx_color_index color) +{ fit_fill(dev, x, y, w, h); + bits_fill_rectangle(scan_line_base(mdev, y), x << 1, mdev->raster, + tile_patterns[color], w << 1, h); + return 0; +} + +/* Copy a bitmap. */ +private int +mem_mapped2_copy_mono(gx_device *dev, + const byte *base, int sourcex, int sraster, gx_bitmap_id id, + int x, int y, int w, int h, gx_color_index zero, gx_color_index one) +{ const byte *line; + int first_bit; + byte first_mask, b0, b1, bxor, left_mask, right_mask; + static const byte btab[4] = { 0, 0x55, 0xaa, 0xff }; + static const byte bmask[4] = { 0xc0, 0x30, 0xc, 3 }; + static const byte lmask[4] = { 0, 0xc0, 0xf0, 0xfc }; + declare_scan_ptr(dest); + + fit_copy(dev, base, sourcex, sraster, id, x, y, w, h); + setup_rect(dest); + line = base + (sourcex >> 3); + first_bit = 0x80 >> (sourcex & 7); + first_mask = bmask[x & 3]; + left_mask = lmask[x & 3]; + right_mask = ~lmask[(x + w) & 3]; + if ( (x & 3) + w <= 4 ) + left_mask = right_mask = left_mask | right_mask; + b0 = btab[zero & 3]; + b1 = btab[one & 3]; + bxor = b0 ^ b1; + while ( h-- > 0 ) + { register byte *pptr = (byte *)dest; + const byte *sptr = line; + register int sbyte = *sptr++; + register int bit = first_bit; + register byte mask = first_mask; + int count = w; + + /* We have 4 cases, of which only 2 really matter. */ + if ( one != gx_no_color_index ) + { if ( zero != gx_no_color_index ) + { /* Copying an opaque bitmap. */ + byte data = + (*pptr & left_mask) | (b0 & ~left_mask); + do + { if ( sbyte & bit ) + data ^= bxor & mask; + if ( (bit >>= 1) == 0 ) + bit = 0x80, sbyte = *sptr++; + if ( (mask >>= 2) == 0 ) + mask = 0xc0, *pptr++ = data, data = b0; + } + while ( --count > 0 ); + if ( mask != 0xc0 ) + *pptr = + (*pptr & right_mask) | (data & ~right_mask); + } + else + { /* Filling a mask. */ + do + { if ( sbyte & bit ) + *pptr = (*pptr & ~mask) + (b1 & mask); + if ( (bit >>= 1) == 0 ) + bit = 0x80, sbyte = *sptr++; + if ( (mask >>= 2) == 0 ) + mask = 0xc0, pptr++; + } + while ( --count > 0 ); + } + } + else + { /* Some other case. */ + do + { if ( !(sbyte & bit) ) + { if ( zero != gx_no_color_index ) + *pptr = (*pptr & ~mask) + (b0 & mask); + } + if ( (bit >>= 1) == 0 ) + bit = 0x80, sbyte = *sptr++; + if ( (mask >>= 2) == 0 ) + mask = 0xc0, pptr++; + } + while ( --count > 0 ); + } + line += sraster; + inc_ptr(dest, draster); + } + return 0; +} + +/* Copy a color bitmap. */ +private int +mem_mapped2_copy_color(gx_device *dev, + const byte *base, int sourcex, int sraster, gx_bitmap_id id, + int x, int y, int w, int h) +{ int code; + fit_copy(dev, base, sourcex, sraster, id, x, y, w, h); + /* Use monobit copy_mono. */ + /* Patch the width in the device temporarily. */ + dev->width <<= 1; + code = (*dev_proc(&mem_mono_device, copy_mono)) + (dev, base, sourcex << 1, sraster, id, + x << 1, y, w << 1, h, (gx_color_index)0, (gx_color_index)1); + /* Restore the correct width. */ + dev->width >>= 1; + return code; +} + +/* ================ "Word"-oriented device ================ */ + +/* Note that on a big-endian machine, this is the same as the */ +/* standard byte-oriented-device. */ + +#if !arch_is_big_endian + +/* Procedures */ +declare_mem_procs(mem2_word_copy_mono, mem2_word_copy_color, mem2_word_fill_rectangle); + +/* Here is the device descriptor. */ +const gx_device_memory far_data mem_mapped2_word_device = + mem_full_device("image2w", 2, 0, mem_open, + mem_mapped_map_rgb_color, mem_mapped_map_color_rgb, + mem2_word_copy_mono, mem2_word_copy_color, mem2_word_fill_rectangle, + mem_word_get_bits, gx_default_map_cmyk_color, + gx_default_strip_tile_rectangle, gx_no_strip_copy_rop); + +/* Fill a rectangle with a color. */ +private int +mem2_word_fill_rectangle(gx_device *dev, int x, int y, int w, int h, + gx_color_index color) +{ byte *base; + uint raster; + fit_fill(dev, x, y, w, h); + base = scan_line_base(mdev, y); + raster = mdev->raster; + mem_swap_byte_rect(base, raster, x << 1, w << 1, h, true); + bits_fill_rectangle(base, x << 1, raster, + tile_patterns[color], w << 1, h); + mem_swap_byte_rect(base, raster, x << 1, w << 1, h, true); + return 0; +} + +/* Copy a bitmap. */ +private int +mem2_word_copy_mono(gx_device *dev, + const byte *base, int sourcex, int sraster, gx_bitmap_id id, + int x, int y, int w, int h, gx_color_index zero, gx_color_index one) +{ byte *row; + uint raster; + bool store; + fit_copy(dev, base, sourcex, sraster, id, x, y, w, h); + row = scan_line_base(mdev, y); + raster = mdev->raster; + store = (zero != gx_no_color_index && one != gx_no_color_index); + mem_swap_byte_rect(row, raster, x << 1, w << 1, h, store); + mem_mapped2_copy_mono(dev, base, sourcex, sraster, id, + x, y, w, h, zero, one); + mem_swap_byte_rect(row, raster, x << 1, w << 1, h, false); + return 0; +} + +/* Copy a color bitmap. */ +private int +mem2_word_copy_color(gx_device *dev, + const byte *base, int sourcex, int sraster, gx_bitmap_id id, + int x, int y, int w, int h) +{ int code; + fit_copy(dev, base, sourcex, sraster, id, x, y, w, h); + /* Use monobit copy_mono. */ + /* Patch the width in the device temporarily. */ + dev->width <<= 1; + code = (*dev_proc(&mem_mono_word_device, copy_mono)) + (dev, base, sourcex << 1, sraster, id, + x << 1, y, w << 1, h, (gx_color_index)0, (gx_color_index)1); + /* Restore the correct width. */ + dev->width >>= 1; + return code; +} + +#endif /* !arch_is_big_endian */ diff --git a/pstoraster/gdevm24.c b/pstoraster/gdevm24.c new file mode 100644 index 0000000000..110845525f --- /dev/null +++ b/pstoraster/gdevm24.c @@ -0,0 +1,484 @@ +/* Copyright (C) 1994, 1995, 1996 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to + anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer to + the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given to + you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises is not affiliated with the Free Software Foundation or + the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, + does not depend on any other GNU software. +*/ + +/* gdevm24.c */ +/* 24-bit-per-pixel "memory" (stored bitmap) device */ +#include "memory_.h" +#include "gx.h" +#include "gxdevice.h" +#include "gxdevmem.h" /* semi-public definitions */ +#include "gdevmem.h" /* private definitions */ + +extern dev_proc_strip_copy_rop(mem_gray8_rgb24_strip_copy_rop); /* in gdevmrop.c */ +#define mem_true24_strip_copy_rop mem_gray8_rgb24_strip_copy_rop + +/* ================ Standard (byte-oriented) device ================ */ + +#undef chunk +#define chunk byte + +/* Procedures */ +declare_mem_procs(mem_true24_copy_mono, mem_true24_copy_color, mem_true24_fill_rectangle); +private dev_proc_copy_alpha(mem_true24_copy_alpha); + +/* The device descriptor. */ +const gx_device_memory far_data mem_true24_device = + mem_full_alpha_device("image24", 24, 0, mem_open, + gx_default_rgb_map_rgb_color, gx_default_rgb_map_color_rgb, + mem_true24_copy_mono, mem_true24_copy_color, mem_true24_fill_rectangle, + mem_get_bits, gx_default_map_cmyk_color, mem_true24_copy_alpha, + gx_default_strip_tile_rectangle, mem_true24_strip_copy_rop); + +/* Convert x coordinate to byte offset in scan line. */ +#undef x_to_byte +#define x_to_byte(x) ((x) * 3) + +/* Unpack a color into its bytes. */ +#define declare_unpack_color(r, g, b, color)\ + byte r = (byte)(color >> 16);\ + byte g = (byte)((uint)color >> 8);\ + byte b = (byte)color +/* Put a 24-bit color into the bitmap. */ +#define put3(ptr, r, g, b)\ + (ptr)[0] = r, (ptr)[1] = g, (ptr)[2] = b +/* Put 4 bytes of color into the bitmap. */ +#define putw(ptr, wxyz)\ + *(bits32 *)(ptr) = (wxyz) +/* Load the 3-word 24-bit-color cache. */ +/* Free variables: [m]dev, rgbr, gbrg, brgb. */ +#if arch_is_big_endian +# define set_color24_cache(crgb, r, g, b)\ + mdev->color24.rgbr = rgbr = ((bits32)(crgb) << 8) | (r),\ + mdev->color24.gbrg = gbrg = (rgbr << 8) | (g),\ + mdev->color24.brgb = brgb = (gbrg << 8) | (b),\ + mdev->color24.rgb = (crgb) +#else +# define set_color24_cache(crgb, r, g, b)\ + mdev->color24.rgbr = rgbr =\ + ((bits32)(r) << 24) | ((bits32)(b) << 16) |\ + ((bits16)(g) << 8) | (r),\ + mdev->color24.brgb = brgb = (rgbr << 8) | (b),\ + mdev->color24.gbrg = gbrg = (brgb << 8) | (g),\ + mdev->color24.rgb = (crgb) +#endif + +/* Fill a rectangle with a color. */ +private int +mem_true24_fill_rectangle(gx_device *dev, + int x, int y, int w, int h, gx_color_index color) +{ declare_unpack_color(r, g, b, color); + declare_scan_ptr(dest); + fit_fill_xywh(dev, x, y, w, h); /* don't check w <= 0 or h <= 0 */ + setup_rect(dest); + if ( w >= 5 ) + { if ( r == g && r == b) + { +#if 1 + /* We think we can do better than the library's memset.... */ + int bcntm7 = w * 3 - 7; + register bits32 cword = color | (color << 24); + while ( h-- > 0 ) + { register byte *pptr = dest; + byte *limit = pptr + bcntm7; + /* We want to store full words, but we have to */ + /* guarantee that they are word-aligned. */ + switch ( x & 3 ) + { + case 3: *pptr++ = (byte)cword; + case 2: *pptr++ = (byte)cword; + case 1: *pptr++ = (byte)cword; + case 0: ; + } + /* Even with w = 5, we always store at least */ + /* 3 full words, regardless of the starting x. */ + *(bits32 *)pptr = + ((bits32 *)pptr)[1] = + ((bits32 *)pptr)[2] = cword; + pptr += 12; + while ( pptr < limit ) + { *(bits32 *)pptr = + ((bits32 *)pptr)[1] = cword; + pptr += 8; + } + switch ( pptr - limit ) + { + case 0: pptr[6] = (byte)cword; + case 1: pptr[5] = (byte)cword; + case 2: pptr[4] = (byte)cword; + case 3: *(bits32 *)pptr = cword; + break; + case 4: pptr[2] = (byte)cword; + case 5: pptr[1] = (byte)cword; + case 6: pptr[0] = (byte)cword; + case 7: ; + } + inc_ptr(dest, draster); + } +#else + int bcnt = w * 3; + while ( h-- > 0 ) + { memset(dest, r, bcnt); + inc_ptr(dest, draster); + } +#endif + } + else + { int x3 = -x & 3, ww = w - x3; /* we know ww >= 2 */ + bits32 rgbr, gbrg, brgb; + if ( mdev->color24.rgb == color ) + rgbr = mdev->color24.rgbr, + gbrg = mdev->color24.gbrg, + brgb = mdev->color24.brgb; + else + set_color24_cache(color, r, g, b); + while ( h-- > 0 ) + { register byte *pptr = dest; + int w1 = ww; + switch ( x3 ) + { + case 1: + put3(pptr, r, g, b); + pptr += 3; break; + case 2: + pptr[0] = r; pptr[1] = g; + putw(pptr + 2, brgb); + pptr += 6; break; + case 3: + pptr[0] = r; + putw(pptr + 1, gbrg); + putw(pptr + 5, brgb); + pptr += 9; break; + case 0: + ; + } + while ( w1 >= 4 ) + { putw(pptr, rgbr); + putw(pptr + 4, gbrg); + putw(pptr + 8, brgb); + pptr += 12; + w1 -= 4; + } + switch ( w1 ) + { + case 1: + put3(pptr, r, g, b); + break; + case 2: + putw(pptr, rgbr); + pptr[4] = g; pptr[5] = b; + break; + case 3: + putw(pptr, rgbr); + putw(pptr + 4, gbrg); + pptr[8] = b; + break; + case 0: + ; + } + inc_ptr(dest, draster); + } + } + } + else if ( h > 0 ) /* w < 5 */ + switch ( w ) + { + case 4: + do + { dest[9] = dest[6] = dest[3] = dest[0] = r; + dest[10] = dest[7] = dest[4] = dest[1] = g; + dest[11] = dest[8] = dest[5] = dest[2] = b; + inc_ptr(dest, draster); + } + while ( --h ); + break; + case 3: + do + { dest[6] = dest[3] = dest[0] = r; + dest[7] = dest[4] = dest[1] = g; + dest[8] = dest[5] = dest[2] = b; + inc_ptr(dest, draster); + } + while ( --h ); + break; + case 2: + do + { dest[3] = dest[0] = r; + dest[4] = dest[1] = g; + dest[5] = dest[2] = b; + inc_ptr(dest, draster); + } + while ( --h ); + break; + case 1: + do + { dest[0] = r, dest[1] = g, dest[2] = b; + inc_ptr(dest, draster); + } + while ( --h ); + break; + case 0: + default: + ; + } + return 0; +} + +/* Copy a monochrome bitmap. */ +private int +mem_true24_copy_mono(gx_device *dev, + const byte *base, int sourcex, int sraster, gx_bitmap_id id, + int x, int y, int w, int h, gx_color_index zero, gx_color_index one) +{ const byte *line; + int sbit; + int first_bit; + declare_scan_ptr(dest); + + fit_copy(dev, base, sourcex, sraster, id, x, y, w, h); + setup_rect(dest); + line = base + (sourcex >> 3); + sbit = sourcex & 7; + first_bit = 0x80 >> sbit; + if ( zero != gx_no_color_index ) + { /* Loop for halftones or inverted masks */ + /* (never used). */ + declare_unpack_color(r0, g0, b0, zero); + declare_unpack_color(r1, g1, b1, one); + while ( h-- > 0 ) + { register byte *pptr = dest; + const byte *sptr = line; + register int sbyte = *sptr++; + register int bit = first_bit; + int count = w; + do + { if ( sbyte & bit ) + { if ( one != gx_no_color_index ) + put3(pptr, r1, g1, b1); + } + else + put3(pptr, r0, g0, b0); + pptr += 3; + if ( (bit >>= 1) == 0 ) + bit = 0x80, sbyte = *sptr++; + } + while ( --count > 0 ); + line += sraster; + inc_ptr(dest, draster); + } + } + else if ( one != gx_no_color_index ) + { /* Loop for character and pattern masks. */ + /* This is used heavily. */ + declare_unpack_color(r1, g1, b1, one); + int first_mask = first_bit << 1; + int first_count, first_skip; + if ( sbit + w > 8 ) + first_mask -= 1, + first_count = 8 - sbit; + else + first_mask -= first_mask >> w, + first_count = w; + first_skip = first_count * 3; + while ( h-- > 0 ) + { register byte *pptr = dest; + const byte *sptr = line; + register int sbyte = *sptr++ & first_mask; + int count = w - first_count; + if ( sbyte ) + { register int bit = first_bit; + do + { if ( sbyte & bit ) + put3(pptr, r1, g1, b1); + pptr += 3; + } + while ( (bit >>= 1) & first_mask ); + } + else + pptr += first_skip; + while ( count >= 8 ) + { sbyte = *sptr++; + if ( sbyte & 0xf0 ) + { if ( sbyte & 0x80 ) + put3(pptr, r1, g1, b1); + if ( sbyte & 0x40 ) + put3(pptr + 3, r1, g1, b1); + if ( sbyte & 0x20 ) + put3(pptr + 6, r1, g1, b1); + if ( sbyte & 0x10 ) + put3(pptr + 9, r1, g1, b1); + } + if ( sbyte & 0xf ) + { if ( sbyte & 8 ) + put3(pptr + 12, r1, g1, b1); + if ( sbyte & 4 ) + put3(pptr + 15, r1, g1, b1); + if ( sbyte & 2 ) + put3(pptr + 18, r1, g1, b1); + if ( sbyte & 1 ) + put3(pptr + 21, r1, g1, b1); + } + pptr += 24; + count -= 8; + } + if ( count > 0 ) + { register int bit = 0x80; + sbyte = *sptr++; + do + { if ( sbyte & bit ) + put3(pptr, r1, g1, b1); + pptr += 3; + bit >>= 1; + } + while ( --count > 0 ); + } + line += sraster; + inc_ptr(dest, draster); + } + } + return 0; +} + +/* Copy a color bitmap. */ +private int +mem_true24_copy_color(gx_device *dev, + const byte *base, int sourcex, int sraster, gx_bitmap_id id, + int x, int y, int w, int h) +{ fit_copy(dev, base, sourcex, sraster, id, x, y, w, h); + mem_copy_byte_rect(mdev, base, sourcex, sraster, x, y, w, h); + return 0; +} + +/* Copy an alpha map. */ +private int +mem_true24_copy_alpha(gx_device *dev, const byte *base, int sourcex, + int sraster, gx_bitmap_id id, int x, int y, int w, int h, + gx_color_index color, int depth) +{ const byte *line; + declare_scan_ptr(dest); + declare_unpack_color(r, g, b, color); + + fit_copy(dev, base, sourcex, sraster, id, x, y, w, h); + setup_rect(dest); + line = base; + while ( h-- > 0 ) + { register byte *pptr = dest; + int sx; + + for ( sx = sourcex; sx < sourcex + w; ++sx, pptr += 3 ) + { int alpha2, alpha; + + if ( depth == 2 ) /* map 0 - 3 to 0 - 15 */ + alpha = + ((line[sx >> 2] >> ((3 - (sx & 3)) << 1)) & 3) * 5; + else + alpha2 = line[sx >> 1], + alpha = (sx & 1 ? alpha2 & 0xf : alpha2 >> 4); + if ( alpha == 15 ) + { /* Just write the new color. */ + put3(pptr, r, g, b); + } + else if ( alpha != 0 ) + { /* Blend RGB values. */ +#define make_shade(old, clr, alpha, amax) \ + (old) + (((int)(clr) - (int)(old)) * (alpha) / (amax)) + pptr[0] = make_shade(pptr[0], r, alpha, 15); + pptr[1] = make_shade(pptr[1], g, alpha, 15); + pptr[2] = make_shade(pptr[2], b, alpha, 15); +#undef make_shade + } + } + line += sraster; + inc_ptr(dest, draster); + } + return 0; +} + +/* ================ "Word"-oriented device ================ */ + +/* Note that on a big-endian machine, this is the same as the */ +/* standard byte-oriented-device. */ + +#if !arch_is_big_endian + +/* Procedures */ +declare_mem_procs(mem24_word_copy_mono, mem24_word_copy_color, mem24_word_fill_rectangle); + +/* Here is the device descriptor. */ +const gx_device_memory far_data mem_true24_word_device = + mem_full_device("image24w", 24, 0, mem_open, + gx_default_rgb_map_rgb_color, gx_default_rgb_map_color_rgb, + mem24_word_copy_mono, mem24_word_copy_color, mem24_word_fill_rectangle, + mem_word_get_bits, gx_default_map_cmyk_color, + gx_default_strip_tile_rectangle, gx_no_strip_copy_rop); + +/* Fill a rectangle with a color. */ +private int +mem24_word_fill_rectangle(gx_device *dev, int x, int y, int w, int h, + gx_color_index color) +{ byte *base; + uint raster; + fit_fill(dev, x, y, w, h); + base = scan_line_base(mdev, y); + raster = mdev->raster; + mem_swap_byte_rect(base, raster, x * 24, w * 24, h, true); + mem_true24_fill_rectangle(dev, x, y, w, h, color); + mem_swap_byte_rect(base, raster, x * 24, w * 24, h, false); + return 0; +} + +/* Copy a bitmap. */ +private int +mem24_word_copy_mono(gx_device *dev, + const byte *base, int sourcex, int sraster, gx_bitmap_id id, + int x, int y, int w, int h, gx_color_index zero, gx_color_index one) +{ byte *row; + uint raster; + bool store; + fit_copy(dev, base, sourcex, sraster, id, x, y, w, h); + row = scan_line_base(mdev, y); + raster = mdev->raster; + store = (zero != gx_no_color_index && one != gx_no_color_index); + mem_swap_byte_rect(row, raster, x * 24, w * 24, h, store); + mem_true24_copy_mono(dev, base, sourcex, sraster, id, + x, y, w, h, zero, one); + mem_swap_byte_rect(row, raster, x * 24, w * 24, h, false); + return 0; +} + +/* Copy a color bitmap. */ +private int +mem24_word_copy_color(gx_device *dev, + const byte *base, int sourcex, int sraster, gx_bitmap_id id, + int x, int y, int w, int h) +{ byte *row; + uint raster; + fit_copy(dev, base, sourcex, sraster, id, x, y, w, h); + row = scan_line_base(mdev, y); + raster = mdev->raster; + mem_swap_byte_rect(row, raster, x * 24, w * 24, h, true); + bytes_copy_rectangle(row + x * 3, raster, base + sourcex * 3, sraster, + w * 3, h); + mem_swap_byte_rect(row, raster, x * 24, w * 24, h, false); + return 0; +} + +#endif /* !arch_is_big_endian */ diff --git a/pstoraster/gdevm32.c b/pstoraster/gdevm32.c new file mode 100644 index 0000000000..2e732915e9 --- /dev/null +++ b/pstoraster/gdevm32.c @@ -0,0 +1,233 @@ +/* Copyright (C) 1994, 1995, 1996 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to + anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer to + the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given to + you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises is not affiliated with the Free Software Foundation or + the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, + does not depend on any other GNU software. +*/ + +/* gdevm32.c */ +/* 32-bit-per-pixel "memory" (stored bitmap) device */ +#include "memory_.h" +#include "gx.h" +#include "gxdevice.h" +#include "gxdevmem.h" /* semi-public definitions */ +#include "gdevmem.h" /* private definitions */ + +/* ================ Standard (byte-oriented) device ================ */ + +#undef chunk +#define chunk byte + +/* Procedures */ +declare_mem_procs(mem_true32_copy_mono, mem_true32_copy_color, mem_true32_fill_rectangle); + +/* The device descriptor. */ +const gx_device_memory far_data mem_true32_device = + mem_full_device("image32", 24, 8, mem_open, + gx_default_map_rgb_color, gx_default_map_color_rgb, + mem_true32_copy_mono, mem_true32_copy_color, mem_true32_fill_rectangle, + mem_get_bits, gx_default_cmyk_map_cmyk_color, + gx_default_strip_tile_rectangle, gx_no_strip_copy_rop); + +/* Convert x coordinate to byte offset in scan line. */ +#undef x_to_byte +#define x_to_byte(x) ((x) << 2) + +/* Swap the bytes of a color if needed. */ +#define color_swap_bytes(color)\ + (((color) >> 24) + (((color) >> 8) & 0xff00) +\ + (((color) & 0xff00) << 8) + ((color) << 24)) +#if arch_is_big_endian +# define arrange_bytes(color) (color) +#else +# define arrange_bytes(color) color_swap_bytes(color) +#endif + +/* Fill a rectangle with a color. */ +private int +mem_true32_fill_rectangle(gx_device *dev, + int x, int y, int w, int h, gx_color_index color) +{ bits32 a_color; + declare_scan_ptr(dest); + + fit_fill(dev, x, y, w, h); + a_color = arrange_bytes(color); + setup_rect(dest); + if ( w <= 4 ) + switch ( w ) + { + /*case 0:*/ /* not possible */ +#define dest32 ((bits32 *)dest) + case 1: + do + { dest32[0] = a_color; + inc_ptr(dest, draster); + } + while ( --h > 0 ); + break; + case 2: + do + { dest32[1] = dest32[0] = a_color; + inc_ptr(dest, draster); + } + while ( --h > 0 ); + break; + case 3: + do + { dest32[2] = dest32[1] = dest32[0] = a_color; + inc_ptr(dest, draster); + } + while ( --h > 0 ); + break; + case 4: + do + { dest32[3] = dest32[2] = dest32[1] = dest32[0] = a_color; + inc_ptr(dest, draster); + } + while ( --h > 0 ); + break; + default: /* not possible */ + ; + } + else if ( a_color == 0 ) + do + { memset(dest, 0, w << 2); + inc_ptr(dest, draster); + } + while ( --h > 0 ); + else + do + { bits32 *pptr = dest32; + int cnt = w; + do + { pptr[3] = pptr[2] = pptr[1] = pptr[0] = a_color; + pptr += 4; + } + while ( (cnt -= 4) > 4 ); + do { *pptr++ = a_color; } while ( --cnt > 0 ); + inc_ptr(dest, draster); + } + while ( --h > 0 ); +#undef dest32 + return 0; +} + +/* Copy a monochrome bitmap. */ +private int +mem_true32_copy_mono(gx_device *dev, + const byte *base, int sourcex, int sraster, gx_bitmap_id id, + int x, int y, int w, int h, gx_color_index zero, gx_color_index one) +{ bits32 a_zero = arrange_bytes(zero); + bits32 a_one = arrange_bytes(one); + const byte *line; + int first_bit; + declare_scan_ptr(dest); + fit_copy(dev, base, sourcex, sraster, id, x, y, w, h); + setup_rect(dest); + line = base + (sourcex >> 3); + first_bit = 0x80 >> (sourcex & 7); + while ( h-- > 0 ) + { register bits32 *pptr = (bits32 *)dest; + const byte *sptr = line; + register int sbyte = *sptr++; + register int bit = first_bit; + int count = w; + do + { if ( sbyte & bit ) + { if ( one != gx_no_color_index ) + *pptr = a_one; + } + else + { if ( zero != gx_no_color_index ) + *pptr = a_zero; + } + if ( (bit >>= 1) == 0 ) + bit = 0x80, sbyte = *sptr++; + pptr++; + } + while ( --count > 0 ); + line += sraster; + inc_ptr(dest, draster); + } + return 0; +} + +/* Copy a color bitmap. */ +private int +mem_true32_copy_color(gx_device *dev, + const byte *base, int sourcex, int sraster, gx_bitmap_id id, + int x, int y, int w, int h) +{ fit_copy(dev, base, sourcex, sraster, id, x, y, w, h); + mem_copy_byte_rect(mdev, base, sourcex, sraster, x, y, w, h); + return 0; +} + +/* ================ "Word"-oriented device ================ */ + +/* Note that on a big-endian machine, this is the same as the */ +/* standard byte-oriented-device. */ + +#if !arch_is_big_endian + +/* Procedures */ +declare_mem_procs(mem32_word_copy_mono, mem32_word_copy_color, mem32_word_fill_rectangle); + +/* Here is the device descriptor. */ +const gx_device_memory far_data mem_true32_word_device = + mem_full_device("image32w", 24, 8, mem_open, + gx_default_map_rgb_color, gx_default_map_color_rgb, + mem32_word_copy_mono, mem32_word_copy_color, mem32_word_fill_rectangle, + mem_word_get_bits, gx_default_cmyk_map_cmyk_color, + gx_default_strip_tile_rectangle, gx_no_strip_copy_rop); + +/* Fill a rectangle with a color. */ +private int +mem32_word_fill_rectangle(gx_device *dev, int x, int y, int w, int h, + gx_color_index color) +{ return mem_true32_fill_rectangle(dev, x, y, w, h, + color_swap_bytes(color)); +} + +/* Copy a bitmap. */ +private int +mem32_word_copy_mono(gx_device *dev, + const byte *base, int sourcex, int sraster, gx_bitmap_id id, + int x, int y, int w, int h, gx_color_index zero, gx_color_index one) +{ return mem_true32_copy_mono(dev, base, sourcex, sraster, id, + x, y, w, h, color_swap_bytes(zero), + color_swap_bytes(one)); +} + +/* Copy a color bitmap. */ +private int +mem32_word_copy_color(gx_device *dev, + const byte *base, int sourcex, int sraster, gx_bitmap_id id, + int x, int y, int w, int h) +{ byte *row; + uint raster; + fit_copy(dev, base, sourcex, sraster, id, x, y, w, h); + row = scan_line_base(mdev, y); + raster = mdev->raster; + bytes_copy_rectangle(row + (x << 2), raster, base + (sourcex << 2), + sraster, w << 2, h); + mem_swap_byte_rect(row, raster, x << 5, w << 5, h, false); + return 0; +} + +#endif /* !arch_is_big_endian */ diff --git a/pstoraster/gdevm4.c b/pstoraster/gdevm4.c new file mode 100644 index 0000000000..61b4f637e0 --- /dev/null +++ b/pstoraster/gdevm4.c @@ -0,0 +1,207 @@ +/* Copyright (C) 1992, 1995, 1996 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to + anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer to + the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given to + you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises is not affiliated with the Free Software Foundation or + the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, + does not depend on any other GNU software. +*/ + +/* gdevm4.c */ +/* 4-bit-per-pixel "memory" (stored bitmap) device */ +#include "memory_.h" +#include "gx.h" +#include "gxdevice.h" +#include "gxdevmem.h" /* semi-public definitions */ +#include "gdevmem.h" /* private definitions */ + +/**************** NOTE: copy_rop only works for gray scale ****************/ +extern dev_proc_strip_copy_rop(mem_gray_strip_copy_rop); + +/* ================ Standard (byte-oriented) device ================ */ + +#undef chunk +#define chunk byte +#define fpat(byt) mono_fill_make_pattern(byt) + +/* Procedures */ +declare_mem_procs(mem_mapped4_copy_mono, mem_mapped4_copy_color, mem_mapped4_fill_rectangle); + +/* The device descriptor. */ +const gx_device_memory far_data mem_mapped4_device = + mem_device("image4", 4, 0, + mem_mapped_map_rgb_color, mem_mapped_map_color_rgb, + mem_mapped4_copy_mono, mem_mapped4_copy_color, mem_mapped4_fill_rectangle, + mem_gray_strip_copy_rop); + +/* Convert x coordinate to byte offset in scan line. */ +#undef x_to_byte +#define x_to_byte(x) ((x) >> 1) + +/* Define the 4-bit fill patterns. */ +static const mono_fill_chunk tile_patterns[16] = + { fpat(0x00), fpat(0x11), fpat(0x22), fpat(0x33), + fpat(0x44), fpat(0x55), fpat(0x66), fpat(0x77), + fpat(0x88), fpat(0x99), fpat(0xaa), fpat(0xbb), + fpat(0xcc), fpat(0xdd), fpat(0xee), fpat(0xff) + }; + + +/* Fill a rectangle with a color. */ +private int +mem_mapped4_fill_rectangle(gx_device *dev, + int x, int y, int w, int h, gx_color_index color) +{ fit_fill(dev, x, y, w, h); + bits_fill_rectangle(scan_line_base(mdev, y), x << 2, mdev->raster, + tile_patterns[color], w << 2, h); + return 0; +} + +/* Copy a bitmap. */ +private int +mem_mapped4_copy_mono(gx_device *dev, + const byte *base, int sourcex, int sraster, gx_bitmap_id id, + int x, int y, int w, int h, gx_color_index zero, gx_color_index one) +{ const byte *line; + int first_bit; + byte first_mask, b0, b1; + declare_scan_ptr(dest); + fit_copy(dev, base, sourcex, sraster, id, x, y, w, h); + setup_rect(dest); + line = base + (sourcex >> 3); + first_bit = 0x80 >> (sourcex & 7); + first_mask = (x & 1 ? 0xf : 0xf0); + b0 = ((byte)zero << 4) + (byte)zero; + b1 = ((byte)one << 4) + (byte)one; + while ( h-- > 0 ) + { register byte *pptr = (byte *)dest; + const byte *sptr = line; + register int sbyte = *sptr++; + register int bit = first_bit; + register byte mask = first_mask; + int count = w; + do + { if ( sbyte & bit ) + { if ( one != gx_no_color_index ) + *pptr = (*pptr & ~mask) + (b1 & mask); + } + else + { if ( zero != gx_no_color_index ) + *pptr = (*pptr & ~mask) + (b0 & mask); + } + if ( (bit >>= 1) == 0 ) + bit = 0x80, sbyte = *sptr++; + if ( (mask = ~mask) == 0xf0 ) + pptr++; + } + while ( --count > 0 ); + line += sraster; + inc_ptr(dest, draster); + } + return 0; +} + +/* Copy a color bitmap. */ +private int +mem_mapped4_copy_color(gx_device *dev, + const byte *base, int sourcex, int sraster, gx_bitmap_id id, + int x, int y, int w, int h) +{ int code; + fit_copy(dev, base, sourcex, sraster, id, x, y, w, h); + /* Use monobit copy_mono. */ + /* Patch the width in the device temporarily. */ + dev->width <<= 2; + code = (*dev_proc(&mem_mono_device, copy_mono)) + (dev, base, sourcex << 2, sraster, id, + x << 2, y, w << 2, h, (gx_color_index)0, (gx_color_index)1); + /* Restore the correct width. */ + dev->width >>= 2; + return code; +} + +/* ================ "Word"-oriented device ================ */ + +/* Note that on a big-endian machine, this is the same as the */ +/* standard byte-oriented-device. */ + +#if !arch_is_big_endian + +/* Procedures */ +declare_mem_procs(mem4_word_copy_mono, mem4_word_copy_color, mem4_word_fill_rectangle); + +/* Here is the device descriptor. */ +const gx_device_memory far_data mem_mapped4_word_device = + mem_full_device("image4w", 4, 0, mem_open, + mem_mapped_map_rgb_color, mem_mapped_map_color_rgb, + mem4_word_copy_mono, mem4_word_copy_color, mem4_word_fill_rectangle, + mem_word_get_bits, gx_default_map_cmyk_color, + gx_default_strip_tile_rectangle, gx_no_strip_copy_rop); + +/* Fill a rectangle with a color. */ +private int +mem4_word_fill_rectangle(gx_device *dev, int x, int y, int w, int h, + gx_color_index color) +{ byte *base; + uint raster; + fit_fill(dev, x, y, w, h); + base = scan_line_base(mdev, y); + raster = mdev->raster; + mem_swap_byte_rect(base, raster, x << 2, w << 2, h, true); + bits_fill_rectangle(base, x << 2, raster, + tile_patterns[color], w << 2, h); + mem_swap_byte_rect(base, raster, x << 2, w << 2, h, true); + return 0; +} + +/* Copy a bitmap. */ +private int +mem4_word_copy_mono(gx_device *dev, + const byte *base, int sourcex, int sraster, gx_bitmap_id id, + int x, int y, int w, int h, gx_color_index zero, gx_color_index one) +{ byte *row; + uint raster; + bool store; + fit_copy(dev, base, sourcex, sraster, id, x, y, w, h); + row = scan_line_base(mdev, y); + raster = mdev->raster; + store = (zero != gx_no_color_index && one != gx_no_color_index); + mem_swap_byte_rect(row, raster, x << 2, w << 2, h, store); + mem_mapped4_copy_mono(dev, base, sourcex, sraster, id, + x, y, w, h, zero, one); + mem_swap_byte_rect(row, raster, x << 2, w << 2, h, false); + return 0; +} + +/* Copy a color bitmap. */ +private int +mem4_word_copy_color(gx_device *dev, + const byte *base, int sourcex, int sraster, gx_bitmap_id id, + int x, int y, int w, int h) +{ int code; + fit_copy(dev, base, sourcex, sraster, id, x, y, w, h); + /* Use monobit copy_mono. */ + /* Patch the width in the device temporarily. */ + dev->width <<= 2; + code = (*dev_proc(&mem_mono_word_device, copy_mono)) + (dev, base, sourcex << 2, sraster, id, + x << 2, y, w << 2, h, (gx_color_index)0, (gx_color_index)1); + /* Restore the correct width. */ + dev->width >>= 2; + return code; +} + +#endif /* !arch_is_big_endian */ diff --git a/pstoraster/gdevm8.c b/pstoraster/gdevm8.c new file mode 100644 index 0000000000..e24957d339 --- /dev/null +++ b/pstoraster/gdevm8.c @@ -0,0 +1,225 @@ +/* Copyright (C) 1994, 1995, 1996 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to + anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer to + the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given to + you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises is not affiliated with the Free Software Foundation or + the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, + does not depend on any other GNU software. +*/ + +/* gdevm8.c */ +/* 8-bit-per-pixel "memory" (stored bitmap) device */ +#include "memory_.h" +#include "gx.h" +#include "gxdevice.h" +#include "gxdevmem.h" /* semi-public definitions */ +#include "gdevmem.h" /* private definitions */ + +/**************** NOTE: copy_rop only works for gray scale ****************/ +extern dev_proc_strip_copy_rop(mem_gray8_rgb24_strip_copy_rop); /* in gdevmrop.c */ +#define mem_gray8_strip_copy_rop mem_gray8_rgb24_strip_copy_rop + +/* ================ Standard (byte-oriented) device ================ */ + +#undef chunk +#define chunk byte + +/* Procedures */ +declare_mem_procs(mem_mapped8_copy_mono, mem_mapped8_copy_color, mem_mapped8_fill_rectangle); + +/* The device descriptor. */ +const gx_device_memory far_data mem_mapped8_device = + mem_device("image8", 8, 0, + mem_mapped_map_rgb_color, mem_mapped_map_color_rgb, + mem_mapped8_copy_mono, mem_mapped8_copy_color, mem_mapped8_fill_rectangle, + mem_gray8_strip_copy_rop); + +/* Convert x coordinate to byte offset in scan line. */ +#undef x_to_byte +#define x_to_byte(x) (x) + +/* Fill a rectangle with a color. */ +private int +mem_mapped8_fill_rectangle(gx_device *dev, + int x, int y, int w, int h, gx_color_index color) +{ fit_fill(dev, x, y, w, h); + bytes_fill_rectangle(scan_line_base(mdev, y) + x, mdev->raster, + (byte)color, w, h); + return 0; +} + +/* Copy a monochrome bitmap. */ +/* We split up this procedure because of limitations in the bcc32 compiler. */ +private void mapped8_copy01(P9(chunk *, const byte *, int, int, uint, + int, int, byte, byte)); +private void mapped8_copyN1(P8(chunk *, const byte *, int, int, uint, + int, int, byte)); +private void mapped8_copy0N(P8(chunk *, const byte *, int, int, uint, + int, int, byte)); +private int +mem_mapped8_copy_mono(gx_device *dev, + const byte *base, int sourcex, int sraster, gx_bitmap_id id, + int x, int y, int w, int h, gx_color_index zero, gx_color_index one) +{ const byte *line; + int first_bit; + declare_scan_ptr(dest); + fit_copy(dev, base, sourcex, sraster, id, x, y, w, h); + setup_rect(dest); + line = base + (sourcex >> 3); + first_bit = 0x80 >> (sourcex & 7); +#define is_color(c) ((int)(c) != (int)gx_no_color_index) + if ( is_color(one) ) + { if ( is_color(zero) ) + mapped8_copy01(dest, line, first_bit, sraster, draster, + w, h, (byte)zero, (byte)one); + else + mapped8_copyN1(dest, line, first_bit, sraster, draster, + w, h, (byte)one); + } + else if ( is_color(zero) ) + mapped8_copy0N(dest, line, first_bit, sraster, draster, + w, h, (byte)zero); +#undef is_color + return 0; +} +/* Macros for copy loops */ +#define COPY_BEGIN\ + while ( h-- > 0 )\ + { register byte *pptr = dest;\ + const byte *sptr = line;\ + register int sbyte = *sptr;\ + register uint bit = first_bit;\ + int count = w;\ + do\ + { +#define COPY_END\ + if ( (bit >>= 1) == 0 )\ + bit = 0x80, sbyte = *++sptr;\ + pptr++;\ + }\ + while ( --count > 0 );\ + line += sraster;\ + inc_ptr(dest, draster);\ + } +/* Halftone coloring */ +private void +mapped8_copy01(chunk *dest, const byte *line, int first_bit, + int sraster, uint draster, int w, int h, byte b0, byte b1) +{ COPY_BEGIN + *pptr = (sbyte & bit ? b1 : b0); + COPY_END +} +/* Stenciling */ +private void +mapped8_copyN1(chunk *dest, const byte *line, int first_bit, + int sraster, uint draster, int w, int h, byte b1) +{ COPY_BEGIN + if ( sbyte & bit ) + *pptr = b1; + COPY_END +} +/* Reverse stenciling (probably never used) */ +private void +mapped8_copy0N(chunk *dest, const byte *line, int first_bit, + int sraster, uint draster, int w, int h, byte b0) +{ COPY_BEGIN + if ( !(sbyte & bit) ) + *pptr = b0; + COPY_END +} +#undef COPY_BEGIN +#undef COPY_END + +/* Copy a color bitmap. */ +private int +mem_mapped8_copy_color(gx_device *dev, + const byte *base, int sourcex, int sraster, gx_bitmap_id id, + int x, int y, int w, int h) +{ fit_copy(dev, base, sourcex, sraster, id, x, y, w, h); + mem_copy_byte_rect(mdev, base, sourcex, sraster, x, y, w, h); + return 0; +} + +/* ================ "Word"-oriented device ================ */ + +/* Note that on a big-endian machine, this is the same as the */ +/* standard byte-oriented-device. */ + +#if !arch_is_big_endian + +/* Procedures */ +declare_mem_procs(mem8_word_copy_mono, mem8_word_copy_color, mem8_word_fill_rectangle); + +/* Here is the device descriptor. */ +const gx_device_memory far_data mem_mapped8_word_device = + mem_full_device("image8w", 8, 0, mem_open, + mem_mapped_map_rgb_color, mem_mapped_map_color_rgb, + mem8_word_copy_mono, mem8_word_copy_color, mem8_word_fill_rectangle, + mem_word_get_bits, gx_default_map_cmyk_color, + gx_default_strip_tile_rectangle, gx_no_strip_copy_rop); + +/* Fill a rectangle with a color. */ +private int +mem8_word_fill_rectangle(gx_device *dev, int x, int y, int w, int h, + gx_color_index color) +{ byte *base; + uint raster; + fit_fill(dev, x, y, w, h); + base = scan_line_base(mdev, y); + raster = mdev->raster; + mem_swap_byte_rect(base, raster, x << 3, w << 3, h, true); + bytes_fill_rectangle(base + x, raster, (byte)color, w, h); + mem_swap_byte_rect(base, raster, x << 3, w << 3, h, true); + return 0; +} + +/* Copy a bitmap. */ +private int +mem8_word_copy_mono(gx_device *dev, + const byte *base, int sourcex, int sraster, gx_bitmap_id id, + int x, int y, int w, int h, gx_color_index zero, gx_color_index one) +{ byte *row; + uint raster; + bool store; + fit_copy(dev, base, sourcex, sraster, id, x, y, w, h); + row = scan_line_base(mdev, y); + raster = mdev->raster; + store = (zero != gx_no_color_index && one != gx_no_color_index); + mem_swap_byte_rect(row, raster, x << 3, w << 3, h, store); + mem_mapped8_copy_mono(dev, base, sourcex, sraster, id, + x, y, w, h, zero, one); + mem_swap_byte_rect(row, raster, x << 3, w << 3, h, false); + return 0; +} + +/* Copy a color bitmap. */ +private int +mem8_word_copy_color(gx_device *dev, + const byte *base, int sourcex, int sraster, gx_bitmap_id id, + int x, int y, int w, int h) +{ byte *row; + uint raster; + fit_copy(dev, base, sourcex, sraster, id, x, y, w, h); + row = scan_line_base(mdev, y); + raster = mdev->raster; + mem_swap_byte_rect(row, raster, x << 3, w << 3, h, true); + mem_copy_byte_rect(mdev, base, sourcex, sraster, x, y, w, h); + mem_swap_byte_rect(row, raster, x << 3, w << 3, h, false); + return 0; +} + +#endif /* !arch_is_big_endian */ diff --git a/pstoraster/gdevmem.c b/pstoraster/gdevmem.c new file mode 100644 index 0000000000..ee5c3d75a2 --- /dev/null +++ b/pstoraster/gdevmem.c @@ -0,0 +1,363 @@ +/* Copyright (C) 1989, 1995 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to + anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer to + the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given to + you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises is not affiliated with the Free Software Foundation or + the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, + does not depend on any other GNU software. +*/ + +/* gdevmem.c */ +/* Generic "memory" (stored bitmap) device */ +#include "memory_.h" +#include "gx.h" +#include "gserrors.h" +#include "gsstruct.h" +#include "gxdevice.h" +#include "gxdevmem.h" /* semi-public definitions */ +#include "gdevmem.h" /* private definitions */ + +/* Structure descriptor */ +public_st_device_memory(); + +/* GC procedures */ +#define mptr ((gx_device_memory *)vptr) +private ENUM_PTRS_BEGIN(device_memory_enum_ptrs) { + return (*st_device_forward.enum_ptrs)(vptr, sizeof(gx_device_forward), index-2, pep); + } + case 0: + *pep = (mptr->foreign_bits ? NULL : (void *)mptr->base); + break; + ENUM_STRING_PTR(1, gx_device_memory, palette); +ENUM_PTRS_END +private RELOC_PTRS_BEGIN(device_memory_reloc_ptrs) { + if ( !mptr->foreign_bits ) + { byte *base_old = mptr->base; + long reloc; + int y; + RELOC_PTR(gx_device_memory, base); + reloc = base_old - mptr->base; + for ( y = 0; y < mptr->height; y++ ) + mptr->line_ptrs[y] -= reloc; + /* Relocate line_ptrs, which also points into the data area. */ + mptr->line_ptrs = (byte **)((byte *)mptr->line_ptrs - reloc); + } + RELOC_CONST_STRING_PTR(gx_device_memory, palette); + (*st_device_forward.reloc_ptrs)(vptr, sizeof(gx_device_forward), gcst); +} RELOC_PTRS_END +#undef mptr + +/* Define the palettes for monobit devices. */ +private const byte b_w_palette_string[6] = { 0xff,0xff,0xff, 0,0,0 }; +const gs_const_string mem_mono_b_w_palette = { b_w_palette_string, 6 }; +private const byte w_b_palette_string[6] = { 0,0,0, 0xff,0xff,0xff }; +const gs_const_string mem_mono_w_b_palette = { w_b_palette_string, 6 }; + +/* ------ Generic code ------ */ + +/* Return the appropriate memory device for a given */ +/* number of bits per pixel (0 if none suitable). */ +const gx_device_memory * +gdev_mem_device_for_bits(int bits_per_pixel) +{ switch ( bits_per_pixel ) + { + case 1: return &mem_mono_device; + case 2: return &mem_mapped2_device; + case 4: return &mem_mapped4_device; + case 8: return &mem_mapped8_device; + case 16: return &mem_true16_device; + case 24: return &mem_true24_device; + case 32: return &mem_true32_device; + default: return 0; + } +} +/* Do the same for a word-oriented device. */ +const gx_device_memory * +gdev_mem_word_device_for_bits(int bits_per_pixel) +{ switch ( bits_per_pixel ) + { + case 1: return &mem_mono_word_device; + case 2: return &mem_mapped2_word_device; + case 4: return &mem_mapped4_word_device; + case 8: return &mem_mapped8_word_device; + case 24: return &mem_true24_word_device; + case 32: return &mem_true32_word_device; + default: return 0; + } +} + +/* Make a memory device. */ +/* Note that the default for monobit devices is white = 0, black = 1. */ +void +gs_make_mem_device(gx_device_memory *dev, const gx_device_memory *mdproto, + gs_memory_t *mem, int page_device, gx_device *target) +{ *dev = *mdproto; + dev->memory = mem; + dev->stype = &st_device_memory; + switch ( page_device ) + { + case -1: + dev->std_procs.get_page_device = gx_default_get_page_device; + break; + case 1: + dev->std_procs.get_page_device = gx_page_device_get_page_device; + break; + } + dev->target = target; + if ( target != 0 ) + { /* Forward the color mapping operations to the target. */ + gx_device_forward_color_procs((gx_device_forward *)dev); + } + if ( dev->color_info.depth == 1 ) + gdev_mem_mono_set_inverted(dev, + (target == 0 || + (*dev_proc(target, map_rgb_color)) + (target, (gx_color_value)0, (gx_color_value)0, + (gx_color_value)0) != 0)); +} +/* Make a monobit memory device. This is never a page device. */ +/* Note that white=0, black=1. */ +void +gs_make_mem_mono_device(gx_device_memory *dev, gs_memory_t *mem, + gx_device *target) +{ *dev = mem_mono_device; + dev->memory = mem; + dev->std_procs.get_page_device = gx_default_get_page_device; + mdev->target = target; + gdev_mem_mono_set_inverted(dev, true); +} + + +/* Define whether a monobit memory device is inverted (black=1). */ +void +gdev_mem_mono_set_inverted(gx_device_memory *dev, bool black_is_1) +{ if ( black_is_1 ) + dev->palette = mem_mono_b_w_palette; + else + dev->palette = mem_mono_w_b_palette; +} + +/* Compute the size of the bitmap storage, */ +/* including the space for the scan line pointer table. */ +/* Note that scan lines are padded to a multiple of align_bitmap_mod bytes, */ +/* and additional padding may be needed if the pointer table */ +/* must be aligned to an even larger modulus. */ +private ulong +mem_bitmap_bits_size(const gx_device_memory *dev) +{ return round_up((ulong)dev->height * gdev_mem_raster(dev), + max(align_bitmap_mod, arch_align_ptr_mod)); +} +ulong +gdev_mem_bitmap_size(const gx_device_memory *dev) +{ return mem_bitmap_bits_size(dev) + + (ulong)dev->height * sizeof(byte *); +} + +/* Open a memory device, allocating the data area if appropriate, */ +/* and create the scan line table. */ +private void mem_set_line_ptrs(P3(gx_device_memory *, byte **, byte *)); +int +mem_open(gx_device *dev) +{ if ( mdev->bitmap_memory != 0 ) + { /* Allocate the data now. */ + ulong size = gdev_mem_bitmap_size(mdev); + if ( (uint)size != size ) + return_error(gs_error_limitcheck); + mdev->base = gs_alloc_bytes(mdev->bitmap_memory, (uint)size, + "mem_open"); + if ( mdev->base == 0 ) + return_error(gs_error_VMerror); + mdev->foreign_bits = false; + } +/* + * Macro for adding an offset to a pointer when setting up the + * scan line table. This isn't just pointer arithmetic, because of + * the segmenting considerations discussed in gdevmem.h. + */ +#define huge_ptr_add(base, offset)\ + ((void *)((byte huge *)(base) + (offset))) + mem_set_line_ptrs(mdev, + huge_ptr_add(mdev->base, + mem_bitmap_bits_size(mdev)), + mdev->base); + return 0; +} +/* Set up the scan line pointers of a memory device. */ +/* Sets line_ptrs, base, raster; uses width, height, color_info.depth. */ +private void +mem_set_line_ptrs(gx_device_memory *devm, byte **line_ptrs, byte *base) +{ byte **pptr = devm->line_ptrs = line_ptrs; + byte **pend = pptr + devm->height; + byte *scan_line = devm->base = base; + uint raster = devm->raster = gdev_mem_raster(devm); + + while ( pptr < pend ) + { *pptr++ = scan_line; + scan_line = huge_ptr_add(scan_line, raster); + } +} + +/* Return the initial transformation matrix */ +void +mem_get_initial_matrix(gx_device *dev, gs_matrix *pmat) +{ pmat->xx = mdev->initial_matrix.xx; + pmat->xy = mdev->initial_matrix.xy; + pmat->yx = mdev->initial_matrix.yx; + pmat->yy = mdev->initial_matrix.yy; + pmat->tx = mdev->initial_matrix.tx; + pmat->ty = mdev->initial_matrix.ty; +} + +/* Test whether a device is a memory device */ +bool +gs_device_is_memory(const gx_device *dev) +{ /* We can't just compare the procs, or even an individual proc, */ + /* because we might be tracing. Instead, check the identity of */ + /* the device name. */ + const gx_device_memory *bdev = + gdev_mem_device_for_bits(dev->color_info.depth); + if ( bdev != 0 && bdev->dname == dev->dname ) + return true; + bdev = gdev_mem_word_device_for_bits(dev->color_info.depth); + return (bdev != 0 && bdev->dname == dev->dname); +} + +/* Close a memory device, freeing the data area if appropriate. */ +int +mem_close(gx_device *dev) +{ if ( mdev->bitmap_memory != 0 ) + gs_free_object(mdev->bitmap_memory, mdev->base, "mem_close"); + return 0; +} + +/* Copy a scan line to a client. */ +#undef chunk +#define chunk byte +int +mem_get_bits(gx_device *dev, int y, byte *str, byte **actual_data) +{ byte *src; + if ( y < 0 || y >= dev->height ) + return_error(gs_error_rangecheck); + src = scan_line_base(mdev, y); + if ( actual_data == 0 ) + memcpy(str, src, gx_device_raster(dev, 0)); + else + *actual_data = src; + return 0; +} + +#if !arch_is_big_endian + +/* Swap byte order in a rectangular subset of a bitmap. */ +/* If store = true, assume the rectangle will be overwritten, */ +/* so don't swap any bytes where it doesn't matter. */ +/* The caller has already done a fit_fill or fit_copy. */ +void +mem_swap_byte_rect(byte *base, uint raster, int x, int w, int h, bool store) +{ int xbit = x & 31; + if ( store ) + { if ( xbit + w > 64 ) + { /* Operation spans multiple words. */ + /* Just swap the words at the left and right edges. */ + if ( xbit != 0 ) + mem_swap_byte_rect(base, raster, x, 1, h, false); + x += w - 1; + xbit = x & 31; + if ( xbit == 31 ) + return; + w = 1; + } + } + /* Swap the entire rectangle (or what's left of it). */ + { byte *row = base + ((x >> 5) << 2); + int nw = (xbit + w + 31) >> 5; + int ny; + for ( ny = h; ny > 0; row += raster, --ny ) + { int nx = nw; + bits32 *pw = (bits32 *)row; + do + { bits32 w = *pw; + *pw++ = (w >> 24) + ((w >> 8) & 0xff00) + + ((w & 0xff00) << 8) + (w << 24); + } + while ( --nx); + } + } +} + +/* Copy a word-oriented scan line to the client, swapping bytes as needed. */ +int +mem_word_get_bits(gx_device *dev, int y, byte *str, byte **actual_data) +{ byte *src; + uint raster = gx_device_raster(dev, 0); /* only doing 1 scan line */ + if ( y < 0 || y >= dev->height ) + return_error(gs_error_rangecheck); + src = scan_line_base(mdev, y); + /* We use raster << 3 rather than dev->width so that */ + /* the right thing will happen if depth > 1. */ + mem_swap_byte_rect(src, raster, 0, raster << 3, 1, false); + memcpy(str, src, raster); + if ( actual_data != 0 ) + *actual_data = str; + mem_swap_byte_rect(src, raster, 0, raster << 3, 1, false); + return 0; +} + +#endif /* !arch_is_big_endian */ + +/* Map a r-g-b color to a color index for a mapped color memory device */ +/* (2, 4, or 8 bits per pixel.) */ +/* This requires searching the palette. */ +gx_color_index +mem_mapped_map_rgb_color(gx_device *dev, gx_color_value r, gx_color_value g, + gx_color_value b) +{ byte br = gx_color_value_to_byte(r); + byte bg = gx_color_value_to_byte(g); + byte bb = gx_color_value_to_byte(b); + register const byte *pptr = mdev->palette.data; + int cnt = mdev->palette.size; + const byte *which = 0; /* initialized only to pacify gcc */ + int best = 256*3; + + while ( (cnt -= 3) >= 0 ) + { register int diff = *pptr - br; + if ( diff < 0 ) diff = -diff; + if ( diff < best ) /* quick rejection */ + { int dg = pptr[1] - bg; + if ( dg < 0 ) dg = -dg; + if ( (diff += dg) < best ) /* quick rejection */ + { int db = pptr[2] - bb; + if ( db < 0 ) db = -db; + if ( (diff += db) < best ) + which = pptr, best = diff; + } + } + pptr += 3; + } + return (gx_color_index)((which - mdev->palette.data) / 3); +} + +/* Map a color index to a r-g-b color for a mapped color memory device. */ +int +mem_mapped_map_color_rgb(gx_device *dev, gx_color_index color, + gx_color_value prgb[3]) +{ const byte *pptr = mdev->palette.data + (int)color * 3; + prgb[0] = gx_color_value_from_byte(pptr[0]); + prgb[1] = gx_color_value_from_byte(pptr[1]); + prgb[2] = gx_color_value_from_byte(pptr[2]); + return 0; +} diff --git a/pstoraster/gdevmem.h b/pstoraster/gdevmem.h new file mode 100644 index 0000000000..02db913798 --- /dev/null +++ b/pstoraster/gdevmem.h @@ -0,0 +1,217 @@ +/* Copyright (C) 1991, 1995, 1996 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to + anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer to + the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given to + you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises is not affiliated with the Free Software Foundation or + the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, + does not depend on any other GNU software. +*/ + +/* gdevmem.h */ +/* Private definitions for memory devices. */ + +#include "gsbitops.h" + +/* + The representation for a "memory" device is simply a + contiguous bitmap stored in something like the PostScript + representation, i.e., each scan line (in left-to-right order), padded + to a multiple of bitmap_align_mod bytes, followed immediately by + the next one. + + The representation of strings in the interpreter limits + the size of a string to 64K-1 bytes, which means we can't simply use + a string for the contents of a memory device. + We get around this problem by making the client read out the + contents of a memory device bitmap in pieces. + + On 80x86 PCs running in 16-bit mode, there may be no way to + obtain a contiguous block of storage larger than 64K bytes, + which typically isn't big enough for a full-screen bitmap. + We take the following compromise position: if the PC is running in + native mode (pseudo-segmenting), we limit the bitmap to 64K; + if the PC is running in protected mode (e.g., under MS Windows), + we assume that blocks larger than 64K have sequential segment numbers, + and that the client arranges things so that an individual scan line, + the scan line pointer table, and any single call on a drawing routine + do not cross a segment boundary. + + Even though the scan lines are stored contiguously, we store a table + of their base addresses, because indexing into it is faster than + the multiplication that would otherwise be needed. +*/ + +/* + * Macros for scan line access. + * x_to_byte is different for each number of bits per pixel. + * Note that these macros depend on the definition of chunk: + * each procedure that uses the scanning macros should #define + * (not typedef) chunk as either uint or byte. + */ +#define declare_scan_ptr(ptr) declare_scan_ptr_as(ptr, chunk *) +#define declare_scan_ptr_as(ptr,ptype)\ + register ptype ptr; uint draster +#define setup_rect(ptr) setup_rect_as(ptr, chunk *) +#define setup_rect_as(ptr,ptype)\ + draster = mdev->raster;\ + ptr = (ptype)(scan_line_base(mdev, y) +\ + (x_to_byte(x) & -chunk_align_bytes)) + +/* ------ Generic macros ------ */ + +/* Macro for declaring the essential device procedures. */ +dev_proc_get_initial_matrix(mem_get_initial_matrix); +dev_proc_close_device(mem_close); +#define declare_mem_map_procs(map_rgb_color, map_color_rgb)\ + private dev_proc_map_rgb_color(map_rgb_color);\ + private dev_proc_map_color_rgb(map_color_rgb) +#define declare_mem_procs(copy_mono, copy_color, fill_rectangle)\ + private dev_proc_copy_mono(copy_mono);\ + private dev_proc_copy_color(copy_color);\ + private dev_proc_fill_rectangle(fill_rectangle) + +/* The following are used for all except planar or word-oriented devices. */ +dev_proc_open_device(mem_open); +dev_proc_get_bits(mem_get_bits); +/* The following are for word-oriented devices. */ +#if arch_is_big_endian +# define mem_word_get_bits mem_get_bits +#else +dev_proc_get_bits(mem_word_get_bits); +#endif +/* The following are used for the non-true-color devices. */ +dev_proc_map_rgb_color(mem_mapped_map_rgb_color); +dev_proc_map_color_rgb(mem_mapped_map_color_rgb); + +/* + * Macro for generating the device descriptor. + * Various compilers have problems with the obvious definition + * for max_value, namely: + * (depth >= 8 ? 255 : (1 << depth) - 1) + * I tried changing (1 << depth) to (1 << (depth & 15)) to forestall bogus + * error messages about invalid shift counts, but the H-P compiler chokes + * on this. Since the only values of depth we ever plan to support are + * powers of 2 (and 24), we just go ahead and enumerate them. + */ +#define max_value_gray(rgb_depth, gray_depth)\ + (gray_depth ? (1 << gray_depth) - 1 : max_value_rgb(rgb_depth, 0)) +#define max_value_rgb(rgb_depth, gray_depth)\ + (rgb_depth >= 8 ? 255 : rgb_depth == 4 ? 15 : rgb_depth == 2 ? 3 :\ + rgb_depth == 1 ? 1 : (1 << gray_depth) - 1) +#define mem_full_alpha_device(name, rgb_depth, gray_depth, open, map_rgb_color, map_color_rgb, copy_mono, copy_color, fill_rectangle, get_bits, map_cmyk_color, copy_alpha, strip_tile_rectangle, strip_copy_rop)\ +{ std_device_dci_body(gx_device_memory, 0, name,\ + 0, 0, 72, 72,\ + (rgb_depth ? 3 : 0) + (gray_depth ? 1 : 0), /* num_components */\ + rgb_depth + gray_depth, /* depth */\ + max_value_gray(rgb_depth, gray_depth), /* max_gray */\ + max_value_rgb(rgb_depth, gray_depth), /* max_color */\ + max_value_gray(rgb_depth, gray_depth) + 1, /* dither_grays */\ + max_value_rgb(rgb_depth, gray_depth) + 1 /* dither_colors */\ + ),\ + { open, /* differs */\ + mem_get_initial_matrix,\ + gx_default_sync_output,\ + gx_default_output_page,\ + mem_close,\ + map_rgb_color, /* differs */\ + map_color_rgb, /* differs */\ + fill_rectangle, /* differs */\ + gx_default_tile_rectangle,\ + copy_mono, /* differs */\ + copy_color, /* differs */\ + gx_default_draw_line,\ + get_bits, /* differs */\ + gx_default_get_params,\ + gx_default_put_params,\ + map_cmyk_color, /* differs */\ + gx_forward_get_xfont_procs,\ + gx_forward_get_xfont_device,\ + gx_default_map_rgb_alpha_color,\ + gx_forward_get_page_device,\ + gx_default_get_alpha_bits, /* default is no alpha */\ + copy_alpha, /* differs */\ + gx_default_get_band,\ + gx_default_copy_rop,\ + gx_default_fill_path,\ + gx_default_stroke_path,\ + gx_default_fill_mask,\ + gx_default_fill_trapezoid,\ + gx_default_fill_parallelogram,\ + gx_default_fill_triangle,\ + gx_default_draw_thin_line,\ + gx_default_begin_image,\ + gx_default_image_data,\ + gx_default_end_image,\ + strip_tile_rectangle, /* differs */\ + strip_copy_rop /* differs */\ + },\ + 0, /* target */\ + mem_device_init_private /* see gxdevmem.h */\ +} +#define mem_full_device(name, rgb_depth, gray_depth, open, map_rgb_color, map_color_rgb, copy_mono, copy_color, fill_rectangle, get_bits, map_cmyk_color, strip_tile_rectangle, strip_copy_rop)\ + mem_full_alpha_device(name, rgb_depth, gray_depth, open, map_rgb_color,\ + map_color_rgb, copy_mono, copy_color, fill_rectangle,\ + get_bits, map_cmyk_color, gx_default_copy_alpha,\ + strip_tile_rectangle, strip_copy_rop) +#define mem_device(name, rgb_depth, gray_depth, map_rgb_color, map_color_rgb, copy_mono, copy_color, fill_rectangle, strip_copy_rop)\ + mem_full_device(name, rgb_depth, gray_depth, mem_open, map_rgb_color,\ + map_color_rgb, copy_mono, copy_color, fill_rectangle,\ + mem_get_bits, gx_default_map_cmyk_color,\ + gx_default_strip_tile_rectangle, strip_copy_rop) + +/* Swap a rectangle of bytes, for converting between word- and */ +/* byte-oriented representation. */ +void mem_swap_byte_rect(P6(byte *, uint, int, int, int, bool)); + +/* Copy a rectangle of bytes from a source to a destination. */ +#define mem_copy_byte_rect(mdev, base, sourcex, sraster, x, y, w, h)\ + bytes_copy_rectangle(scan_line_base(mdev, y) + x_to_byte(x),\ + (mdev)->raster,\ + base + x_to_byte(sourcex), sraster,\ + x_to_byte(w), h) + +/* Macro for casting gx_device argument */ +#define mdev ((gx_device_memory *)dev) + +/* ------ Implementations ------ */ + +extern const gx_device_memory far_data mem_mono_device; +extern const gx_device_memory far_data mem_mapped2_device; +extern const gx_device_memory far_data mem_mapped4_device; +extern const gx_device_memory far_data mem_mapped8_device; +extern const gx_device_memory far_data mem_true16_device; +extern const gx_device_memory far_data mem_true24_device; +extern const gx_device_memory far_data mem_true32_device; +extern const gx_device_memory far_data mem_planar_device; +#if arch_is_big_endian +# define mem_mono_word_device mem_mono_device +# define mem_mapped2_word_device mem_mapped2_device +# define mem_mapped4_word_device mem_mapped4_device +# define mem_mapped8_word_device mem_mapped8_device +# define mem_true24_word_device mem_true24_device +# define mem_true32_word_device mem_true32_device +#else +extern const gx_device_memory far_data mem_mono_word_device; +extern const gx_device_memory far_data mem_mapped2_word_device; +extern const gx_device_memory far_data mem_mapped4_word_device; +extern const gx_device_memory far_data mem_mapped8_word_device; +extern const gx_device_memory far_data mem_true24_word_device; +extern const gx_device_memory far_data mem_true32_word_device; +#endif +/* Provide standard palettes for 1-bit devices. */ +extern const gs_const_string mem_mono_b_w_palette; /* black=1, white=0 */ +extern const gs_const_string mem_mono_w_b_palette; /* black=0, white=1 */ diff --git a/pstoraster/gdevmpla.c b/pstoraster/gdevmpla.c new file mode 100644 index 0000000000..66df9173c8 --- /dev/null +++ b/pstoraster/gdevmpla.c @@ -0,0 +1,182 @@ +/* Copyright (C) 1993, 1994 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to + anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer to + the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given to + you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises is not affiliated with the Free Software Foundation or + the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, + does not depend on any other GNU software. +*/ + +/* gdevmpla.c */ +/* Any-depth planar "memory" (stored bitmap) devices */ +#include "memory_.h" +#include "gx.h" +#include "gxdevice.h" +#include "gxdevmem.h" /* semi-public definitions */ +#include "gdevmem.h" /* private definitions */ + +/* + * Planar memory devices store the bits by planes instead of by chunks. + * The plane corresponding to the least significant bit of the color index + * is stored first. + * + * The current implementations are quite inefficient. + * We may improve them someday if anyone cares. + */ + +/* Procedures */ +declare_mem_map_procs(mem_planar_map_rgb_color, mem_planar_map_color_rgb); +declare_mem_procs(mem_planar_copy_mono, mem_planar_copy_color, mem_planar_fill_rectangle); + +/* The device descriptor. */ +/* The instance is public. */ +/* The default instance has depth = 1, but clients may set this */ +/* to other values before opening the device. */ +private dev_proc_open_device(mem_planar_open); +private dev_proc_get_bits(mem_planar_get_bits); +const gx_device_memory far_data mem_planar_device = + mem_full_device("image(planar)", 0, 1, mem_planar_open, + mem_planar_map_rgb_color, mem_planar_map_color_rgb, + mem_planar_copy_mono, mem_planar_copy_color, mem_planar_fill_rectangle, + mem_planar_get_bits, gx_default_map_cmyk_color, + gx_default_strip_tile_rectangle, gx_no_strip_copy_rop); + +/* Open a planar memory device. */ +private int +mem_planar_open(gx_device *dev) +{ /* Temporarily reset the parameters, and call */ + /* the generic open procedure. */ + int depth = dev->color_info.depth; + int height = dev->height; + int code; + + dev->height *= depth; + dev->color_info.depth = 1; + code = mem_open(dev); + dev->height = height; + dev->color_info.depth = depth; + return code; +} + +/* Map a r-g-b color to a color index. */ +private gx_color_index +mem_planar_map_rgb_color(gx_device *dev, gx_color_value r, gx_color_value g, + gx_color_value b) +{ int depth = dev->color_info.depth; + return (*dev_proc(gdev_mem_device_for_bits(depth), map_rgb_color)) + (dev, r, g, b); +} + +/* Map a color index to a r-g-b color. */ +private int +mem_planar_map_color_rgb(gx_device *dev, gx_color_index color, + gx_color_value prgb[3]) +{ int depth = dev->color_info.depth; + return (*dev_proc(gdev_mem_device_for_bits(depth), map_color_rgb)) + (dev, color, prgb); +} + +/* Fill a rectangle with a color. */ +private int +mem_planar_fill_rectangle(gx_device *dev, + int x, int y, int w, int h, gx_color_index color) +{ byte **ptrs = mdev->line_ptrs; + int i; + for ( i = 0; i < dev->color_info.depth; + i++, mdev->line_ptrs += dev->height + ) + (*dev_proc(&mem_mono_device, fill_rectangle))(dev, + x, y, w, h, (color >> i) & 1); + mdev->line_ptrs = ptrs; + return 0; +} + +/* Copy a bitmap. */ +private int +mem_planar_copy_mono(gx_device *dev, + const byte *base, int sourcex, int sraster, gx_bitmap_id id, + int x, int y, int w, int h, gx_color_index zero, gx_color_index one) +{ byte **ptrs = mdev->line_ptrs; + int i; + for ( i = 0; i < dev->color_info.depth; + i++, mdev->line_ptrs += dev->height + ) + (*dev_proc(&mem_mono_device, copy_mono))(dev, + base, sourcex, sraster, id, x, y, w, h, + (zero == gx_no_color_index ? gx_no_color_index : + (zero >> i) & 1), + (one == gx_no_color_index ? gx_no_color_index : + (one >> i) & 1)); + mdev->line_ptrs = ptrs; + return 0; +} + +/* Copy a color bitmap. */ +/* This is very slow and messy. */ +private int +mem_planar_copy_color(gx_device *dev, + const byte *base, int sourcex, int sraster, gx_bitmap_id id, + int x, int y, int w, int h) +{ byte **ptrs = mdev->line_ptrs; + int depth = dev->color_info.depth; + int wleft = w; + int hleft = h; + const byte *srow = base; + int ynext = y; +#define max_w 32 + union _b { + long l[max_w / sizeof(long)]; + byte b[max_w / 8]; + } buf; + + while ( wleft > max_w ) + { mem_planar_copy_color(dev, base, + sourcex + wleft - max_w, sraster, gx_no_bitmap_id, + x + wleft - max_w, y, max_w, h); + wleft -= max_w; + } + for ( ; hleft > 0; + srow += sraster, ynext++, hleft--, + mdev->line_ptrs += dev->height + ) + { int i; + for ( i = 0; i < depth; + i++, mdev->line_ptrs += dev->height + ) + { int sx, bx; + memset(buf.b, 0, sizeof(buf.b)); + for ( sx = 0, bx = sourcex * depth + depth - 1 - i; + sx < w; sx++, bx += depth + ) + if ( srow[bx >> 3] & (0x80 >> (bx & 7)) ) + buf.b[sx >> 3] |= 0x80 >> (sx & 7); + (*dev_proc(&mem_mono_device, copy_mono))(dev, + buf.b, 0, sizeof(buf), gx_no_bitmap_id, + x, ynext, w, 1, + (gx_color_index)0, (gx_color_index)1); + } + mdev->line_ptrs = ptrs; + } + return 0; +} + +/* Copy bits back from a planar memory device. */ +/****** NOT IMPLEMENTED YET ******/ +private int +mem_planar_get_bits(gx_device *dev, int y, byte *str, byte **actual_data) +{ return -1; +} diff --git a/pstoraster/gdevmrop.c b/pstoraster/gdevmrop.c new file mode 100644 index 0000000000..30bb1d0ef7 --- /dev/null +++ b/pstoraster/gdevmrop.c @@ -0,0 +1,1013 @@ +/* Copyright (C) 1995, 1996 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to + anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer to + the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given to + you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises is not affiliated with the Free Software Foundation or + the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, + does not depend on any other GNU software. +*/ + +/* gdevmrop.c */ +/* RasterOp / transparency / render algorithm implementation for */ +/* memory devices */ +#include "memory_.h" +#include "gx.h" +#include "gsbittab.h" +#include "gserrors.h" +#include "gsropt.h" +#include "gxdcolor.h" +#include "gxdevice.h" +#include "gxdevmem.h" +#include "gxdevrop.h" +#include "gdevmrop.h" + +#define mdev ((gx_device_memory *)dev) + +/**************** NOTE: **************** + * The 2- and 4-bit cases don't handle transparency right. + * The 8- and 24-bit cases haven't been tested. + * The 16- and 32-bit cases aren't implemented. + ***************** ****************/ + +/* Forward references */ +private gs_rop3_t gs_transparent_rop(P3(gs_rop3_t rop, bool source_transparent, + bool pattern_transparent)); + +#define chunk byte + +/* Calculate the X offset for a given Y value, */ +/* taking shift into account if necessary. */ +#define x_offset(px, ty, textures)\ + ((textures)->shift == 0 ? (px) :\ + (px) + (ty) / (textures)->rep_height * (textures)->rep_shift) + +/* ---------------- Initialization ---------------- */ + +void +gs_roplib_init(gs_memory_t *mem) +{ /* Replace the default and forwarding copy_rop procedures. */ + gx_default_copy_rop_proc = gx_real_default_copy_rop; + gx_forward_copy_rop_proc = gx_forward_copy_rop; + gx_default_strip_copy_rop_proc = gx_real_default_strip_copy_rop; + gx_forward_strip_copy_rop_proc = gx_forward_strip_copy_rop; +} + +/* ---------------- Debugging aids ---------------- */ + +#ifdef DEBUG + +private void +trace_copy_rop(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) +{ dprintf4("%s: dev=0x%lx(%s) depth=%d\n", + cname, (ulong)dev, dev->dname, dev->color_info.depth); + dprintf4(" source data=0x%lx x=%d raster=%u id=%lu colors=", + (ulong)sdata, sourcex, sraster, (ulong)id); + if ( scolors ) + dprintf2("(%lu,%lu);\n", scolors[0], scolors[1]); + else + dputs("none;\n"); + if ( textures ) + dprintf8(" textures=0x%lx size=%dx%d(%dx%d) raster=%u shift=%d(%d)", + (ulong)textures, textures->size.x, textures->size.y, + textures->rep_width, textures->rep_height, textures->raster, + textures->shift, textures->rep_shift); + else + dputs(" textures=none"); + if ( tcolors ) + dprintf2(" colors=(%lu,%lu)\n", tcolors[0], tcolors[1]); + else + dputs(" colors=none\n"); + dprintf7(" rect=(%d,%d),(%d,%d) phase=(%d,%d) op=0x%x\n", + x, y, x + width, y + height, phase_x, phase_y, + (uint)lop); + if ( gs_debug_c('B') ) + { if ( sdata ) + debug_dump_bitmap(sdata, sraster, height, "source bits"); + if ( textures && textures->data ) + debug_dump_bitmap(textures->data, textures->raster, + textures->size.y, "textures bits"); + } +} + +#endif + +/* ---------------- Monobit RasterOp ---------------- */ + +int +mem_mono_strip_copy_rop(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) +{ gs_rop3_t rop = lop & lop_rop_mask; + gx_strip_bitmap no_texture; + bool invert; + uint draster = mdev->raster; + uint traster; + int line_count; + byte *drow; + const byte *srow; + int ty; + + /* If map_rgb_color isn't the default one for monobit memory */ + /* devices, palette might not be set; set it now if needed. */ + if ( mdev->palette.data == 0 ) + gdev_mem_mono_set_inverted(mdev, + (*dev_proc(dev, map_rgb_color)) + (dev, (gx_color_value)0, + (gx_color_value)0, (gx_color_value)0) + != 0); + invert = mdev->palette.data[0] != 0; + +#ifdef DEBUG + if ( gs_debug_c('b') ) + trace_copy_rop("mem_mono_strip_copy_rop", + dev, sdata, sourcex, sraster, + id, scolors, textures, tcolors, + x, y, width, height, phase_x, phase_y, lop); + if ( gs_debug_c('B') ) + debug_dump_bitmap(scan_line_base(mdev, y), mdev->raster, + height, "initial dest bits"); +#endif + + /* Handle source and destination transparency. */ + rop = gs_transparent_rop(rop, lop & lop_S_transparent, + lop & lop_T_transparent); + + /* + * RasterOp is defined as operating in RGB space; in the monobit + * case, this means black = 0, white = 1. However, most monobit + * devices use the opposite convention. To make this work, + * we must precondition the Boolean operation by swapping the + * order of bits end-for-end and then inverting. + */ + + if ( invert ) + rop = byte_reverse_bits[rop] ^ 0xff; + + /* Modify the raster operation according to the source palette. */ + if ( scolors != 0 ) + { /* Source with palette. */ + switch ( (int)((scolors[1] << 1) + scolors[0]) ) + { + case 0: rop = rop3_know_S_0(rop); break; + case 1: rop = rop3_invert_S(rop); break; + case 2: break; + case 3: rop = rop3_know_S_1(rop); break; + } + } + + /* Modify the raster operation according to the texture palette. */ + if ( tcolors != 0 ) + { /* Texture with palette. */ + switch ( (int)((tcolors[1] << 1) + tcolors[0]) ) + { + case 0: rop = rop3_know_T_0(rop); break; + case 1: rop = rop3_invert_T(rop); break; + case 2: break; + case 3: rop = rop3_know_T_1(rop); break; + } + } + + /* Handle constant source and/or texture. */ + if ( rop3_uses_S(rop) ) + { fit_copy(dev, sdata, sourcex, sraster, id, + x, y, width, height); + } + else + { /* Source is not used; sdata et al may be garbage. */ + sdata = mdev->base; /* arbitrary, as long as all */ + /* accesses are valid */ + sourcex = x; /* guarantee no source skew */ + sraster = 0; + fit_fill(dev, x, y, width, height); + } + if ( !rop3_uses_T(rop) ) + { /* Texture is not used; texture may be garbage. */ + no_texture.data = mdev->base; /* arbitrary */ + no_texture.raster = 0; + no_texture.size.x = width; + no_texture.size.y = height; + no_texture.rep_width = no_texture.rep_height = 1; + no_texture.rep_shift = no_texture.shift = 0; + textures = &no_texture; + } + +#ifdef DEBUG + if_debug1('b', "final rop=0x%x\n", rop); +#endif + + /* Set up transfer parameters. */ + line_count = height; + srow = sdata; + drow = scan_line_base(mdev, y); + traster = textures->raster; + ty = y + phase_y; + + /* Loop over scan lines. */ + for ( ; line_count-- > 0; drow += draster, srow += sraster, ++ty ) + { /* Loop over copies of the tile. */ + int sx = sourcex; + int dx = x; + int w = width; + const byte *trow = + textures->data + (ty % textures->size.y) * traster; + int xoff = x_offset(phase_x, ty, textures); + int nw; + + for ( ; w > 0; sx += nw, dx += nw, w -= nw ) + { int dbit = dx & 7; + int sbit = sx & 7; + int sskew = sbit - dbit; + int tx = (dx + xoff) % textures->rep_width; + int tbit = tx & 7; + int tskew = tbit - dbit; + int left = nw = min(w, textures->size.x - tx); + byte lmask = 0xff >> dbit; + byte rmask = 0xff << (~(dbit + nw - 1) & 7); + byte mask = lmask; + int nx = 8 - dbit; + byte *dptr = drow + (dx >> 3); + const byte *sptr = srow + (sx >> 3); + const byte *tptr = trow + (tx >> 3); + + if ( sskew < 0 ) + --sptr, sskew += 8; + if ( tskew < 0 ) + --tptr, tskew += 8; + for ( ; left > 0; + left -= nx, mask = 0xff, nx = 8, + ++dptr, ++sptr, ++tptr + ) + { byte dbyte = *dptr; +#define fetch1(ptr, skew)\ + (skew ? (ptr[0] << skew) + (ptr[1] >> (8 - skew)) : *ptr) + byte sbyte = fetch1(sptr, sskew); + byte tbyte = fetch1(tptr, tskew); +#undef fetch1 + byte result = + (*rop_proc_tab[rop])(dbyte, sbyte, tbyte); + if ( left <= nx ) + mask &= rmask; + *dptr = (mask == 0xff ? result : + (result & mask) | (dbyte & ~mask)); + } + } + } +#ifdef DEBUG + if ( gs_debug_c('B') ) + debug_dump_bitmap(scan_line_base(mdev, y), mdev->raster, + height, "final dest bits"); +#endif + return 0; +} + +/* ---------------- Fake RasterOp for 2- and 4-bit devices ---------------- */ + +int +mem_gray_strip_copy_rop(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) +{ gx_color_index scolors2[2]; + const gx_color_index *real_scolors = scolors; + gx_color_index tcolors2[2]; + const gx_color_index *real_tcolors = tcolors; + gx_strip_bitmap texture2; + const gx_strip_bitmap *real_texture = textures; + long tdata; + int depth = dev->color_info.depth; + int log2_depth = depth >> 1; /* works for 2, 4 */ + gx_color_index max_pixel = (1 << depth) - 1; + int code; + +#ifdef DEBUG + if ( gs_debug_c('b') ) + trace_copy_rop("mem_gray_strip_copy_rop", + dev, sdata, sourcex, sraster, + id, scolors, textures, tcolors, + x, y, width, height, phase_x, phase_y, lop); +#endif + if ( scolors ) + { /* We can't handle "real" source colors. */ + if ( (scolors[0] | scolors[1]) & ~max_pixel ) + return_error(gs_error_rangecheck); + scolors2[0] = scolors[0] & 1; + scolors2[1] = scolors[1] & 1; + real_scolors = scolors2; + } + if ( textures ) + { texture2 = *textures; + texture2.size.x <<= log2_depth; + texture2.rep_width <<= log2_depth; + texture2.shift <<= log2_depth; + texture2.rep_shift <<= log2_depth; + real_texture = &texture2; + } + if ( tcolors ) + { /* We can't handle monobit textures. */ + if ( tcolors[0] != tcolors[1] ) + return_error(gs_error_rangecheck); + /* For polybit textures with colors other than */ + /* all 0s or all 1s, fabricate the data. */ + if ( tcolors[0] != 0 && tcolors[0] != max_pixel ) + { real_tcolors = 0; + *(byte *)&tdata = (byte)tcolors[0] << (8 - depth); + texture2.data = (byte *)&tdata; + texture2.raster = align_bitmap_mod; + texture2.size.x = texture2.rep_width = depth; + texture2.size.y = texture2.rep_height = 1; + texture2.id = gx_no_bitmap_id; + texture2.shift = texture2.rep_shift = 0; + real_texture = &texture2; + } + else + { tcolors2[0] = tcolors2[1] = tcolors[0] & 1; + real_tcolors = tcolors2; + } + } + dev->width <<= log2_depth; + code = mem_mono_strip_copy_rop(dev, sdata, + (real_scolors == NULL ? sourcex << log2_depth : sourcex), + sraster, id, real_scolors, real_texture, real_tcolors, + x << log2_depth, y, width << log2_depth, height, + phase_x << log2_depth, phase_y, lop); + dev->width >>= log2_depth; + return code; +} + +/* ---------------- RasterOp with 8-bit gray / 24-bit RGB ---------------- */ + +int +mem_gray8_rgb24_strip_copy_rop(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) +{ gs_rop3_t rop = lop & lop_rop_mask; + gx_color_index const_source = gx_no_color_index; + gx_color_index const_texture = gx_no_color_index; + uint draster = mdev->raster; + int line_count; + byte *drow; + int depth = dev->color_info.depth; + int bpp = depth >> 3; /* bytes per pixel, 1 or 3 */ + gx_color_index all_ones = ((gx_color_index)1 << depth) - 1; + gx_color_index strans = + (lop & lop_S_transparent ? all_ones : gx_no_color_index); + gx_color_index ttrans = + (lop & lop_T_transparent ? all_ones : gx_no_color_index); + + /* Check for constant source. */ + if ( scolors != 0 && scolors[0] == scolors[1] ) + { /* Constant source */ + const_source = scolors[0]; + if ( const_source == 0 ) + rop = rop3_know_S_0(rop); + else if ( const_source == all_ones ) + rop = rop3_know_S_1(rop); + } + else if ( !rop3_uses_S(rop) ) + const_source = 0; /* arbitrary */ + + /* Check for constant texture. */ + if ( tcolors != 0 && tcolors[0] == tcolors[1] ) + { /* Constant texture */ + const_texture = tcolors[0]; + if ( const_texture == 0 ) + rop = rop3_know_T_0(rop); + else if ( const_texture == all_ones ) + rop = rop3_know_T_1(rop); + } + else if ( !rop3_uses_T(rop) ) + const_texture = 0; /* arbitrary */ + + /* Adjust coordinates to be in bounds. */ + if ( const_source == gx_no_color_index ) + { fit_copy(dev, sdata, sourcex, sraster, id, + x, y, width, height); + } + else + { fit_fill(dev, x, y, width, height); + } + + /* Set up transfer parameters. */ + line_count = height; + drow = scan_line_base(mdev, y) + x * bpp; + + /* + * There are 18 cases depending on whether each of the source and + * texture is constant, 1-bit, or multi-bit, and on whether the + * depth is 8 or 24 bits. We divide first according to constant + * vs. non-constant, and then according to 1- vs. multi-bit, and + * finally according to pixel depth. This minimizes source code, + * but not necessarily time, since we do some of the divisions + * within 1 or 2 levels of loop. + */ + +#define dbit(base, i) ((base)[(i) >> 3] & (0x80 >> ((i) & 7))) +/* 8-bit */ +#define cbit8(base, i, colors)\ + (dbit(base, i) ? (byte)colors[1] : (byte)colors[0]) +#define rop_body_8()\ + if ( s_pixel == strans || /* So = 0, s_tr = 1 */\ + t_pixel == ttrans /* Po = 0, p_tr = 1 */\ + )\ + continue;\ + *dptr = (*rop_proc_tab[rop])(*dptr, s_pixel, t_pixel) +/* 24-bit */ +#define get24(ptr)\ + (((gx_color_index)(ptr)[0] << 16) | ((gx_color_index)(ptr)[1] << 8) | (ptr)[2]) +#define put24(ptr, pixel)\ + (ptr)[0] = (byte)((pixel) >> 16),\ + (ptr)[1] = (byte)((uint)(pixel) >> 8),\ + (ptr)[2] = (byte)(pixel) +#define cbit24(base, i, colors)\ + (dbit(base, i) ? colors[1] : colors[0]) +#define rop_body_24()\ + if ( s_pixel == strans || /* So = 0, s_tr = 1 */\ + t_pixel == ttrans /* Po = 0, p_tr = 1 */\ + )\ + continue;\ + { gx_color_index d_pixel = get24(dptr);\ + d_pixel = (*rop_proc_tab[rop])(d_pixel, s_pixel, t_pixel);\ + put24(dptr, d_pixel);\ + } + + if ( const_texture != gx_no_color_index ) /**** Constant texture ****/ + { + if ( const_source != gx_no_color_index ) /**** Constant source & texture ****/ + { + for ( ; line_count-- > 0; drow += draster ) + { byte *dptr = drow; + int left = width; + if ( bpp == 1 ) /**** 8-bit destination ****/ +#define s_pixel (byte)const_source +#define t_pixel (byte)const_texture + for ( ; left > 0; ++dptr, --left ) + { rop_body_8(); + } +#undef s_pixel +#undef t_pixel + else /**** 24-bit destination ****/ +#define s_pixel const_source +#define t_pixel const_texture + for ( ; left > 0; dptr += 3, --left ) + { rop_body_24(); + } +#undef s_pixel +#undef t_pixel + } + } + else /**** Data source, const texture ****/ + { const byte *srow = sdata; + for ( ; line_count-- > 0; drow += draster, srow += sraster ) + { byte *dptr = drow; + int left = width; + if ( scolors ) /**** 1-bit source ****/ + { int sx = sourcex; + if ( bpp == 1 ) /**** 8-bit destination ****/ +#define t_pixel (byte)const_texture + for ( ; left > 0; ++dptr, ++sx, --left ) + { byte s_pixel = cbit8(srow, sx, scolors); + rop_body_8(); + } +#undef t_pixel + else /**** 24-bit destination ****/ +#define t_pixel const_texture + for ( ; left > 0; dptr += 3, ++sx, --left ) + { bits32 s_pixel = cbit24(srow, sx, scolors); + rop_body_24(); + } +#undef t_pixel + } + else if ( bpp == 1) /**** 8-bit source & dest ****/ + { const byte *sptr = srow + sourcex; +#define t_pixel (byte)const_texture + for ( ; left > 0; ++dptr, ++sptr, --left ) + { byte s_pixel = *sptr; + rop_body_8(); + } +#undef t_pixel + } + else /**** 24-bit source & dest ****/ + { const byte *sptr = srow + sourcex * 3; +#define t_pixel const_texture + for ( ; left > 0; dptr += 3, sptr += 3, --left ) + { bits32 s_pixel = get24(sptr); + rop_body_24(); + } +#undef t_pixel + } + } + } + } + else if ( const_source != gx_no_color_index ) /**** Const source, data texture ****/ + { uint traster = textures->raster; + int ty = y + phase_y; + + for ( ; line_count-- > 0; drow += draster, ++ty ) + { /* Loop over copies of the tile. */ + int dx = x, w = width, nw; + byte *dptr = drow; + const byte *trow = + textures->data + (ty % textures->size.y) * traster; + int xoff = x_offset(phase_x, ty, textures); + + for ( ; w > 0; dx += nw, w -= nw ) + { int tx = (dx + xoff) % textures->rep_width; + int left = nw = min(w, textures->size.x - tx); + const byte *tptr = trow; + + if ( tcolors ) /**** 1-bit texture ****/ + { if ( bpp == 1 ) /**** 8-bit dest ****/ +#define s_pixel (byte)const_source + for ( ; left > 0; ++dptr, ++tx, --left ) + { byte t_pixel = cbit8(tptr, tx, tcolors); + rop_body_8(); + } +#undef s_pixel + else /**** 24-bit dest ****/ +#define s_pixel const_source + for ( ; left > 0; dptr += 3, ++tx, --left ) + { bits32 t_pixel = cbit24(tptr, tx, tcolors); + rop_body_24(); + } +#undef s_pixel + } + else if ( bpp == 1 ) /**** 8-bit T & D ****/ + { tptr += tx; +#define s_pixel (byte)const_source + for ( ; left > 0; ++dptr, ++tptr, --left ) + { byte t_pixel = *tptr; + rop_body_8(); + } +#undef s_pixel + } + else /**** 24-bit T & D ****/ + { tptr += tx * 3; +#define s_pixel const_source + for ( ; left > 0; dptr += 3, tptr += 3, --left ) + { bits32 t_pixel = get24(tptr); + rop_body_24(); + } +#undef s_pixel + } + } + } + } + else /**** Data source & texture ****/ + { + uint traster = textures->raster; + int ty = y + phase_y; + const byte *srow = sdata; + + /* Loop over scan lines. */ + for ( ; line_count-- > 0; drow += draster, srow += sraster, ++ty ) + { /* Loop over copies of the tile. */ + int sx = sourcex; + int dx = x; + int w = width; + int nw; + byte *dptr = drow; + const byte *trow = + textures->data + (ty % textures->size.y) * traster; + int xoff = x_offset(phase_x, ty, textures); + + for ( ; w > 0; dx += nw, w -= nw ) + { /* Loop over individual pixels. */ + int tx = (dx + xoff) % textures->rep_width; + int left = nw = min(w, textures->size.x - tx); + const byte *tptr = trow; + + /* + * For maximum speed, we should split this loop + * into 7 cases depending on source & texture + * depth: (1,1), (1,8), (1,24), (8,1), (8,8), + * (24,1), (24,24). But since we expect these + * cases to be relatively uncommon, we just + * divide on the destination depth. + */ + if ( bpp == 1 ) /**** 8-bit destination ****/ + { const byte *sptr = srow + sx; + tptr += tx; + for ( ; left > 0; ++dptr, ++sptr, ++tptr, ++sx, ++tx, --left ) + { byte s_pixel = + (scolors ? cbit8(srow, sx, scolors) : *sptr); + byte t_pixel = + (tcolors ? cbit8(tptr, tx, tcolors) : *tptr); + rop_body_8(); + } + } + else /**** 24-bit destination ****/ + { const byte *sptr = srow + sx * 3; + tptr += tx * 3; + for ( ; left > 0; dptr += 3, sptr += 3, tptr += 3, ++sx, ++tx, --left ) + { bits32 s_pixel = + (scolors ? cbit24(srow, sx, scolors) : + get24(sptr)); + bits32 t_pixel = + (tcolors ? cbit24(tptr, tx, tcolors) : + get24(tptr)); + rop_body_24(); + } + } + } + } + } +#undef rop_body_8 +#undef rop_body_24 +#undef dbit +#undef cbit8 +#undef cbit24 + return 0; +} + +/* ---------------- Default copy_rop implementations ---------------- */ + +#undef mdev + +int +gx_real_default_copy_rop(gx_device *dev, + const byte *sdata, int sourcex, uint sraster, gx_bitmap_id id, + const gx_color_index *scolors, + const gx_tile_bitmap *texture, const gx_color_index *tcolors, + int x, int y, int width, int height, + int phase_x, int phase_y, gs_logical_operation_t lop) +{ const gx_strip_bitmap *textures; + gx_strip_bitmap tiles; + + if ( texture == 0 ) + textures = 0; + else + { *(gx_tile_bitmap *)&tiles = *texture; + tiles.rep_shift = tiles.shift = 0; + textures = &tiles; + } + return (*dev_proc(dev, strip_copy_rop)) + (dev, sdata, sourcex, sraster, id, scolors, textures, tcolors, + x, y, width, height, phase_x, phase_y, lop); +} + +int +gx_real_default_strip_copy_rop(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) +{ /* + * The default implementation uses get_bits to read out the + * pixels, the memory device implementation to do the operation, + * and copy_color to write the pixels back. + */ + gs_rop3_t rop = lop & lop_rop_mask; + int depth = dev->color_info.depth; + const gx_device_memory *mdproto = gdev_mem_device_for_bits(depth); + gx_device_memory mdev; + uint draster = gx_device_raster(dev, true); + bool uses_d = rop3_uses_D(rop); + byte *row; + int code; + int py; + +#ifdef DEBUG + if ( gs_debug_c('b') ) + trace_copy_rop("gx_default_strip_copy_rop", + dev, sdata, sourcex, sraster, + id, scolors, textures, tcolors, + x, y, width, height, phase_x, phase_y, lop); +#endif + if ( mdproto == 0 ) + return_error(gs_error_rangecheck); + gs_make_mem_device(&mdev, mdproto, 0, -1, dev); + mdev.width = width; + mdev.height = 1; + mdev.bitmap_memory = &gs_memory_default; + code = (*dev_proc(&mdev, open_device))((gx_device *)&mdev); + if ( code < 0 ) + return code; + row = gs_malloc(1, draster, "copy_rop buffer"); + if ( row == 0 ) + { (*dev_proc(&mdev, close_device))((gx_device *)&mdev); + return_error(gs_error_VMerror); + } + for ( py = y; py < y + height; ++py ) + { byte *data; + + if ( uses_d ) + { code = (*dev_proc(dev, get_bits))(dev, py, row, &data); + if ( code < 0 ) + break; + code = (*dev_proc(&mdev, copy_color))((gx_device *)&mdev, + data, x, draster, gx_no_bitmap_id, + 0, 0, width, 1); + if ( code < 0 ) + return code; + } + code = (*dev_proc(&mdev, strip_copy_rop))((gx_device *)&mdev, + sdata + (py - y) * sraster, sourcex, sraster, + gx_no_bitmap_id, scolors, textures, tcolors, + 0, 0, width, 1, phase_x + x, phase_y + py, + lop); + if ( code < 0 ) + break; + code = (*dev_proc(&mdev, get_bits))((gx_device *)&mdev, 0, row, &data); + if ( code < 0 ) + break; + code = (*dev_proc(dev, copy_color))(dev, + data, 0, draster, gx_no_bitmap_id, + x, py, width, 1); + if ( code < 0 ) + break; + } + gs_free(row, 1, draster, "copy_rop buffer"); + (*dev_proc(&mdev, close_device))((gx_device *)&mdev); + return code; +} + +int +gx_forward_copy_rop(gx_device *dev, + const byte *sdata, int sourcex, uint sraster, gx_bitmap_id id, + const gx_color_index *scolors, + const gx_tile_bitmap *texture, const gx_color_index *tcolors, + int x, int y, int width, int height, + int phase_x, int phase_y, gs_logical_operation_t lop) +{ gx_device *tdev = ((gx_device_forward *)dev)->target; + dev_proc_copy_rop((*proc)); + + if ( tdev == 0 ) + tdev = dev, proc = gx_default_copy_rop; + else + proc = dev_proc(tdev, copy_rop); + return (*proc)(tdev, sdata, sourcex, sraster, id, scolors, + texture, tcolors, x, y, width, height, + phase_x, phase_y, lop); +} + +int +gx_forward_strip_copy_rop(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) +{ gx_device *tdev = ((gx_device_forward *)dev)->target; + dev_proc_strip_copy_rop((*proc)); + + if ( tdev == 0 ) + tdev = dev, proc = gx_default_strip_copy_rop; + else + proc = dev_proc(tdev, strip_copy_rop); + return (*proc)(tdev, sdata, sourcex, sraster, id, scolors, + textures, tcolors, x, y, width, height, + phase_x, phase_y, lop); +} + +int +gx_copy_rop_unaligned(gx_device *dev, + const byte *sdata, int sourcex, uint sraster, gx_bitmap_id id, + const gx_color_index *scolors, + const gx_tile_bitmap *texture, const gx_color_index *tcolors, + int x, int y, int width, int height, + int phase_x, int phase_y, gs_logical_operation_t lop) +{ const gx_strip_bitmap *textures; + gx_strip_bitmap tiles; + + if ( texture == 0 ) + textures = 0; + else + { *(gx_tile_bitmap *)&tiles = *texture; + tiles.rep_shift = tiles.shift = 0; + textures = &tiles; + } + return gx_strip_copy_rop_unaligned + (dev, sdata, sourcex, sraster, id, scolors, textures, tcolors, + x, y, width, height, phase_x, phase_y, lop); +} + +int +gx_strip_copy_rop_unaligned(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) +{ dev_proc_strip_copy_rop((*copy_rop)) = dev_proc(dev, strip_copy_rop); + int depth = (scolors == 0 ? dev->color_info.depth : 1); + int step = sraster & (align_bitmap_mod - 1); + + /* Adjust the origin. */ + if ( sdata != 0 ) + { uint offset = + (uint)(sdata - (const byte *)0) & (align_bitmap_mod - 1); + /* See copy_color above re the following statement. */ + if ( depth == 24 ) + offset += (offset % 3) * + (align_bitmap_mod * (3 - (align_bitmap_mod % 3))); + sdata -= offset; + sourcex += (offset << 3) / depth; + } + + /* Adjust the raster. */ + if ( !step || sdata == 0 || + (scolors != 0 && scolors[0] == scolors[1]) + ) + { /* No adjustment needed. */ + return (*copy_rop)(dev, sdata, sourcex, sraster, id, scolors, + textures, tcolors, x, y, width, height, + phase_x, phase_y, lop); + } + + /* Do the transfer one scan line at a time. */ + { const byte *p = sdata; + int d = sourcex; + int dstep = (step << 3) / depth; + int code = 0; + int i; + + for ( i = 0; i < height && code >= 0; + ++i, p += sraster - step, d += dstep + ) + code = (*copy_rop)(dev, p, d, sraster, gx_no_bitmap_id, scolors, + textures, tcolors, x, y + i, width, 1, + phase_x, phase_y, lop); + return code; + } +} + +/* ---------------- RasterOp texture device ---------------- */ + +public_st_device_rop_texture(); + +/* Device for clipping with a region. */ +private dev_proc_fill_rectangle(rop_texture_fill_rectangle); +private dev_proc_copy_mono(rop_texture_copy_mono); +private dev_proc_copy_color(rop_texture_copy_color); + +/* The device descriptor. */ +private const gx_device_rop_texture far_data gs_rop_texture_device = +{ std_device_std_body(gx_device_rop_texture, 0, "rop source", + 0, 0, 1, 1), + { gx_default_open_device, + NULL, /* get_initial_matrix */ + gx_default_sync_output, + gx_default_output_page, + gx_default_close_device, + NULL, /* map_rgb_color */ + NULL, /* map_color_rgb */ + rop_texture_fill_rectangle, + gx_default_tile_rectangle, + rop_texture_copy_mono, + rop_texture_copy_color, + gx_default_draw_line, + NULL, /* get_bits */ + NULL, /* get_params */ + NULL, /* put_params */ + NULL, /* map_cmyk_color */ + NULL, /* get_xfont_procs */ + NULL, /* get_xfont_device */ + NULL, /* map_rgb_alpha_color */ + NULL, /* get_page_device */ + gx_default_get_alpha_bits, /* (no alpha) */ + gx_no_copy_alpha, /* shouldn't be called */ + NULL, /* get_band */ + gx_no_copy_rop /* shouldn't be called */ + }, + 0, /* target */ + lop_default, /* log_op */ + NULL /* texture */ +}; +#define rtdev ((gx_device_rop_texture *)dev) + +/* Initialize a RasterOp source device. */ +void +gx_make_rop_texture_device(gx_device_rop_texture *dev, gx_device *target, + gs_logical_operation_t log_op, const gx_device_color *texture) +{ *dev = gs_rop_texture_device; + gx_device_forward_fill_in_procs((gx_device_forward *)dev); + dev->color_info = target->color_info; + dev->target = target; + dev->log_op = log_op; + dev->texture = texture; +} + +/* Fill a rectangle */ +private int +rop_texture_fill_rectangle(gx_device *dev, int x, int y, int w, int h, + gx_color_index color) +{ gx_rop_source_t source; + + source.sdata = NULL; + source.sourcex = 0; + source.sraster = 0; + source.id = gx_no_bitmap_id; + source.scolors[0] = source.scolors[1] = color; + return gx_device_color_fill_rectangle(rtdev->texture, + x, y, w, h, rtdev->target, + rtdev->log_op, &source); +} + +/* Copy a monochrome rectangle */ +private int +rop_texture_copy_mono(gx_device *dev, + const byte *data, int sourcex, int raster, gx_bitmap_id id, + int x, int y, int w, int h, + gx_color_index color0, gx_color_index color1) +{ gx_rop_source_t source; + gs_logical_operation_t lop = rtdev->log_op; + + source.sdata = data; + source.sourcex = sourcex; + source.sraster = raster; + source.id = id; + source.scolors[0] = color0; + source.scolors[1] = color1; + /* Adjust the logical operation per transparent colors. */ + if ( color0 == gx_no_color_index ) + lop = rop3_use_D_when_S_0(lop); + else if ( color1 == gx_no_color_index ) + lop = rop3_use_D_when_S_1(lop); + return gx_device_color_fill_rectangle(rtdev->texture, + x, y, w, h, rtdev->target, + lop, &source); +} + +/* Copy a color rectangle */ +private int +rop_texture_copy_color(gx_device *dev, + const byte *data, int sourcex, int raster, gx_bitmap_id id, + int x, int y, int w, int h) +{ gx_rop_source_t source; + + source.sdata = data; + source.sourcex = sourcex; + source.sraster = raster; + source.id = id; + source.scolors[0] = source.scolors[1] = gx_no_color_index; + return gx_device_color_fill_rectangle(rtdev->texture, + x, y, w, h, rtdev->target, + rtdev->log_op, &source); +} + +/* ---------------- Internal routines ---------------- */ + +/* Compute the effective RasterOp for the 1-bit case, */ +/* taking transparency into account. */ +private gs_rop3_t +gs_transparent_rop(gs_rop3_t rop, bool source_transparent, + bool pattern_transparent) +{ /* + * The algorithm for computing an effective RasterOp is presented, + * albeit obfuscated, in the H-P PCL5 technical documentation. + * One applies the original RasterOp to compute an intermediate + * result R, and then computes the final result as + * (R & M) | (D & ~M) where M depends on transparencies as follows: + * s_tr p_tr M + * 0 0 1 + * 0 1 ~So | Po (? Po ?) + * 1 0 So + * 1 1 So & Po + * or equivalently + * So Po M + * 0 0 ~s_tr (? ~s_tr & ~p_tr ?) + * 0 1 ~s_tr + * 1 0 ~p_tr + * 1 1 1 + * The s_tr = 0, p_tr = 1 case seems wrong, but it's clearly + * specified that way in the "PCL 5 Color Technical Reference + * Manual." So and Po are "source opaque" and "pattern opaque"; + * in the uninverted 1-bit case with black = 0, these are + * equivalent to ~S and ~P. + */ +#define So rop3_not(rop3_S) +#define Po rop3_not(rop3_T) + gs_rop3_t mask = + (source_transparent ? + (pattern_transparent ? So & Po : So) : + (pattern_transparent ? ~So | Po : rop3_1)); + return (rop & mask) | (rop3_D & ~mask); +} diff --git a/pstoraster/gdevmrop.h b/pstoraster/gdevmrop.h new file mode 100644 index 0000000000..65699e51c7 --- /dev/null +++ b/pstoraster/gdevmrop.h @@ -0,0 +1,65 @@ +/* Copyright (C) 1995 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to + anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer to + the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given to + you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises is not affiliated with the Free Software Foundation or + the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, + does not depend on any other GNU software. +*/ + +/* gdevmrop.h */ +/* Interfaces to RasterOp implementation */ +/* Requires gxdevmem.h, gsropt.h */ + +/* Define the table of RasterOp implementation procedures. */ +extern const far_data rop_proc rop_proc_tab[256]; + +/* + * 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 PostScript 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; + const gx_device_color *texture; +}; +extern_st(st_device_rop_texture); +#define public_st_device_rop_texture()\ + gs_public_st_suffix_add1(st_device_rop_texture, gx_device_rop_texture,\ + "gx_device_rop_texture", device_rop_texture_enum_ptrs, device_rop_texture_reloc_ptrs,\ + st_device_forward, texture) + +/* 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)); diff --git a/pstoraster/gdevnfwd.c b/pstoraster/gdevnfwd.c new file mode 100644 index 0000000000..c65b6c4013 --- /dev/null +++ b/pstoraster/gdevnfwd.c @@ -0,0 +1,561 @@ +/* Copyright (C) 1996 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to + anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer to + the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given to + you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises is not affiliated with the Free Software Foundation or + the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, + does not depend on any other GNU software. +*/ + +/* gdevnfwd.c */ +/* Null and forwarding device implementation */ +#include "gx.h" +#include "gxdevice.h" + +/* ---------------- Forwarding procedures ---------------- */ + +#define fdev ((gx_device_forward *)dev) + +/* Fill in NULL procedures in a forwarding device procedure record. */ +/* We don't fill in: open_device, close_device, or the lowest-level */ +/* drawing operations. */ +void +gx_device_forward_fill_in_procs(register gx_device_forward *dev) +{ gx_device_set_procs((gx_device *)dev); + /* NOT open_device */ + fill_dev_proc(dev, get_initial_matrix, gx_forward_get_initial_matrix); + fill_dev_proc(dev, sync_output, gx_forward_sync_output); + fill_dev_proc(dev, output_page, gx_forward_output_page); + /* NOT close_device */ + fill_dev_proc(dev, map_rgb_color, gx_forward_map_rgb_color); + fill_dev_proc(dev, map_color_rgb, gx_forward_map_color_rgb); + /* NOT fill_rectangle */ + /* NOT tile_rectangle */ + /* NOT copy_mono */ + /* NOT copy_color */ + /* NOT draw_line (OBSOLETE) */ + fill_dev_proc(dev, get_bits, gx_forward_get_bits); + fill_dev_proc(dev, get_params, gx_forward_get_params); + fill_dev_proc(dev, put_params, gx_forward_put_params); + fill_dev_proc(dev, map_cmyk_color, gx_forward_map_cmyk_color); + fill_dev_proc(dev, get_xfont_procs, gx_forward_get_xfont_procs); + fill_dev_proc(dev, get_xfont_device, gx_forward_get_xfont_device); + fill_dev_proc(dev, map_rgb_alpha_color, gx_forward_map_rgb_alpha_color); + fill_dev_proc(dev, get_page_device, gx_forward_get_page_device); + fill_dev_proc(dev, get_alpha_bits, gx_forward_get_alpha_bits); + /* NOT copy_alpha */ + fill_dev_proc(dev, get_band, gx_forward_get_band); + fill_dev_proc(dev, copy_rop, gx_forward_copy_rop_proc); + fill_dev_proc(dev, fill_path, gx_forward_fill_path); + fill_dev_proc(dev, stroke_path, gx_forward_stroke_path); + fill_dev_proc(dev, fill_mask, gx_forward_fill_mask); + fill_dev_proc(dev, fill_trapezoid, gx_forward_fill_trapezoid); + fill_dev_proc(dev, fill_parallelogram, gx_forward_fill_parallelogram); + fill_dev_proc(dev, fill_triangle, gx_forward_fill_triangle); + fill_dev_proc(dev, draw_thin_line, gx_forward_draw_thin_line); + fill_dev_proc(dev, begin_image, gx_forward_begin_image); + fill_dev_proc(dev, image_data, gx_forward_image_data); + fill_dev_proc(dev, end_image, gx_forward_end_image); + /* NOT strip_tile_rectangle */ + fill_dev_proc(dev, strip_copy_rop, gx_forward_strip_copy_rop_proc); + gx_device_fill_in_procs((gx_device *)dev); +} + +/* Forward the color mapping procedures from a device to its target. */ +void +gx_device_forward_color_procs(gx_device_forward *dev) +{ 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); +} + +void +gx_forward_get_initial_matrix(gx_device *dev, gs_matrix *pmat) +{ gx_device *tdev = fdev->target; + if ( tdev == 0 ) + gx_default_get_initial_matrix(dev, pmat); + else + (*dev_proc(tdev, get_initial_matrix))(tdev, pmat); +} + +int +gx_forward_sync_output(gx_device *dev) +{ gx_device *tdev = fdev->target; + return (tdev == 0 ? gx_default_sync_output(dev) : + (*dev_proc(tdev, sync_output))(tdev)); +} + +int +gx_forward_output_page(gx_device *dev, int num_copies, int flush) +{ gx_device *tdev = fdev->target; + return (tdev == 0 ? gx_default_output_page(dev, num_copies, flush) : + (*dev_proc(tdev, output_page))(tdev, num_copies, flush)); +} + +gx_color_index +gx_forward_map_rgb_color(gx_device *dev, gx_color_value r, gx_color_value g, + gx_color_value b) +{ gx_device *tdev = fdev->target; + return (tdev == 0 ? gx_default_map_rgb_color(dev, r, g, b) : + (*dev_proc(tdev, map_rgb_color))(tdev, r, g, b)); +} + +int +gx_forward_map_color_rgb(gx_device *dev, gx_color_index color, + gx_color_value prgb[3]) +{ gx_device *tdev = fdev->target; + return (tdev == 0 ? gx_default_map_color_rgb(dev, color, prgb) : + (*dev_proc(tdev, map_color_rgb))(tdev, color, prgb)); +} + +int +gx_forward_tile_rectangle(gx_device *dev, const gx_tile_bitmap *tile, + int x, int y, int w, int h, gx_color_index color0, gx_color_index color1, + int px, int py) +{ gx_device *tdev = fdev->target; + dev_proc_tile_rectangle((*proc)); + + if ( tdev == 0 ) + tdev = dev, proc = gx_default_tile_rectangle; + else + proc = dev_proc(tdev, tile_rectangle); + return (*proc)(tdev, tile, x, y, w, h, color0, color1, px, py); +} + +int +gx_forward_get_bits(gx_device *dev, int y, byte *data, byte **actual_data) +{ gx_device *tdev = fdev->target; + return (tdev == 0 ? gx_default_get_bits(dev, y, data, actual_data) : + (*dev_proc(tdev, get_bits))(tdev, y, data, actual_data)); +} + +int +gx_forward_get_params(gx_device *dev, gs_param_list *plist) +{ gx_device *tdev = fdev->target; + return (tdev == 0 ? gx_default_get_params(dev, plist) : + (*dev_proc(tdev, get_params))(tdev, plist)); +} + +int +gx_forward_put_params(gx_device *dev, gs_param_list *plist) +{ gx_device *tdev = fdev->target; + return (tdev == 0 ? gx_default_put_params(dev, plist) : + (*dev_proc(tdev, put_params))(tdev, plist)); +} + +gx_color_index +gx_forward_map_cmyk_color(gx_device *dev, gx_color_value c, gx_color_value m, + gx_color_value y, gx_color_value k) +{ gx_device *tdev = fdev->target; + return (tdev == 0 ? gx_default_map_cmyk_color(dev, c, m, y, k) : + (*dev_proc(tdev, map_cmyk_color))(tdev, c, m, y, k)); +} + +gx_xfont_procs * +gx_forward_get_xfont_procs(gx_device *dev) +{ gx_device *tdev = fdev->target; + return (tdev == 0 ? gx_default_get_xfont_procs(dev) : + (*dev_proc(tdev, get_xfont_procs))(tdev)); +} + +gx_device * +gx_forward_get_xfont_device(gx_device *dev) +{ gx_device *tdev = fdev->target; + return (tdev == 0 ? gx_default_get_xfont_device(dev) : + (*dev_proc(tdev, get_xfont_device))(tdev)); +} + +gx_color_index +gx_forward_map_rgb_alpha_color(gx_device *dev, gx_color_value r, + gx_color_value g, gx_color_value b, gx_color_value alpha) +{ gx_device *tdev = fdev->target; + return (tdev == 0 ? + gx_default_map_rgb_alpha_color(dev, r, g, b, alpha) : + (*dev_proc(tdev, map_rgb_alpha_color))(tdev, r, g, b, alpha)); +} + +gx_device * +gx_forward_get_page_device(gx_device *dev) +{ gx_device *tdev = fdev->target; + return (tdev == 0 ? gx_default_get_page_device(dev) : + (*dev_proc(tdev, get_page_device))(tdev)); +} + +int +gx_forward_get_alpha_bits(gx_device *dev, graphics_object_type type) +{ gx_device *tdev = fdev->target; + return (tdev == 0 ? + gx_default_get_alpha_bits(dev, type) : + (*dev_proc(tdev, get_alpha_bits))(tdev, type)); +} + +int +gx_forward_get_band(gx_device *dev, int y, int *band_start) +{ gx_device *tdev = fdev->target; + return (tdev == 0 ? + gx_default_get_band(dev, y, band_start) : + (*dev_proc(tdev, get_band))(tdev, y, band_start)); +} + +int +gx_forward_fill_path(gx_device *dev, const gs_imager_state *pis, + gx_path *ppath, const gx_fill_params *params, + const gx_drawing_color *pdcolor, const gx_clip_path *pcpath) +{ gx_device *tdev = fdev->target; + dev_proc_fill_path((*proc)); + + if ( tdev == 0 ) + tdev = dev, proc = gx_default_fill_path; + else + proc = dev_proc(tdev, fill_path); + return (*proc)(tdev, pis, ppath, params, pdcolor, pcpath); +} + +int +gx_forward_stroke_path(gx_device *dev, const gs_imager_state *pis, + gx_path *ppath, const gx_stroke_params *params, + const gx_drawing_color *pdcolor, const gx_clip_path *pcpath) +{ gx_device *tdev = fdev->target; + dev_proc_stroke_path((*proc)); + + if ( tdev == 0 ) + tdev = dev, proc = gx_default_stroke_path; + else + proc = dev_proc(tdev, stroke_path); + return (*proc)(tdev, pis, ppath, params, pdcolor, pcpath); +} + +int +gx_forward_fill_mask(gx_device *dev, + const byte *data, int dx, int raster, gx_bitmap_id id, + int x, int y, int w, int h, + const gx_drawing_color *pdcolor, int depth, + gs_logical_operation_t lop, const gx_clip_path *pcpath) +{ gx_device *tdev = fdev->target; + dev_proc_fill_mask((*proc)); + + if ( tdev == 0 ) + tdev = dev, proc = gx_default_fill_mask; + else + proc = dev_proc(tdev, fill_mask); + return (*proc)(dev, data, dx, raster, id, x, y, w, h, pdcolor, depth, + lop, pcpath); +} + +int +gx_forward_fill_trapezoid(gx_device *dev, + const gs_fixed_edge *left, const gs_fixed_edge *right, + fixed ybot, fixed ytop, bool swap_axes, + const gx_drawing_color *pdcolor, gs_logical_operation_t lop) +{ gx_device *tdev = fdev->target; + dev_proc_fill_trapezoid((*proc)); + + if ( tdev == 0 ) + tdev = dev, proc = gx_default_fill_trapezoid; + else + proc = dev_proc(tdev, fill_trapezoid); + return (*proc)(tdev, left, right, ybot, ytop, swap_axes, pdcolor, lop); +} + +int +gx_forward_fill_parallelogram(gx_device *dev, + fixed px, fixed py, fixed ax, fixed ay, fixed bx, fixed by, + const gx_drawing_color *pdcolor, gs_logical_operation_t lop) +{ gx_device *tdev = fdev->target; + dev_proc_fill_parallelogram((*proc)); + + if ( tdev == 0 ) + tdev = dev, proc = gx_default_fill_parallelogram; + else + proc = dev_proc(tdev, fill_parallelogram); + return (*proc)(tdev, px, py, ax, ay, bx, by, pdcolor, lop); +} + +int +gx_forward_fill_triangle(gx_device *dev, + fixed px, fixed py, fixed ax, fixed ay, fixed bx, fixed by, + const gx_drawing_color *pdcolor, gs_logical_operation_t lop) +{ gx_device *tdev = fdev->target; + dev_proc_fill_triangle((*proc)); + + if ( tdev == 0 ) + tdev = dev, proc = gx_default_fill_triangle; + else + proc = dev_proc(tdev, fill_triangle); + return (*proc)(tdev, px, py, ax, ay, bx, by, pdcolor, lop); +} + +int +gx_forward_draw_thin_line(gx_device *dev, + fixed fx0, fixed fy0, fixed fx1, fixed fy1, + const gx_drawing_color *pdcolor, gs_logical_operation_t lop) +{ gx_device *tdev = fdev->target; + dev_proc_draw_thin_line((*proc)); + + if ( tdev == 0 ) + tdev = dev, proc = gx_default_draw_thin_line; + else + proc = dev_proc(tdev, draw_thin_line); + return (*proc)(tdev, fx0, fy0, fx1, fy1, pdcolor, lop); +} + +int +gx_forward_begin_image(gx_device *dev, + const gs_imager_state *pis, const gs_image_t *pim, + gs_image_format_t format, gs_image_shape_t shape, + const gx_drawing_color *pdcolor, const gx_clip_path *pcpath, + gs_memory_t *memory, void **pinfo) +{ gx_device *tdev = fdev->target; + dev_proc_begin_image((*proc)); + + if ( tdev == 0 ) + tdev = dev, proc = gx_default_begin_image; + else + proc = dev_proc(tdev, begin_image); + return (*proc)(tdev, pis, pim, format, shape, pdcolor, pcpath, + memory, pinfo); +} + +int +gx_forward_image_data(gx_device *dev, + void *info, const byte **planes, uint raster, + int x, int y, int width, int height) +{ gx_device *tdev = fdev->target; + dev_proc_image_data((*proc)); + + if ( tdev == 0 ) + tdev = dev, proc = gx_default_image_data; + else + proc = dev_proc(tdev, image_data); + return (*proc)(tdev, info, planes, raster, x, y, width, height); +} + +int +gx_forward_end_image(gx_device *dev, + void *info, bool draw_last) +{ gx_device *tdev = fdev->target; + dev_proc_end_image((*proc)); + + if ( tdev == 0 ) + tdev = dev, proc = gx_default_end_image; + else + proc = dev_proc(tdev, end_image); + return (*proc)(tdev, info, draw_last); +} + +int +gx_forward_strip_tile_rectangle(gx_device *dev, const gx_strip_bitmap *tiles, + int x, int y, int w, int h, gx_color_index color0, gx_color_index color1, + int px, int py) +{ gx_device *tdev = fdev->target; + dev_proc_strip_tile_rectangle((*proc)); + + if ( tdev == 0 ) + tdev = dev, proc = gx_default_strip_tile_rectangle; + else + proc = dev_proc(tdev, strip_tile_rectangle); + return (*proc)(tdev, tiles, x, y, w, h, color0, color1, px, py); +} + +/* ---------------- The null device(s) ---------------- */ + +private dev_proc_fill_rectangle(null_fill_rectangle); +private dev_proc_copy_mono(null_copy_mono); +private dev_proc_copy_color(null_copy_color); +private dev_proc_put_params(null_put_params); +private dev_proc_copy_alpha(null_copy_alpha); +private dev_proc_copy_rop(null_copy_rop); +private dev_proc_fill_path(null_fill_path); +private dev_proc_stroke_path(null_stroke_path); +private dev_proc_fill_trapezoid(null_fill_trapezoid); +private dev_proc_fill_parallelogram(null_fill_parallelogram); +private dev_proc_fill_triangle(null_fill_triangle); +private dev_proc_draw_thin_line(null_draw_thin_line); +private dev_proc_begin_image(null_begin_image); +private dev_proc_image_data(null_image_data); +private dev_proc_end_image(null_end_image); +private dev_proc_strip_copy_rop(null_strip_copy_rop); + +#define null_procs(get_page_device) {\ + gx_default_open_device,\ + gx_forward_get_initial_matrix,\ + gx_default_sync_output,\ + gx_default_output_page,\ + gx_default_close_device,\ + gx_forward_map_rgb_color,\ + gx_forward_map_color_rgb,\ + null_fill_rectangle,\ + gx_default_tile_rectangle,\ + null_copy_mono,\ + null_copy_color,\ + gx_default_draw_line,\ + gx_default_get_bits,\ + gx_forward_get_params,\ + null_put_params,\ + gx_forward_map_cmyk_color,\ + gx_forward_get_xfont_procs,\ + gx_forward_get_xfont_device,\ + gx_forward_map_rgb_alpha_color,\ + get_page_device, /* differs */\ + gx_forward_get_alpha_bits,\ + null_copy_alpha,\ + gx_forward_get_band,\ + null_copy_rop,\ + null_fill_path,\ + null_stroke_path,\ + gx_default_fill_mask,\ + null_fill_trapezoid,\ + null_fill_parallelogram,\ + null_fill_triangle,\ + null_draw_thin_line,\ + null_begin_image,\ + null_image_data,\ + null_end_image,\ + gx_default_strip_tile_rectangle,\ + null_strip_copy_rop,\ +} + +gx_device_null far_data gs_null_device = { + std_device_std_body_open(gx_device_null, 0, "null", + 0, 0, 72, 72), + null_procs(gx_default_get_page_device /* not a page device */), + 0 /* target */ +}; + +gx_device_null far_data gs_nullpage_device = { + std_device_std_body_open(gx_device_null, 0, "nullpage", + 0, 0, 72, 72), + null_procs(gx_page_device_get_page_device /* a page device */), + 0 /* target */ +}; + +private int +null_fill_rectangle(gx_device *dev, int x, int y, int w, int h, + gx_color_index color) +{ return 0; +} +private int +null_copy_mono(gx_device *dev, const byte *data, + int dx, int raster, gx_bitmap_id id, int x, int y, int w, int h, + gx_color_index zero, gx_color_index one) +{ return 0; +} +private int +null_copy_color(gx_device *dev, const byte *data, + int data_x, int raster, gx_bitmap_id id, + int x, int y, int width, int height) +{ return 0; +} +private int +null_put_params(gx_device *dev, gs_param_list *plist) +{ /* We must defeat attempts to reset the size; */ + /* otherwise this is equivalent to gx_forward_put_params. */ + gx_device *tdev = fdev->target; + int code; + + if ( tdev != 0 ) + return (*dev_proc(tdev, put_params))(tdev, plist); + code = gx_default_put_params(dev, plist); + if ( code < 0 ) + return code; + dev->width = dev->height = 0; + return code; +} +private int +null_copy_alpha(gx_device *dev, const byte *data, int data_x, + int raster, gx_bitmap_id id, int x, int y, int width, int height, + gx_color_index color, int depth) +{ return 0; +} +private int +null_copy_rop(gx_device *dev, + const byte *sdata, int sourcex, uint sraster, gx_bitmap_id id, + const gx_color_index *scolors, + const gx_tile_bitmap *texture, const gx_color_index *tcolors, + int x, int y, int width, int height, + int phase_x, int phase_y, gs_logical_operation_t lop) +{ return 0; +} +private int +null_fill_path(gx_device *dev, const gs_imager_state *pis, + gx_path *ppath, const gx_fill_params *params, + const gx_drawing_color *pdcolor, const gx_clip_path *pcpath) +{ return 0; +} +private int +null_stroke_path(gx_device *dev, const gs_imager_state *pis, + gx_path *ppath, const gx_stroke_params *params, + const gx_drawing_color *pdcolor, const gx_clip_path *pcpath) +{ return 0; +} +private int +null_fill_trapezoid(gx_device *dev, + const gs_fixed_edge *left, const gs_fixed_edge *right, + fixed ybot, fixed ytop, bool swap_axes, + const gx_drawing_color *pdcolor, gs_logical_operation_t lop) +{ return 0; +} +private int +null_fill_parallelogram(gx_device *dev, + fixed px, fixed py, fixed ax, fixed ay, fixed bx, fixed by, + const gx_drawing_color *pdcolor, gs_logical_operation_t lop) +{ return 0; +} +private int +null_fill_triangle(gx_device *dev, + fixed px, fixed py, fixed ax, fixed ay, fixed bx, fixed by, + const gx_drawing_color *pdcolor, gs_logical_operation_t lop) +{ return 0; +} +private int +null_draw_thin_line(gx_device *dev, + fixed fx0, fixed fy0, fixed fx1, fixed fy1, + const gx_drawing_color *pdcolor, gs_logical_operation_t lop) +{ return 0; +} +private int +null_begin_image(gx_device *dev, + const gs_imager_state *pis, const gs_image_t *pim, + gs_image_format_t format, gs_image_shape_t shape, + const gx_drawing_color *pdcolor, const gx_clip_path *pcpath, + gs_memory_t *memory, void **pinfo) +{ *pinfo = 0; + return 0; +} +private int +null_image_data(gx_device *dev, + void *info, const byte **planes, uint raster, + int x, int y, int width, int height) +{ return 0; +} +private int +null_end_image(gx_device *dev, + void *info, bool draw_last) +{ return 0; +} +private int +null_strip_copy_rop(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) +{ return 0; +} + +#undef fdev diff --git a/pstoraster/gdevpipe.c b/pstoraster/gdevpipe.c new file mode 100644 index 0000000000..ef6e7fa848 --- /dev/null +++ b/pstoraster/gdevpipe.c @@ -0,0 +1,74 @@ +/* Copyright (C) 1993, 1994 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to + anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer to + the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given to + you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises is not affiliated with the Free Software Foundation or + the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, + does not depend on any other GNU software. +*/ + +/* gdevpipe.c */ +/* %pipe% IODevice */ +#include "errno_.h" +#include "stdio_.h" +#include "string_.h" +#include "gserror.h" +#include "gstypes.h" +#include "gsmemory.h" /* for gxiodev.h */ +#include "stream.h" +#include "gxiodev.h" + +/* popen isn't POSIX-standard, so we declare it here. */ +/* Because of inconsistent (and sometimes incorrect) header files, */ +/* we must omit the argument list. */ +extern FILE *popen( /* P2(const char *, const char *) */ ); +extern int pclose(P1(FILE *)); + +/* The pipe IODevice */ +private iodev_proc_fopen(pipe_fopen); +private iodev_proc_fclose(pipe_fclose); +gx_io_device gs_iodev_pipe = { + "%pipe%", "FileSystem", + { iodev_no_init, iodev_no_open_device, + NULL /*iodev_os_open_file*/, pipe_fopen, pipe_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 */ + +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 */ + /* prototype for popen.... */ + errno = 0; + *pfile = popen((char *)fname, (char *)access); + if ( *pfile == NULL ) + return_error(gs_fopen_errno_to_code(errno)); + if ( rfname != NULL ) + strcpy(rfname, fname); + return 0; +} + +private int +pipe_fclose(gx_io_device *iodev, FILE *file) +{ pclose(file); + return 0; +} diff --git a/pstoraster/gdevprn.c b/pstoraster/gdevprn.c new file mode 100644 index 0000000000..fec60d4002 --- /dev/null +++ b/pstoraster/gdevprn.c @@ -0,0 +1,757 @@ +/* + Copyright 1993-1999 by Easy Software Products. + Copyright (C) 1990, 1995, 1996 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to + anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer to + the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given to + you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises is not affiliated with the Free Software Foundation or + the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, + does not depend on any other GNU software. +*/ + +/* gdevprn.c */ +/* Generic printer driver support */ +#include +#include "ctype_.h" +#include "gdevprn.h" +#include "gp.h" +#include "gsparam.h" +#include "gxclio.h" + +/* ---------------- Standard device procedures ---------------- */ + +/* Macros for casting the pdev argument */ +#define ppdev ((gx_device_printer *)pdev) +#define pmemdev ((gx_device_memory *)pdev) +#define pcldev (&((gx_device_clist *)pdev)->common) + +/* Define the standard printer procedure vector. */ +gx_device_procs prn_std_procs = + prn_procs(gdev_prn_open, gdev_prn_output_page, gdev_prn_close); + +/* ------ Open/close ------ */ + +/* Forward references */ +private int gdev_prn_alloc(P1(gx_device *)); +private int gdev_prn_free(P1(gx_device *)); + +/* Open a generic printer device. */ +/* Specific devices may wish to extend this. */ +int +gdev_prn_open(gx_device *pdev) +{ int code; + ppdev->file = NULL; + code = gdev_prn_alloc(pdev); + if ( code < 0 ) + return code; + if ( ppdev->OpenOutputFile ) + code = gdev_prn_open_printer(pdev, 1); + return code; +} + +/* Allocate buffer space and initialize the device. */ +/* We break this out as a separate procedure so that resetting */ +/* the page dimensions doesn't have to close and reopen the device. */ +private int +gdev_prn_alloc(gx_device *pdev) +{ ulong mem_space; + byte *base = 0; + void *left = 0; + int cache_size; /* Size of tile cache in bytes */ + char *cache_env, /* Cache size environment variable */ + cache_units[255]; /* Cache size units */ + + + memset(ppdev->skip, 0, sizeof(ppdev->skip)); + ppdev->orig_procs = pdev->std_procs; + ppdev->ccfile = ppdev->cbfile = NULL; + + /* + * MRS - reset max_bitmap to the value of RIP_MAX_CACHE as necessary... + */ + + if ((cache_env = getenv("RIP_MAX_CACHE")) != NULL) + { + switch (sscanf(cache_env, "%d%s", &cache_size, cache_units)) + { + case 0 : + cache_size = 32 * 1024 * 1024; + break; + case 1 : + cache_size *= 4 * 256 * 256; + break; + case 2 : + if (tolower(cache_units[0]) == 'g') /* Gigabytes */ + cache_size *= 1024 * 1024 * 1024; + else if (tolower(cache_units[0]) == 'm') /* Megabytes */ + cache_size *= 1024 * 1024; + else if (tolower(cache_units[0]) == 'k') /* Kilobytes */ + cache_size *= 1024; + else if (tolower(cache_units[0]) == 't') /* Tiles */ + cache_size *= 4 * 256 * 256; + break; + } + } + else + cache_size = 32 * 1024 * 1024; + + ppdev->max_bitmap = cache_size; + ppdev->use_buffer_space = cache_size / 8; + + mem_space = gdev_mem_bitmap_size(pmemdev); + + if ( mem_space >= ppdev->max_bitmap || + mem_space != (uint)mem_space || /* too big to allocate */ + (base = (byte *)gs_malloc((uint)mem_space, 1, "printer buffer")) == 0 || /* can't allocate */ + (PRN_MIN_MEMORY_LEFT != 0 && + (left = gs_malloc(PRN_MIN_MEMORY_LEFT, 1, "printer memory left")) == 0) /* not enough left */ + ) + { /* Buffer the image in a command list. */ + uint space; + int code, bcode = 0, ccode = 0; + + /* Release the buffer if we allocated it. */ + gs_free(base, (uint)mem_space, 1, "printer buffer(open)"); + for ( space = ppdev->use_buffer_space; ; ) + { base = (byte *)gs_malloc(space, 1, + "command list buffer"); + if ( base != 0 ) break; + if ( (space >>= 1) < PRN_MIN_BUFFER_SPACE ) + return_error(gs_error_VMerror); /* no hope */ + } +open_c: pcldev->data = base; + pcldev->data_size = space; + pcldev->target = pdev; + pcldev->make_buffer_device = + ppdev->printer_procs.make_buffer_device; + ppdev->buf = base; + ppdev->buffer_space = space; + + /* Try opening the command list, to see if we allocated */ + /* enough buffer space. */ + code = (*gs_clist_device_procs.open_device)((gx_device *)pcldev); + if ( code < 0 ) + { /* If there wasn't enough room, and we haven't */ + /* already shrunk the buffer, try enlarging it. */ + if ( code == gs_error_limitcheck && + space >= ppdev->use_buffer_space + ) + { gs_free(base, space, 1, + "command list buffer(retry open)"); + space <<= 1; + base = (byte *)gs_malloc(space, 1, + "command list buffer(retry open)"); + ppdev->buf = base; + if ( base != 0 ) + goto open_c; + } + /* Fall through with code < 0 */ + } + if ( code < 0 || + (ccode = clist_open_scratch(ppdev->ccfname, &ppdev->ccfile, &gs_memory_default, true)) < 0 || + (bcode = clist_open_scratch(ppdev->cbfname, &ppdev->cbfile, &gs_memory_default, false)) < 0 + ) + { /* Clean up before exiting */ + eprintf3("Problem opening clist: code=%d, bcode=%d, ccode=%d\n", + code, bcode, ccode); + gdev_prn_free(pdev); + return (code < 0 ? code : ccode < 0 ? ccode : bcode); + } + pcldev->cfile = ppdev->ccfile; + pcldev->bfile = ppdev->cbfile; + pcldev->bfile_end_pos = 0; + ppdev->std_procs = gs_clist_device_procs; + } + else + { /* Render entirely in memory. */ + int code; + /* Release the leftover memory. */ + gs_free(left, PRN_MIN_MEMORY_LEFT, 1, + "printer memory left"); + ppdev->buffer_space = 0; + code = (*ppdev->printer_procs.make_buffer_device) + (pmemdev, pdev, pdev->memory, false); + if ( code < 0 ) + { gs_free(base, space, 1, "command list buffer"); + return code; + } + pmemdev->base = base; + } + + /* Synthesize the procedure vector. */ + /* Rendering operations come from the memory or clist device, */ + /* non-rendering come from the printer device. */ +#define copy_proc(p) set_dev_proc(ppdev, p, ppdev->orig_procs.p) + copy_proc(get_initial_matrix); + copy_proc(output_page); + copy_proc(close_device); + copy_proc(map_rgb_color); + copy_proc(map_color_rgb); + copy_proc(get_params); + copy_proc(put_params); + copy_proc(map_cmyk_color); + copy_proc(get_xfont_procs); + copy_proc(get_xfont_device); + copy_proc(map_rgb_alpha_color); + /* All printers are page devices, even if they didn't use the */ + /* standard macros for generating their procedure vectors. */ + set_dev_proc(ppdev, get_page_device, gx_page_device_get_page_device); + copy_proc(get_alpha_bits); +#undef copy_proc + return (*dev_proc(pdev, open_device))(pdev); +} + +/* Generic closing for the printer device. */ +/* Specific devices may wish to extend this. */ +int +gdev_prn_close(gx_device *pdev) +{ gdev_prn_free(pdev); + if ( ppdev->file != NULL ) + { if ( ppdev->file != stdout ) + gp_close_printer(ppdev->file, ppdev->fname); + ppdev->file = NULL; + } + return 0; +} + +/* Free buffer space and related objects, the inverse of alloc. */ +/* Again, we break this out for resetting page dimensions. */ +private int +gdev_prn_free(gx_device *pdev) +{ if ( ppdev->ccfile != NULL ) + { clist_fclose_and_unlink(ppdev->ccfile, ppdev->ccfname); + ppdev->ccfile = NULL; + } + if ( ppdev->cbfile != NULL ) + { clist_fclose_and_unlink(ppdev->cbfile, ppdev->cbfname); + ppdev->cbfile = NULL; + } + if ( ppdev->buffer_space != 0 ) + { /* Free the buffer */ + gs_free(ppdev->buf, (uint)ppdev->buffer_space, 1, + "command list buffer(close)"); + ppdev->buf = 0; + ppdev->buffer_space = 0; + } + else + { /* Free the memory device bitmap */ + gs_free(pmemdev->base, (uint)gdev_mem_bitmap_size(pmemdev), 1, + "printer buffer(close)"); + pmemdev->base = 0; + } + pdev->std_procs = ppdev->orig_procs; + return 0; +} + +/* ------ Get/put parameters ------ */ + +/* Get parameters. Printer devices add several more parameters */ +/* to the default set. */ +int +gdev_prn_get_params(gx_device *pdev, gs_param_list *plist) +{ int code = gx_default_get_params(pdev, plist); + gs_param_string ofns; + + if ( code < 0 ) return code; + + code = (ppdev->NumCopies_set ? + param_write_int(plist, "NumCopies", &ppdev->NumCopies) : + param_write_null(plist, "NumCopies")); + if ( code < 0 ) return code; + + code = param_write_bool(plist, "OpenOutputFile", &ppdev->OpenOutputFile); + if ( code < 0 ) return code; + + if ( ppdev->Duplex_set >= 0 ) + { code = + (ppdev->Duplex_set ? param_write_bool(plist, "Duplex", &ppdev->Duplex) : + param_write_null(plist, "Duplex")); + if ( code < 0 ) return code; + } + + code = param_write_long(plist, "BufferSpace", &ppdev->use_buffer_space); + if ( code < 0 ) return code; + + code = param_write_long(plist, "MaxBitmap", &ppdev->max_bitmap); + if ( code < 0 ) return code; + + ofns.data = (const byte *)ppdev->fname, + ofns.size = strlen(ppdev->fname), + ofns.persistent = false; + return param_write_string(plist, "OutputFile", &ofns); +} + +/* Put parameters. */ +int +gdev_prn_put_params(gx_device *pdev, gs_param_list *plist) +{ int ecode = 0; + int code; + const char _ds *param_name; + bool is_open = pdev->is_open; + int nci = ppdev->NumCopies; + bool ncset = ppdev->NumCopies_set; + bool oof = ppdev->OpenOutputFile; + bool duplex; + int duplex_set = -1; + int width = pdev->width; + int height = pdev->height; + long buffer_space = ppdev->use_buffer_space; + long max_bitmap = ppdev->max_bitmap; + long bsl = buffer_space; + long mbl = max_bitmap; + gs_param_string ofs; + gs_param_dict mdict; + + switch ( code = param_read_int(plist, (param_name = "NumCopies"), &nci) ) + { + case 0: + if ( nci < 0 ) + ecode = gs_error_rangecheck; + else + { ncset = true; + break; + } + goto nce; + default: + if ( (code = param_read_null(plist, param_name)) == 0 ) + { ncset = false; + break; + } + ecode = code; /* can't be 1 */ +nce: param_signal_error(plist, param_name, ecode); + case 1: + break; + } + + switch ( code = param_read_bool(plist, (param_name = "OpenOutputFile"), &oof) ) + { + default: + ecode = code; + param_signal_error(plist, param_name, ecode); + case 0: + case 1: + break; + } + + if ( ppdev->Duplex_set >= 0 ) /* i.e., Duplex is supported */ + switch ( code = param_read_bool(plist, (param_name = "Duplex"), + &duplex) ) + { + case 0: + duplex_set = 1; + break; + default: + if ( (code = param_read_null(plist, param_name)) == 0 ) + { duplex_set = 0; + break; + } + ecode = code; + param_signal_error(plist, param_name, ecode); + case 1: + ; + } + + switch ( code = param_read_long(plist, (param_name = "BufferSpace"), &bsl) ) + { + case 0: + if ( bsl < 10000 ) + ecode = gs_error_rangecheck; + else + break; + goto bse; + default: + ecode = code; +bse: param_signal_error(plist, param_name, ecode); + case 1: + break; + } + + switch ( code = param_read_long(plist, (param_name = "MaxBitmap"), &mbl) ) + { + case 0: + if ( mbl < 10000 ) + ecode = gs_error_rangecheck; + else + break; + goto mbe; + default: + ecode = code; +mbe: param_signal_error(plist, param_name, ecode); + case 1: + break; + } + + switch ( code = param_read_string(plist, (param_name = "OutputFile"), &ofs) ) + { + case 0: + if ( ofs.size >= prn_fname_sizeof ) + ecode = gs_error_limitcheck; + else + { /* Check the validity of any % formats. */ + uint i; + bool pagenum = false; + for ( i = 0; i < ofs.size; ++i ) + if ( ofs.data[i] == '%' ) + { if ( i+1 < ofs.size && ofs.data[i+1] == '%' ) + continue; + if ( pagenum ) /* more than one %, */ + i = ofs.size - 1; /* force error */ + pagenum = true; +sw: if ( ++i == ofs.size ) + { ecode = gs_error_rangecheck; + goto ofe; + } + switch ( ofs.data[i] ) + { + 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: + ecode = gs_error_rangecheck; + goto ofe; + } + } + break; + } + goto ofe; + default: + ecode = code; +ofe: param_signal_error(plist, param_name, ecode); + case 1: + ofs.data = 0; + break; + } + + /* Read InputAttributes and OutputAttributes just for the type */ + /* check and to indicate that they aren't undefined. */ +#define read_media(pname)\ + switch ( code = param_begin_read_dict(plist, (param_name = pname), &mdict, true) )\ + {\ + case 0:\ + param_end_read_dict(plist, pname, &mdict);\ + break;\ + default:\ + ecode = code;\ + param_signal_error(plist, param_name, ecode);\ + case 1:\ + ;\ + } + + read_media("InputAttributes"); + read_media("OutputAttributes"); + + if ( ecode < 0 ) + return ecode; + /* Prevent gx_default_put_params from closing the printer. */ + pdev->is_open = false; + code = gx_default_put_params(pdev, plist); + pdev->is_open = is_open; + if ( code < 0 ) + return code; + + ppdev->NumCopies = nci; + ppdev->NumCopies_set = ncset; + ppdev->OpenOutputFile = oof; + if ( duplex_set >= 0 ) + { ppdev->Duplex = duplex; + ppdev->Duplex_set = duplex_set; + } + /* If necessary, free and reallocate the printer memory. */ + if ( bsl != buffer_space || mbl != max_bitmap || + pdev->width != width || pdev->height != height + ) + { if ( is_open ) + gdev_prn_free(pdev); + ppdev->use_buffer_space = bsl; + ppdev->max_bitmap = mbl; + if ( is_open ) + { ecode = code = gdev_prn_alloc(pdev); + if ( code < 0 ) + { /* Try to put things back as they were. */ + ppdev->use_buffer_space = buffer_space; + ppdev->max_bitmap = max_bitmap; + gx_device_set_width_height(pdev, + width, height); + code = gdev_prn_alloc(pdev); + if ( code < 0 ) + { /* Disaster! We can't get back. */ + pdev->is_open = false; + return code; + } + return ecode; + } + } + } + if ( ofs.data != 0 && + bytes_compare(ofs.data, ofs.size, + (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); + ppdev->file = NULL; + memcpy(ppdev->fname, ofs.data, ofs.size); + ppdev->fname[ofs.size] = 0; + } + + /* If the device is open and OpenOutputFile is true, */ + /* open the OutputFile now. (If the device isn't open, */ + /* this will happen when it is opened.) */ + if ( pdev->is_open && oof ) + { code = gdev_prn_open_printer(pdev, 1); + if ( code < 0 ) + return code; + } + + return 0; +} + +/* Put InputAttributes and OutputAttributes. */ +int +gdev_prn_input_page_size(int index, gs_param_dict *pdict, + floatp width_points, floatp height_points) +{ input_media media; + media.PageSize[0] = width_points; + media.PageSize[1] = height_points; + media.MediaColor = 0; + media.MediaWeight = 0; + media.MediaType = 0; + return gdev_prn_input_media(index, pdict, &media); +} +private int +finish_media(gs_param_list *mlist, gs_param_name key, const char *media_type) +{ int code = 0; + if ( media_type != 0 ) + { gs_param_string as; + param_string_from_string(as, media_type); + code = param_write_string(mlist, key, &as); + } + return code; +} +int +gdev_prn_input_media(int index, gs_param_dict *pdict, const input_media *pim) +{ char key[25]; + gs_param_dict mdict; + int code; + gs_param_string as; + + sprintf(key, "%d", index); + mdict.size = 4; + code = param_begin_write_dict(pdict->list, key, &mdict, false); + if ( code < 0 ) + return code; + if ( pim->PageSize[0] != 0 && pim->PageSize[1] != 0 ) + { gs_param_float_array psa; + psa.data = pim->PageSize, psa.size = 2, psa.persistent = false; + code = param_write_float_array(mdict.list, "PageSize", + &psa); + if ( code < 0 ) + return code; + } + if ( pim->MediaColor != 0 ) + { param_string_from_string(as, pim->MediaColor); + code = param_write_string(mdict.list, "MediaColor", + &as); + if ( code < 0 ) + return code; + } + if ( pim->MediaWeight != 0 ) + { /* We do the following silly thing in order to avoid */ + /* having to work around the 'const' in the arg list. */ + float weight = pim->MediaWeight; + code = param_write_float(mdict.list, "MediaWeight", + &weight); + if ( code < 0 ) + return code; + } + code = finish_media(mdict.list, "MediaType", pim->MediaType); + if ( code < 0 ) + return code; + return param_end_write_dict(pdict->list, key, &mdict); +} +int +gdev_prn_output_media(int index, gs_param_dict *pdict, const output_media *pom) +{ char key[25]; + gs_param_dict mdict; + int code; + + sprintf(key, "%d", index); + mdict.size = 4; + code = param_begin_write_dict(pdict->list, key, &mdict, false); + if ( code < 0 ) + return code; + code = finish_media(mdict.list, "OutputType", pom->OutputType); + if ( code < 0 ) + return code; + return param_end_write_dict(pdict->list, key, &mdict); +} + +/* ------ Others ------ */ + +/* Generic routine to send the page to the printer. */ +int +gdev_prn_output_page(gx_device *pdev, int num_copies, int flush) +{ int code, outcode, closecode, errcode; + + if ( num_copies > 0 ) + { code = gdev_prn_open_printer(pdev, 1); + if ( code < 0 ) + return code; + + /* Print the accumulated page description. */ + outcode = + (*ppdev->printer_procs.print_page_copies)(ppdev, + ppdev->file, + num_copies); + if (ppdev->file != NULL) + errcode = (ferror(ppdev->file) ? gs_error_ioerror : 0); + else + errcode = 0; + + closecode = gdev_prn_close_printer(pdev); + } + else + code = outcode = closecode = errcode = 0; + + if ( ppdev->buffer_space ) /* reinitialize clist for writing */ + code = (*gs_clist_device_procs.output_page)(pdev, num_copies, flush); + + if ( outcode < 0 ) + return outcode; + if ( errcode < 0 ) + return_error(errcode); + if ( closecode < 0 ) + return closecode; + return code; +} + +/* Print multiple copies of a page by calling print_page multiple times. */ +int +gx_default_print_page_copies(gx_device_printer *pdev, FILE *prn_stream, + int num_copies) +{ int i = num_copies; + int code = 0; + while ( code >= 0 && i-- > 0 ) + code = (*pdev->printer_procs.print_page)(pdev, prn_stream); + return code; +} + +/* ---------------- Driver services ---------------- */ + +/* Return the number of scan lines that should actually be passed */ +/* to the device. */ +int +gdev_prn_print_scan_lines(gx_device *pdev) +{ int height = pdev->height; + gs_matrix imat; + float yscale; + int top, bottom, offset, end; + + (*dev_proc(pdev, get_initial_matrix))(pdev, &imat); + yscale = imat.yy * 72.0; /* Y dpi, may be negative */ + top = (int)(dev_t_margin(pdev) * yscale); + bottom = (int)(dev_b_margin(pdev) * yscale); + offset = (int)(dev_y_offset(pdev) * yscale); + if ( yscale < 0 ) + { /* Y=0 is top of page */ + end = -offset + height + bottom; + } + else + { /* Y=0 is bottom of page */ + end = offset + height - top; + } + return min(height, end); +} + +/* Open the current page for printing. */ +int +gdev_prn_open_printer(gx_device *pdev, int binary_mode) +{ char *fname = ppdev->fname; + char pfname[prn_fname_sizeof + 20]; + char *fchar = fname; + long count1 = ppdev->PageCount + 1; + + while ( (fchar = strchr(fchar, '%')) != NULL ) + { if ( *++fchar == '%' ) + { ++fchar; + continue; + } + while ( !isalpha(*fchar) ) + ++fchar; + sprintf(pfname, fname, + (*fchar == 'l' ? count1 : (int)count1)); + fname = pfname; + break; + } + if ( ppdev->file == NULL ) + { if ( !strcmp(fname, "-") ) + ppdev->file = stdout; + else + { ppdev->file = gp_open_printer(fname, binary_mode); + if ( ppdev->file == NULL ) + return_error(gs_error_invalidfileaccess); + } + ppdev->file_is_new = true; + } + else + ppdev->file_is_new = false; + return 0; +} + +/* Copy a scan line from the buffer to the printer. */ +int +gdev_prn_get_bits(gx_device_printer *pdev, int y, byte *str, byte **actual_data) +{ int code = (*dev_proc(pdev, get_bits))((gx_device *)pdev, y, str, actual_data); + uint line_size = gdev_prn_raster(pdev); + int last_bits = -(pdev->width * pdev->color_info.depth) & 7; + if ( code < 0 ) return code; + if ( last_bits != 0 ) + { byte *dest = (actual_data != 0 ? *actual_data : str); + dest[line_size - 1] &= 0xff << last_bits; + } + return 0; +} +/* Copy scan lines to a buffer. Return the number of scan lines, */ +/* or <0 if error. */ +int +gdev_prn_copy_scan_lines(gx_device_printer *pdev, int y, byte *str, uint size) +{ uint line_size = gdev_prn_raster(pdev); + int count = size / line_size; + int i; + byte *dest = str; + count = min(count, pdev->height - y); + for ( i = 0; i < count; i++, dest += line_size ) + { int code = gdev_prn_get_bits(pdev, y + i, dest, NULL); + if ( code < 0 ) return code; + } + return count; +} + +/* Close the current page. */ +int +gdev_prn_close_printer(gx_device *pdev) +{ if ( strchr(ppdev->fname, '%') ) /* file per page */ + { gp_close_printer(ppdev->file, ppdev->fname); + ppdev->file = NULL; + } + return 0; +} diff --git a/pstoraster/gdevprn.h b/pstoraster/gdevprn.h new file mode 100644 index 0000000000..5206d2a2e0 --- /dev/null +++ b/pstoraster/gdevprn.h @@ -0,0 +1,418 @@ +/* + Copyright 1993-1999 by Easy Software Products. + Copyright (C) 1989, 1995, 1996 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to + anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer to + the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given to + you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises is not affiliated with the Free Software Foundation or + the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, + does not depend on any other GNU software. +*/ + +/* gdevprn.h */ +/* Common header file for memory-buffered printers */ + +#ifndef gdevprn_INCLUDED +# define gdevprn_INCLUDED + +#include "memory_.h" +#include "string_.h" +#include "gx.h" +#include "gserrors.h" +#include "gsmatrix.h" /* for gxdevice.h */ +#include "gsutil.h" /* for memflip8x8 */ +#include "gxdevice.h" +#include "gxdevmem.h" +#include "gxclist.h" +#include "gsparam.h" + +/* Define the page size parameters. */ +/* U.S. letter paper (8.5" x 11"). */ +#define DEFAULT_WIDTH_10THS_US_LETTER 85 +#define DEFAULT_HEIGHT_10THS_US_LETTER 110 +/* A4 paper (210mm x 297mm). The dimensions are off by a few mm.... */ +#define DEFAULT_WIDTH_10THS_A4 83 +#define DEFAULT_HEIGHT_10THS_A4 117 +/* Choose a default. A4 may be set in the makefile. */ +#ifdef A4 +# define DEFAULT_WIDTH_10THS DEFAULT_WIDTH_10THS_A4 +# define DEFAULT_HEIGHT_10THS DEFAULT_HEIGHT_10THS_A4 +#else +# define DEFAULT_WIDTH_10THS DEFAULT_WIDTH_10THS_US_LETTER +# define DEFAULT_HEIGHT_10THS DEFAULT_HEIGHT_10THS_US_LETTER +#endif + +/* + * Define the parameters for the printer rendering method. + * If the entire bitmap fits in PRN_MAX_BITMAP, and there is at least + * PRN_MIN_MEMORY_LEFT memory left after allocating it, render in RAM, + * otherwise use a command list with a size of PRN_BUFFER_SPACE. + * (These are parameters that can be changed by a client program.) + */ +/* Define parameters for machines with little dinky RAMs.... */ +#define PRN_MAX_BITMAP_SMALL 32000 +#define PRN_BUFFER_SPACE_SMALL 25000 +#define PRN_MIN_MEMORY_LEFT_SMALL 32000 +/* Define parameters for machines with great big hulking RAMs.... */ +#define PRN_MAX_BITMAP_LARGE 10000000L +#define PRN_BUFFER_SPACE_LARGE 1000000L +#define PRN_MIN_MEMORY_LEFT_LARGE 500000L +/* Define parameters valid on all machines. */ +#define PRN_MIN_BUFFER_SPACE 10000 /* give up if less than this */ +/* Now define conditional parameters. */ +#if arch_small_memory +# define PRN_MAX_BITMAP PRN_MAX_BITMAP_SMALL +# define PRN_BUFFER_SPACE PRN_BUFFER_SPACE_SMALL +# define PRN_MIN_MEMORY_LEFT PRN_MIN_MEMORY_LEFT_SMALL +#else +/****** These should really be conditional on gs_debug_c('.') if + ****** DEBUG is defined, but they're used in static initializers, + ****** so we can't do it. + ******/ +# if 0 /****** # ifdef DEBUG ******/ +# define PRN_MAX_BITMAP\ + (gs_debug_c('.') ? PRN_MAX_BITMAP_SMALL : PRN_MAX_BITMAP_LARGE) +# define PRN_BUFFER_SPACE\ + (gs_debug_c('.') ? PRN_BUFFER_SPACE_SMALL : PRN_BUFFER_SPACE_LARGE) +# define PRN_MIN_MEMORY_LEFT\ + (gs_debug_c('.') ? PRN_MIN_MEMORY_LEFT_SMALL : PRN_MIN_MEMORY_LEFT_LARGE) +# else +# define PRN_MAX_BITMAP PRN_MAX_BITMAP_LARGE +# define PRN_BUFFER_SPACE PRN_BUFFER_SPACE_LARGE +# define PRN_MIN_MEMORY_LEFT PRN_MIN_MEMORY_LEFT_LARGE +# endif +#endif + +/* Define the abstract type for a printer device. */ +typedef struct gx_device_printer_s gx_device_printer; + +/* + * Define the special procedures for band devices. + */ +typedef struct gx_printer_device_procs_s { + + /* + * Print the page on the output file. Required only for devices + * where output_page is gdev_prn_output_page; ignored for other + * devices. + */ + +#define dev_proc_print_page(proc)\ + int proc(P2(gx_device_printer *, FILE *)) + dev_proc_print_page((*print_page)); + + /* Print the page on the output file, with a given # of copies. */ + +#define dev_proc_print_page_copies(proc)\ + int proc(P3(gx_device_printer *, FILE *, int)) + dev_proc_print_page_copies((*print_page_copies)); + + /* Initialize the memory device for a page or a band. */ + /* (The macro definition is in gxdevice.h.) */ + + dev_proc_make_buffer_device((*make_buffer_device)); + +} gx_printer_device_procs; + +/* ------ Printer device definition ------ */ + +/* Structure for generic printer devices. */ +/* This must be preceded by gx_device_common. */ +/* Printer devices are actually a union of a memory device */ +/* and a clist device, plus some additional state. */ +#define prn_fname_sizeof 80 +#define gx_prn_device_common\ + byte skip[max(sizeof(gx_device_memory), sizeof(gx_device_clist)) -\ + sizeof(gx_device) + sizeof(double) /* padding */];\ + gx_printer_device_procs printer_procs;\ + /* ------ The following items must be set before ------ */\ + /* ------ calling the device open routine. ------ */\ + long max_bitmap; /* max size of non-buffered bitmap */\ + long use_buffer_space; /* space to use for buffer */\ + char fname[prn_fname_sizeof]; /* output file name */\ + /* ------ End of preset items ------ */\ + int NumCopies;\ + bool NumCopies_set;\ + bool OpenOutputFile;\ + bool Duplex;\ + int Duplex_set; /* -1 = not supported */\ + bool file_is_new; /* true iff file just opened */\ + FILE *file; /* output file */\ + char ccfname[60]; /* clist file name */\ + clist_file_ptr ccfile; /* command list scratch file */\ + char cbfname[60]; /* clist block file name */\ + clist_file_ptr cbfile; /* command list block scratch file */\ + long buffer_space; /* amount of space for clist buffer, */\ + /* 0 means not using clist */\ + byte *buf; /* buffer for rendering */\ + gx_device_procs orig_procs /* original (std_)procs */ + +/* The device descriptor */ +struct gx_device_printer_s { + gx_device_common; + gx_prn_device_common; +}; + +/* Macro for casting gx_device argument */ +#define prn_dev ((gx_device_printer *)dev) + +/* Define a typedef for the sake of ansi2knr. */ +typedef dev_proc_print_page((*dev_proc_print_page_t)); + +/* Standard device procedures for printers */ +dev_proc_open_device(gdev_prn_open); +dev_proc_output_page(gdev_prn_output_page); +dev_proc_close_device(gdev_prn_close); +#define gdev_prn_map_rgb_color gx_default_b_w_map_rgb_color +#define gdev_prn_map_color_rgb gx_default_b_w_map_color_rgb +dev_proc_get_params(gdev_prn_get_params); +dev_proc_put_params(gdev_prn_put_params); + +/* Macro for generating procedure table */ +#define prn_procs(p_open, p_output_page, p_close)\ + prn_color_procs(p_open, p_output_page, p_close, gdev_prn_map_rgb_color, gdev_prn_map_color_rgb) +#define prn_params_procs(p_open, p_output_page, p_close, p_get_params, p_put_params)\ + prn_color_params_procs(p_open, p_output_page, p_close, gdev_prn_map_rgb_color, gdev_prn_map_color_rgb, p_get_params, p_put_params) +#define prn_color_procs(p_open, p_output_page, p_close, p_map_rgb_color, p_map_color_rgb)\ + prn_color_params_procs(p_open, p_output_page, p_close, p_map_rgb_color, p_map_color_rgb, gdev_prn_get_params, gdev_prn_put_params) +/* See gdev_prn_open for explanation of the NULLs below. */ +#define prn_color_params_procs(p_open, p_output_page, p_close, p_map_rgb_color, p_map_color_rgb, p_get_params, p_put_params) {\ + p_open,\ + NULL, /* get_initial_matrix */\ + NULL, /* sync_output */\ + p_output_page,\ + p_close,\ + p_map_rgb_color,\ + p_map_color_rgb,\ + NULL, /* fill_rectangle */\ + NULL, /* tile_rectangle */\ + NULL, /* copy_mono */\ + NULL, /* copy_color */\ + NULL, /* draw_line */\ + NULL, /* get_bits */\ + p_get_params,\ + p_put_params,\ + NULL, /* map_cmyk_color */\ + NULL, /* get_xfont_procs */\ + NULL, /* get_xfont_device */\ + NULL, /* map_rgb_alpha_color */\ + gx_page_device_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 */\ + NULL, /* strip_tile_rectangle */\ + NULL /* strip_copy_rop */\ +} + +/* The standard printer device procedures */ +/* (using gdev_prn_open/output_page/close). */ +extern gx_device_procs prn_std_procs; + +/* + * Define macros for generating the device structure, + * analogous to the std_device_body macros in gxdevice.h + * Note that the macros are broken up so as to be usable for devices that + * add further initialized state to the printer device. + * + * The 'margin' values provided here specify the unimageable region + * around the edges of the page (in inches), and the left and top margins + * also specify the displacement of the device (0,0) point from the + * upper left corner. We should provide macros that allow specifying + * all 6 values independently, but we don't yet. + */ +#define prn_device_body_rest_(print_page)\ + { 0 }, /* std_procs */\ + { 0 }, /* skip */\ + { print_page,\ + gx_default_print_page_copies,\ + gx_default_make_buffer_device\ + },\ + PRN_MAX_BITMAP,\ + PRN_BUFFER_SPACE,\ + { 0 }, /* fname */\ + 1, 0/*false*/, /* NumCopies[_set] */\ + 0/*false*/, /* OpenOutputFile */\ + 0/*false*/, -1, /* Duplex[_set] */\ + 0/*false*/, 0, { 0 }, 0, { 0 }, 0, 0, 0, { 0 } /* ... orig_procs */ + +/* The Sun cc compiler won't allow \ within a macro argument list. */ +/* This accounts for the short parameter names here and below. */ +#define prn_device_margins_body(dtype, procs, dname, w10, h10, xdpi, ydpi, lo, to, lm, bm, rm, tm, ncomp, depth, mg, mc, dg, dc, print_page)\ + std_device_full_body(dtype, &procs, dname,\ + (int)((long)w10 * xdpi / 10),\ + (int)((long)h10 * ydpi / 10),\ + xdpi, ydpi,\ + ncomp, depth, mg, mc, dg, dc,\ + -(lo) * (xdpi), -(to) * (ydpi),\ + (lm) * 72.0, (bm) * 72.0,\ + (rm) * 72.0, (tm) * 72.0\ + ),\ + prn_device_body_rest_(print_page) + +#define prn_device_body(dtype, procs, dname, w10, h10, xdpi, ydpi, lm, bm, rm, tm, ncomp, depth, mg, mc, dg, dc, print_page)\ + prn_device_margins_body(dtype, procs, dname, w10, h10, xdpi, ydpi,\ + lm, tm, lm, bm, rm, tm, ncomp, depth, mg, mc, dg, dc, print_page) + +#define prn_device_body_copies(dtype, procs, dname, w10, h10, xdpi, ydpi, lm, bm, rm, tm, ncomp, depth, mg, mc, dg, dc, print_pages)\ + std_device_full_body(dtype, &procs, dname,\ + (int)((long)w10 * xdpi / 10),\ + (int)((long)h10 * ydpi / 10),\ + xdpi, ydpi,\ + ncomp, depth, mg, mc, dg, dc,\ + -(lm) * (xdpi), -(tm) * (ydpi),\ + (lm) * 72.0, (bm) * 72.0,\ + (rm) * 72.0, (tm) * 72.0\ + ),\ + { 0 }, /* std_procs */\ + { 0 }, /* skip */\ + { NULL,\ + print_pages,\ + gx_default_make_buffer_device\ + },\ + PRN_MAX_BITMAP,\ + PRN_BUFFER_SPACE,\ + { 0 }, /* fname */\ + 1, 0/*false*/, /* NumCopies[_set] */\ + 0/*false*/, /* OpenOutputFile */\ + 0/*false*/, -1, /* Duplex[_set] */\ + 0/*false*/, 0, { 0 }, 0, { 0 }, 0, 0, 0, { 0 } /* ... orig_procs */ + +#define prn_device_std_margins_body(dtype, procs, dname, w10, h10, xdpi, ydpi, lo, to, lm, bm, rm, tm, color_bits, print_page)\ + std_device_std_color_full_body(dtype, &procs, dname,\ + (int)((long)w10 * xdpi / 10),\ + (int)((long)h10 * ydpi / 10),\ + xdpi, ydpi, color_bits,\ + -(lo) * (xdpi), -(to) * (ydpi),\ + (lm) * 72.0, (bm) * 72.0,\ + (rm) * 72.0, (tm) * 72.0\ + ),\ + prn_device_body_rest_(print_page) + +#define prn_device_std_body(dtype, procs, dname, w10, h10, xdpi, ydpi, lm, bm, rm, tm, color_bits, print_page)\ + prn_device_std_margins_body(dtype, procs, dname, w10, h10, xdpi, ydpi,\ + lm, tm, lm, bm, rm, tm, color_bits, print_page) + +#define prn_device_margins(procs, dname, w10, h10, xdpi, ydpi, lo, to, lm, bm, rm, tm, color_bits, print_page)\ +{ prn_device_std_margins_body(gx_device_printer, procs, dname,\ + w10, h10, xdpi, ydpi, lo, to, lm, bm, rm, tm, color_bits, print_page)\ +} + +#define prn_device(procs, dname, w10, h10, xdpi, ydpi, lm, bm, rm, tm, color_bits, print_page)\ + prn_device_margins(procs, dname, w10, h10, xdpi, ydpi,\ + lm, tm, lm, bm, rm, tm, color_bits, print_page)\ + +/* ------ Utilities ------ */ +/* These are defined in gdevprn.c. */ + +int gdev_prn_open_printer(P2(gx_device *dev, int binary_mode)); +#define gdev_prn_file_is_new(pdev) ((pdev)->file_is_new) +#define gdev_prn_raster(pdev) gx_device_raster((gx_device *)(pdev), 0) +int gdev_prn_get_bits(P4(gx_device_printer *, int, byte *, byte **)); +int gdev_prn_copy_scan_lines(P4(gx_device_printer *, int, byte *, uint)); +int gdev_prn_close_printer(P1(gx_device *)); + +/* Define the InputAttributes and OutputAttributes of a device. */ +/* The device get_params procedure would call these. */ + +typedef struct input_media_s { + float PageSize[2]; + const char *MediaColor; + float MediaWeight; + const char *MediaType; +} input_media; +#define gdev_prn_begin_input_media(plist, pdict, count)\ + ((pdict)->size = (count),\ + param_begin_write_dict(plist, "InputAttributes", pdict, true)) +int gdev_prn_input_page_size(P4(int index, gs_param_dict *pdict, + floatp width_points, floatp height_points)); +int gdev_prn_input_media(P3(int index, gs_param_dict *pdict, + const input_media *pim)); +#define gdev_prn_end_input_media(plist, pdict)\ + param_end_write_dict(plist, "InputAttributes", pdict) + +typedef struct output_media_s { + const char *OutputType; +} output_media; +#define gdev_prn_begin_output_media(plist, pdict, count)\ + ((pdict)->size = (count),\ + param_begin_write_dict(plist, "OutputAttributes", pdict, true)) +int gdev_prn_output_media(P3(int index, gs_param_dict *pdict, + const output_media *pom)); +#define gdev_prn_end_output_media(plist, pdict)\ + param_end_write_dict(plist, "OutputAttributes", pdict) + +/* The default print_page_copies procedure just calls print_page */ +/* the given number of times. */ +dev_proc_print_page_copies(gx_default_print_page_copies); + +/* Define the number of scan lines that should actually be passed */ +/* to the device. */ +int gdev_prn_print_scan_lines(P1(gx_device *)); + +/* BACKWARD COMPATIBILITY */ +#define dev_print_scan_lines(dev)\ + gdev_prn_print_scan_lines((gx_device *)(dev)) +#define gdev_mem_bytes_per_scan_line(dev)\ + gdev_prn_raster((gx_device_printer *)(dev)) +#define gdev_prn_transpose_8x8(inp,ils,outp,ols)\ + memflip8x8(inp,ils,outp,ols) + +/* ------ Printer device types ------ */ +/**************** THE FOLLOWING CODE IS NOT USED YET. ****************/ + +#if 0 /**************** VMS linker gets upset ****************/ +extern_st(st_prn_device); +#endif +int gdev_prn_initialize(P3(gx_device *, const char _ds *, dev_proc_print_page((*)))); +void gdev_prn_init_color(P4(gx_device *, int, dev_proc_map_rgb_color((*)), dev_proc_map_color_rgb((*)))); + +#define prn_device_type(dtname, initproc, pageproc)\ +private dev_proc_print_page(pageproc);\ +device_type(dtname, st_prn_device, initproc) + +/****** FOLLOWING SHOULD CHECK __PROTOTYPES__ ******/ +#define prn_device_type_mono(dtname, dname, initproc, pageproc)\ +private dev_proc_print_page(pageproc);\ +private int \ +initproc(gx_device *dev)\ +{ return gdev_prn_initialize(dev, dname, pageproc);\ +}\ +device_type(dtname, st_prn_device, initproc) + +/****** DITTO ******/ +#define prn_device_type_color(dtname, dname, depth, initproc, pageproc, rcproc, crproc)\ +private dev_proc_print_page(pageproc);\ +private int \ +initproc(gx_device *dev)\ +{ int code = gdev_prn_initialize(dev, dname, pageproc);\ + gdev_prn_init_color(dev, depth, rcproc, crproc);\ + return code;\ +}\ +device_type(dtname, st_prn_device, initproc) + +#endif /* gdevprn_INCLUDED */ diff --git a/pstoraster/genarch.c b/pstoraster/genarch.c new file mode 100644 index 0000000000..855fcdbf3f --- /dev/null +++ b/pstoraster/genarch.c @@ -0,0 +1,131 @@ +/* Copyright (C) 1989, 1995 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to + anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer to + the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given to + you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises is not affiliated with the Free Software Foundation or + the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, + does not depend on any other GNU software. +*/ + +/* genarch.c */ +/* Generate a header file (arch.h) with parameters */ +/* reflecting the machine architecture and compiler characteristics. */ + +#include "stdpre.h" +#include +#include "iref.h" + +/* We should write the result on stdout, but the original Turbo C 'make' */ +/* can't handle output redirection (sigh). */ + +main(int argc, char *argv[]) +{ char *fname = argv[1]; + long one = 1; +#define ffs_strlen 16 + char *ffs = "ffffffffffffffff"; + struct { char c; short s; } ss; + struct { char c; int i; } si; + struct { char c; long l; } sl; + struct { char c; char *p; } sp; + struct { char c; float f; } sf; + struct { char c; double d; } sd; + struct { char c; ref r; } sr; + static int log2s[17] = {0,0,1,0,2,0,0,0,3,0,0,0,0,0,0,0,4}; + long lm1 = -1; + long lr1 = lm1 >> 1, lr2 = lm1 >> 2; + unsigned long um1 = ~(unsigned long)0; + int im1 = -1; + int ir1 = im1 >> 1, ir2 = im1 >> 2; + union { long l; char *p; } pl0, pl1; + int ars; + int lwidth = size_of(long) * 8; + union { float f; int i; long l; } f0, f1, fm1; + FILE *f = fopen(fname, "w"); + if ( f == NULL ) + { fprintf(stderr, "genarch.c: can't open %s for writing\n", fname); + return exit_FAILED; + } + fprintf(f, "/* Parameters derived from machine and compiler architecture */\n"); +#define S(str) fprintf(f, "\n\t%s\n\n", str) + +S("/* ---------------- Scalar alignments ---------------- */"); + +#define offset(s, e) (int)((char *)&s.e - (char *)&s) + fprintf(f, "#define arch_align_short_mod %d\n", offset(ss, s)); + fprintf(f, "#define arch_align_int_mod %d\n", offset(si, i)); + fprintf(f, "#define arch_align_long_mod %d\n", offset(sl, l)); + fprintf(f, "#define arch_align_ptr_mod %d\n", offset(sp, p)); + fprintf(f, "#define arch_align_float_mod %d\n", offset(sf, f)); + fprintf(f, "#define arch_align_double_mod %d\n", offset(sd, d)); + fprintf(f, "#define arch_align_ref_mod %d\n", offset(sr, r)); +#undef offset + +S("/* ---------------- Scalar sizes ---------------- */"); + + fprintf(f, "#define arch_log2_sizeof_short %d\n", log2s[size_of(short)]); + fprintf(f, "#define arch_log2_sizeof_int %d\n", log2s[size_of(int)]); + fprintf(f, "#define arch_log2_sizeof_long %d\n", log2s[size_of(long)]); + fprintf(f, "#define arch_sizeof_ds_ptr %d\n", size_of(char _ds *)); + fprintf(f, "#define arch_sizeof_ptr %d\n", size_of(char *)); + fprintf(f, "#define arch_sizeof_float %d\n", size_of(float)); + fprintf(f, "#define arch_sizeof_double %d\n", size_of(double)); + fprintf(f, "#define arch_sizeof_ref %d\n", size_of(ref)); + +S("/* ---------------- Unsigned max values ---------------- */"); + +#define pmax(str, typ, tstr, l)\ + fprintf(f, "#define arch_max_%s ((%s)0x%s%s + (%s)0)\n",\ + str, tstr, ffs + ffs_strlen - size_of(typ) * 2, l, tstr) + pmax("uchar", unsigned char, "unsigned char", ""); + pmax("ushort", unsigned short, "unsigned short", ""); + pmax("uint", unsigned int, "unsigned int", ""); + pmax("ulong", unsigned long, "unsigned long", "L"); +#undef pmax + +S("/* ---------------- Miscellaneous ---------------- */"); + + fprintf(f, "#define arch_is_big_endian %d\n", 1 - *(char *)&one); + pl0.l = 0; + pl1.l = -1; + fprintf(f, "#define arch_ptrs_are_signed %d\n", + (pl1.p < pl0.p)); + f0.f = 0.0, f1.f = 1.0, fm1.f = -1.0; + /* We have to test the size dynamically here, */ + /* because the preprocessor can't evaluate sizeof. */ + fprintf(f, "#define arch_floats_are_IEEE %d\n", + ((size_of(float) == size_of(int) ? + f0.i == 0 && f1.i == (int)0x3f800000 && fm1.i == (int)0xbf800000 : + f0.l == 0 && f1.l == 0x3f800000L && fm1.l == 0xbf800000L) + ? 1 : 0)); + /* There are three cases for arithmetic right shift: */ + /* always correct, correct except for right-shifting a long by 1 */ + /* (a bug in some versions of the Turbo C compiler), and */ + /* never correct. */ + ars = (lr2 != -1 || ir1 != -1 || ir2 != -1 ? 0 : + lr1 != -1 ? 1 : /* Turbo C problem */ + 2); + fprintf(f, "#define arch_arith_rshift %d\n", ars); + /* Some machines can't handle a variable shift by */ + /* the full width of a long. */ + fprintf(f, "#define arch_can_shift_full_long %d\n", + um1 >> lwidth == 0); + +/* ---------------- Done. ---------------- */ + + fclose(f); + return exit_OK; +} diff --git a/pstoraster/ghost.h b/pstoraster/ghost.h new file mode 100644 index 0000000000..fbb6db087d --- /dev/null +++ b/pstoraster/ghost.h @@ -0,0 +1,27 @@ +/* Copyright (C) 1989, 1992 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to + anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer to + the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given to + you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises is not affiliated with the Free Software Foundation or + the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, + does not depend on any other GNU software. +*/ + +/* ghost.h */ +/* Common definitions for interpreter */ +#include "gx.h" +#include "iref.h" diff --git a/pstoraster/gp.h b/pstoraster/gp.h new file mode 100644 index 0000000000..05e9d0fccd --- /dev/null +++ b/pstoraster/gp.h @@ -0,0 +1,201 @@ +/* Copyright (C) 1991, 1995 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to + anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer to + the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given to + you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises is not affiliated with the Free Software Foundation or + the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, + does not depend on any other GNU software. +*/ + +/* gp.h */ +/* Interface to platform-specific routines */ +/* Requires gsmemory.h, gstypes.h */ + +/* + * This file defines the interface to ***ALL*** platform-specific routines. + * The routines are implemented in a gp_*.c file specific to each platform. + * We try very hard to keep this list short! + */ + +/* ------ Initialization/termination ------ */ + +/* + * This routine is called early in the initialization. + * It should do as little as possible. In particular, it should not + * do things like open display connections: that is the responsibility + * of the display device driver. + */ +void gp_init(P0()); + +/* + * This routine is called just before the program exits (normally or + * abnormally). It too should do as little as possible. + */ +void gp_exit(P2(int exit_status, int code)); + +/* + * Exit the program. Normally this just calls the `exit' library procedure, + * but it does something different on a few platforms. + */ +void gp_do_exit(P1(int exit_status)); + +/* ------ Miscellaneous ------ */ + +/* + * Get the string corresponding to an OS error number. + * If no string is available, return NULL. The caller may assume + * the string is allocated statically and permanently. + */ +const char *gp_strerror(P1(int)); + +/* ------ Date and time ------ */ + +/* + * Read the current time (in seconds since an implementation-defined epoch) + * into ptm[0], and fraction (in nanoseconds) into ptm[1]. + */ +void gp_get_realtime(P1(long ptm[2])); + +/* + * Read the current user CPU time (in seconds) into ptm[0], + * and fraction (in nanoseconds) into ptm[1]. + */ +void gp_get_usertime(P1(long ptm[2])); + +/* ------ Screen management ------ */ + +/* + * The following routines are only relevant in a single-window environment + * such as a PC; on platforms with window systems, the 'make current' + * routines do nothing. + */ + +#ifndef gx_device_DEFINED +# define gx_device_DEFINED +typedef struct gx_device_s gx_device; +#endif + +/* Initialize the console. */ +void gp_init_console(P0()); + +/* Write a string to the console. */ +void gp_console_puts(P2(const char *, uint)); + +/* Make the console current on the screen. */ +int gp_make_console_current(P1(gx_device *)); + +/* Make the graphics current on the screen. */ +int gp_make_graphics_current(P1(gx_device *)); + +/* + * The following are only relevant for X Windows. + */ + +/* Get the environment variable that specifies the display to use. */ +const char *gp_getenv_display(P0()); + +/* ------ 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. + */ +FILE *gp_open_printer(P2(char *fname, int binary_mode)); + +/* Close the connection to the printer. */ +void gp_close_printer(P2(FILE *pfile, const char *fname)); + +/* ------ File naming and accessing ------ */ + +/* Define the character used for separating file names in a list. */ +extern const char gp_file_name_list_separator; + +/* Define the default scratch file name prefix. */ +extern const char gp_scratch_file_name_prefix[]; + +/* Define the name of the null output file. */ +extern const char gp_null_file_name[]; + +/* Define the name that designates the current directory. */ +extern const char gp_current_directory_name[]; + +/* Define the string to be concatenated with the file mode */ +/* for opening files without end-of-line conversion. */ +/* This is always either "" or "b". */ +extern const char gp_fmode_binary_suffix[]; +/* Define the file modes for binary reading or writing. */ +/* (This is just a convenience: they are "r" or "w" + the suffix.) */ +extern const char gp_fmode_rb[]; +extern const char gp_fmode_wb[]; + +/* Create and open a scratch file with a given name prefix. */ +/* Write the actual file name at fname. */ +FILE *gp_open_scratch_file(P3(const char *prefix, char *fname, + const char *mode)); + +/* Open a file with the given name, as a stream of uninterpreted bytes. */ +FILE *gp_fopen(P2(const char *fname, const char *mode)); + +/* Answer whether a file name contains a directory/device specification, */ +/* i.e. is absolute (not directory- or device-relative). */ +bool gp_file_name_is_absolute(P2(const char *fname, uint len)); + +/* Answer the string to be used for combining a directory/device prefix */ +/* with a base file name. The file name is known to not be absolute. */ +const char *gp_file_name_concat_string(P4(const char *prefix, uint plen, + const char *fname, uint len)); + +/* ------ 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 + +/* + * Begin an enumeration. pat is a C string that may contain *s or ?s. + * The implementor should copy the string to a safe place. + * If the operating system doesn't support correct, arbitrarily placed + * *s and ?s, the implementation should modify the string so that it + * will return a conservative superset of the request, and then use + * the string_match procedure to select the desired subset. E.g., if the + * OS doesn't implement ? (single-character wild card), any consecutive + * string of ?s should be interpreted as *. Note that \ can appear in + * the pattern also, as a quoting character. + */ +file_enum *gp_enumerate_files_init(P3(const char *pat, uint patlen, + gs_memory_t *memory)); + +/* + * Return the next file name in the enumeration. The client passes in + * a scratch string and a max length. If the name of the next file fits, + * the procedure returns the length. If it doesn't fit, the procedure + * returns max length +1. If there are no more files, the procedure + * returns -1. + */ +uint gp_enumerate_files_next(P3(file_enum *pfen, char *ptr, uint maxlen)); + +/* + * Clean up a file enumeration. This is only called to abandon + * an enumeration partway through: ...next should do it if there are + * no more files to enumerate. This should deallocate the file_enum + * structure and any subsidiary structures, strings, buffers, etc. + */ +void gp_enumerate_files_close(P1(file_enum *pfen)); diff --git a/pstoraster/gp_nofb.c b/pstoraster/gp_nofb.c new file mode 100644 index 0000000000..76e681633c --- /dev/null +++ b/pstoraster/gp_nofb.c @@ -0,0 +1,54 @@ +/* Copyright (C) 1993 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to + anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer to + the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given to + you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises is not affiliated with the Free Software Foundation or + the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, + does not depend on any other GNU software. +*/ + +/* gp_nofb.c */ +/* Dummy routines for Ghostscript platforms with no frame buffer management */ +#include "gx.h" +#include "gp.h" +#include "gxdevice.h" + +/* ------ Screen management ------ */ + +/* Initialize the console. */ +void +gp_init_console(void) +{ +} + +/* Write a string to the console. */ +void +gp_console_puts(const char *str, uint size) +{ fwrite(str, 1, size, stdout); +} + +/* Make the console current on the screen. */ +int +gp_make_console_current(gx_device *dev) +{ return 0; +} + +/* Make the graphics current on the screen. */ +int +gp_make_graphics_current(gx_device *dev) +{ return 0; +} diff --git a/pstoraster/gp_unifn.c b/pstoraster/gp_unifn.c new file mode 100644 index 0000000000..10d55a5831 --- /dev/null +++ b/pstoraster/gp_unifn.c @@ -0,0 +1,58 @@ +/* Copyright (C) 1994, 1996 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to + anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer to + the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given to + you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises is not affiliated with the Free Software Foundation or + the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, + does not depend on any other GNU software. +*/ + +/* gp_unifn.c */ +/* Unix-like file name syntax platform routines for Ghostscript */ +#include "gx.h" +#include "gp.h" + +/* Define the character used for separating file names in a list. */ +const char gp_file_name_list_separator = ':'; + +/* Define the string to be concatenated with the file mode */ +/* for opening files without end-of-line conversion. */ +const char gp_fmode_binary_suffix[] = ""; +/* Define the file modes for binary reading or writing. */ +const char gp_fmode_rb[] = "r"; +const char gp_fmode_wb[] = "w"; + +/* Answer whether a file name contains a directory/device specification, */ +/* i.e. is absolute (not directory- or device-relative). */ +bool +gp_file_name_is_absolute(const char *fname, unsigned len) +{ /* A file name is absolute if it starts with a 0 or more .s */ + /* followed by a /. */ + while ( len && *fname == '.' ) + ++fname, --len; + return (len && *fname == '/'); +} + +/* Answer the string to be used for combining a directory/device prefix */ +/* with a base file name. The file name is known to not be absolute. */ +const char * +gp_file_name_concat_string(const char *prefix, unsigned plen, + const char *fname, unsigned len) +{ if ( plen > 0 && prefix[plen - 1] == '/' ) + return ""; + return "/"; +} diff --git a/pstoraster/gp_unifs.c b/pstoraster/gp_unifs.c new file mode 100644 index 0000000000..7d634db886 --- /dev/null +++ b/pstoraster/gp_unifs.c @@ -0,0 +1,424 @@ +/* Copyright (C) 1993, 1995 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to + anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer to + the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given to + you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises is not affiliated with the Free Software Foundation or + the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, + does not depend on any other GNU software. +*/ + +/* gp_unifs.c */ +/* "Unix-like" file system platform routines for Ghostscript */ +#include "memory_.h" +#include "string_.h" +#include "gx.h" +#include "gp.h" +#include "gsstruct.h" +#include "gsutil.h" /* for string_match */ +#include "stat_.h" +#include "dirent_.h" +#include /* for MAXPATHLEN */ + +/* Some systems (Interactive for example) don't define MAXPATHLEN, + * so we define it here. (This probably should be done via a Config-Script.) + */ + +#ifndef MAXPATHLEN +# define MAXPATHLEN 1024 +#endif + +/* Library routines not declared in a standard header */ +extern char *getenv(P1(const char *)); +extern char *mktemp(P1(char *)); + +/* ------ File naming and accessing ------ */ + +/* Define the default scratch file name prefix. */ +const char gp_scratch_file_name_prefix[] = "gs_"; + +/* Define the name of the null output file. */ +const char gp_null_file_name[] = "/dev/null"; + +/* Define the name that designates the current directory. */ +const char gp_current_directory_name[] = "."; + +/* Create and open a scratch file with a given name prefix. */ +/* Write the actual file name at fname. */ +FILE * +gp_open_scratch_file(const char *prefix, char *fname, const char *mode) +{ char *temp; + if ( (temp = getenv("TEMP")) == NULL ) + strcpy(fname, "/tmp/"); + else + { strcpy(fname, temp); + if ( strlen(fname) != 0 && fname[strlen(fname) - 1] != '/' ) + strcat(fname, "/"); + } + strcat(fname, prefix); + /* Prevent trailing X's in path from being converted by mktemp. */ + if ( *fname != 0 && fname[strlen(fname) - 1] == 'X' ) + strcat(fname, "-"); + strcat(fname, "XXXXXX"); + mktemp(fname); + return fopen(fname, mode); +} + +/* Open a file with the given name, as a stream of uninterpreted bytes. */ +FILE * +gp_fopen(const char *fname, const char *mode) +{ return fopen(fname, mode); +} + +/* ------ File enumeration ------ */ + +/* Thanks to Fritz Elfert (Fritz_Elfert@wue.maus.de) for */ +/* the original version of the following code, and Richard Mlynarik */ +/* (mly@adoc.xerox.com) for an improved version. */ + +typedef struct dirstack_s dirstack; +struct dirstack_s { + dirstack *next; + DIR *entry; +}; +gs_private_st_ptrs1(st_dirstack, dirstack, "dirstack", + dirstack_enum_ptrs, dirstack_reloc_ptrs, next); + +struct file_enum_s { + DIR *dirp; /* pointer to current open directory */ + char *pattern; /* original pattern */ + char *work; /* current path */ + int worklen; /* strlen (work) */ + dirstack *dstack; /* directory stack */ + int patlen; + int pathead; /* how much of pattern to consider + * when listing files in current directory */ + bool first_time; + gs_memory_t *memory; +}; +gs_private_st_ptrs3(st_file_enum, struct file_enum_s, "file_enum", + file_enum_enum_ptrs, file_enum_reloc_ptrs, pattern, work, dstack); + +/* Private procedures */ + +/* Do a wild-card match. */ +#ifdef DEBUG +private bool +wmatch(const byte *str, uint len, const byte *pstr, uint plen, + const string_match_params *psmp) +{ bool match = string_match(str, len, pstr, plen, psmp); + if ( gs_debug_c('e') ) + { dputs("[e]string_match(\""); + fwrite(str, 1, len, dstderr); + dputs("\", \""); + fwrite(pstr, 1, plen, dstderr); + dprintf1("\") = %s\n", (match ? "TRUE" : "false")); + } + return match; +} +#define string_match wmatch +#endif + +/* Search a string backward for a character. */ +/* (This substitutes for strrchr, which some systems don't provide.) */ +private char * +rchr(char *str, char ch, int len) +{ register char *p = str + len; + while ( p > str ) + if ( *--p == ch ) return p; + return 0; +} + +/* Pop a directory from the enumeration stack. */ +private bool +popdir(file_enum *pfen) +{ dirstack *d = pfen->dstack; + if ( d == 0 ) + return false; + pfen->dirp = d->entry; + pfen->dstack = d->next; + gs_free_object(pfen->memory, d, "gp_enumerate_files(popdir)"); + return true; +} + +/* Initialize an enumeration. */ +file_enum * +gp_enumerate_files_init(const char *pat, uint patlen, gs_memory_t *mem) +{ file_enum *pfen; + char *p; + char *work; + + /* Reject attempts to enumerate paths longer than the */ + /* system-dependent limit. */ + if ( patlen > MAXPATHLEN ) + return 0; + + /* Reject attempts to enumerate with a pattern containing zeroes. */ + { const char *p1; + for (p1 = pat; p1 < pat + patlen; p1++) + if (*p1 == 0) return 0; + } + /* >>> Should crunch strings of repeated "/"'s in pat to a single "/" + * >>> to match stupid unix filesystem "conventions" */ + + pfen = gs_alloc_struct(mem, file_enum, &st_file_enum, + "gp_enumerate_files"); + if (pfen == 0) + return 0; + + /* pattern and work could be allocated as strings, */ + /* but it's simpler for GC and freeing to allocate them as bytes. */ + + pfen->pattern = + (char *)gs_alloc_bytes(mem, patlen + 1, + "gp_enumerate_files(pattern)"); + if (pfen->pattern == 0) + return 0; + memcpy(pfen->pattern, pat, patlen); + pfen->pattern[patlen] = 0; + + work = (char *)gs_alloc_bytes(mem, MAXPATHLEN+1, + "gp_enumerate_files(work)"); + if (work == 0) + return 0; + pfen->work = work; + + p = work; + memcpy(p, pat, patlen); + p += patlen; + *p = 0; + + /* Remove directory specifications beyond the first wild card. */ + /* Some systems don't have strpbrk, so we code it open. */ + p = pfen->work; + while ( !(*p == '*' || *p == '?' || *p == 0) ) p++; + while ( !(*p == '/' || *p == 0) ) p++; + if ( *p == '/' ) + *p = 0; + /* Substring for first wildcard match */ + pfen->pathead = p - work; + + /* Select the next higher directory-level. */ + p = rchr(work, '/', p - work); + if (!p) + { /* No directory specification */ + work[0] = 0; + pfen->worklen = 0; + } + else + { if (p == work) + { /* Root directory -- don't turn "/" into "" */ + p++; + } + *p = 0; + pfen->worklen = p - work; + } + + pfen->memory = mem; + pfen->dstack = 0; + pfen->first_time = true; + pfen->patlen = patlen; + return pfen; +} + +/* Enumerate the next file. */ +uint +gp_enumerate_files_next(file_enum *pfen, char *ptr, uint maxlen) +{ dir_entry *de; + char *work = pfen->work; + int worklen = pfen->worklen; + char *pattern = pfen->pattern; + int pathead = pfen->pathead; + int len; + struct stat stbuf; + + if ( pfen->first_time ) + { pfen->dirp = ((worklen == 0) ? opendir(".") : opendir(work)); + if_debug1('e', "[e]file_enum:First-Open '%s'\n", work); + pfen->first_time = false; + if (pfen->dirp == 0) /* first opendir failed */ + { gp_enumerate_files_close(pfen); + return ~(uint)0; + } + } + + top: de = readdir(pfen->dirp); + if (de == 0) + { /* No more entries in this directory */ + char *p; + + if_debug0('e', "[e]file_enum:Closedir\n"); + closedir(pfen->dirp); + /* Back working directory and matching pattern up one level */ + p = rchr(work,'/', worklen); + if (p != 0) + { if (p == work) p++; + *p = 0; + worklen = p - work; + } + else + worklen = 0; + p = rchr(pattern,'/', pathead); + if (p != 0) + pathead = p - pattern; + else + pathead = 0; + + if (popdir(pfen)) + { /* Back up the directory tree. */ + if_debug1('e', "[e]file_enum:Dir popped '%s'\n", work); + goto top; + } + else + { if_debug0('e', "[e]file_enum:Dirstack empty\n"); + gp_enumerate_files_close(pfen); + return ~(uint)0; + } + } + + /* Skip . and .. */ + len = strlen(de->d_name); + if (len <= 2 && (!strcmp(de->d_name,".") || !strcmp(de->d_name,"..") )) + goto top; + if (len + worklen + 1 > MAXPATHLEN) + /* Should be an error, I suppose */ + goto top; + if (worklen == 0) + { /* "Current" directory (evil un*x kludge) */ + memcpy(work, de->d_name, len + 1); + } + else if (worklen == 1 && work[0] == '/') + { /* Root directory */ + memcpy(work + 1, de->d_name, len + 1); + len = len + 1; + } + else + { work[worklen] = '/'; + memcpy(work + worklen + 1, de->d_name, len + 1); + len = worklen + 1 + len; + } + + /* Test for a match at this directory level */ + if (!string_match((byte *)work, len, (byte *)pattern, pathead, NULL)) + goto top; + + /* Perhaps descend into subdirectories */ + if (pathead < pfen->patlen) + { DIR *dp; + + if (((stat(work,&stbuf) >= 0) + ? !stat_is_dir(stbuf) + /* Couldn't stat it. + * Well, perhaps it's a directory and + * we'll be able to list it anyway. + * If it isn't or we can't, no harm done. */ + : 0)) + goto top; + + if (pfen->patlen == pathead + 1) + { /* Listing "foo/?/" -- return this entry */ + /* if it's a directory. */ + if (!stat_is_dir (stbuf)) + { /* Do directoryp test the hard way */ + dp = opendir(work); + if (!dp) goto top; + closedir(dp); + } + work[len++] = '/'; + goto winner; + } + + /* >>> Should optimise the case in which the next level */ + /* >>> of directory has no wildcards. */ + dp = opendir(work); +#ifdef DEBUG + { char save_end = pattern[pathead]; + pattern[pathead] = 0; + if_debug2('e', "[e]file_enum:fname='%s', p='%s'\n", + work, pattern); + pattern[pathead] = save_end; + } +#endif /* DEBUG */ + if (!dp) + /* Can't list this one */ + goto top; + else + { /* Advance to the next directory-delimiter */ + /* in pattern */ + char *p; + dirstack *d; + for (p = pattern + pathead + 1; ; p++) + { if (*p == 0) + { /* No more subdirectories to match */ + pathead = pfen->patlen; + break; + } + else if (*p == '/') + { pathead = p - pattern; + break; + } + } + + /* Push a directory onto the enumeration stack. */ + d = gs_alloc_struct(pfen->memory, dirstack, + &st_dirstack, + "gp_enumerate_files(pushdir)"); + if ( d != 0 ) + { + d->next = pfen->dstack; + d->entry = pfen->dirp; + pfen->dstack = d; + } + else + DO_NOTHING; /* >>> e_VMerror!!! */ + + if_debug1('e', "[e]file_enum:Dir pushed '%s'\n", + work); + worklen = len; + pfen->dirp = dp; + goto top; + } + } + + winner: + /* We have a winner! */ + pfen->worklen = worklen; + pfen->pathead = pathead; + memcpy(ptr, work, len); + return len; +} + +/* Clean up the file enumeration. */ +void +gp_enumerate_files_close(file_enum *pfen) +{ gs_memory_t *mem = pfen->memory; + + if_debug0('e', "[e]file_enum:Cleanup\n"); + while (popdir(pfen)) /* clear directory stack */ + DO_NOTHING; + gs_free_object(mem, (byte *)pfen->work, + "gp_enumerate_close(work)"); + gs_free_object(mem, (byte *)pfen->pattern, + "gp_enumerate_files_close(pattern)"); + gs_free_object(mem, pfen, "gp_enumerate_files_close"); +} + +/* Test-cases: + (../?*r*?/?*.ps) {==} 100 string filenameforall + (../?*r*?/?*.ps*) {==} 100 string filenameforall + (../?*r*?/) {==} 100 string filenameforall + (/t*?/?*.ps) {==} 100 string filenameforall +*/ diff --git a/pstoraster/gp_unix.c b/pstoraster/gp_unix.c new file mode 100644 index 0000000000..d81553c725 --- /dev/null +++ b/pstoraster/gp_unix.c @@ -0,0 +1,174 @@ +/* Copyright (C) 1989, 1995, 1996 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to + anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer to + the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given to + you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises is not affiliated with the Free Software Foundation or + the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, + does not depend on any other GNU software. +*/ + +/* gp_unix.c */ +/* Unix-specific routines for Ghostscript */ +#include "string_.h" +#include "gx.h" +#include "gsexit.h" +#include "gp.h" +#include "time_.h" + +#if defined(SYSV) || defined(SVR4) || defined(CLK_TCK) +#include +#endif + +/* + * Because of inconsistent (and sometimes incorrect) header files, + * we must omit the argument list for popen. + */ +extern FILE *popen( /* P2(const char *, const char *) */ ); +extern int pclose(P1(FILE *)); +/* + * This is the only place in Ghostscript that calls 'exit'. Including + * is overkill, but that's where it's declared on ANSI systems. + * We don't have any way of detecting whether we have a standard library + * (some GNU compilers perversely define __STDC__ but don't provide + * an ANSI-compliant library), so we check __PROTOTYPES__ and + * hope for the best. We pick up getenv at the same time. + */ +#ifdef __PROTOTYPES__ +# include /* for exit and getenv */ +#else +extern void exit(P1(int)); +extern char *getenv(P1(const char *)); +#endif + +/* Do platform-dependent initialization. */ +void +gp_init(void) +{ +} + +/* Do platform-dependent cleanup. */ +void +gp_exit(int exit_status, int code) +{ +} + +/* Exit the program. */ +void +gp_do_exit(int exit_status) +{ exit(exit_status); +} + +/* ------ Miscellaneous ------ */ + +/* Get the string corresponding to an OS error number. */ +/* Unix systems support this so inconsistently that we don't attempt */ +/* to figure out whether it's available. */ +const char * +gp_strerror(int errnum) +{ return NULL; +} + +/* ------ Date and time ------ */ + +/* Read the current time (in seconds since Jan. 1, 1970) */ +/* and fraction (in nanoseconds). */ +void +gp_get_realtime(long *pdt) +{ struct timeval tp; + +#if gettimeofday_no_timezone /* older versions of SVR4 */ + { if ( gettimeofday(&tp) == -1 ) + { lprintf("Ghostscript: gettimeofday failed!\n"); + gs_exit(1); + } + } +#else /* All other systems */ + { struct timezone tzp; + if ( gettimeofday(&tp, &tzp) == -1 ) + { lprintf("Ghostscript: gettimeofday failed!\n"); + gs_exit(1); + } + } +#endif + + /* tp.tv_sec is #secs since Jan 1, 1970 */ + pdt[0] = tp.tv_sec; + + /* Some Unix systems (e.g., Interactive 3.2 r3.0) return garbage */ + /* in tp.tv_usec. Try to filter out the worst of it here. */ + pdt[1] = tp.tv_usec >= 0 && tp.tv_usec < 1000000 ? tp.tv_usec*1000 : 0; + +#ifdef DEBUG_CLOCK + printf("tp.tv_sec = %d tp.tv_usec = %d pdt[0] = %ld pdt[1] = %ld\n", + tp.tv_sec, tp.tv_usec, pdt[0], pdt[1]); +#endif +} + +/* Read the current user CPU time (in seconds) */ +/* and fraction (in nanoseconds). */ +void +gp_get_usertime(long *pdt) +{ +#if use_times_for_usertime + struct tms tms; + long ticks; + + static long ticks_per_sec; + if ( !ticks_per_sec ) /* not initialized yet */ + ticks_per_sec = CLK_TCK; + + times(&tms); + ticks = tms.tms_utime + tms.tms_stime + tms.tms_cutime + tms.tms_cstime; + pdt[0] = ticks / ticks_per_sec; + pdt[1] = (ticks % ticks_per_sec) * (1000000000 / ticks_per_sec); +#else + gp_get_realtime(pdt); /* Use an approximation on other hosts. */ +#endif +} + +/* ------ Screen management ------ */ + +/* Get the environment variable that specifies the display to use. */ +const char * +gp_getenv_display(void) +{ return getenv("DISPLAY"); +} + +/* ------ 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. */ +FILE * +gp_open_printer(char *fname, int binary_mode) +{ return + (strlen(fname) == 0 ? + gp_open_scratch_file(gp_scratch_file_name_prefix, fname, "w") : + fname[0] == '|' ? + popen(fname + 1, "w") : + fopen(fname, "w")); +} + +/* Close the connection to the printer. */ +void +gp_close_printer(FILE *pfile, const char *fname) +{ if ( fname[0] == '|' ) + pclose(pfile); + else + fclose(pfile); +} diff --git a/pstoraster/gpcheck.h b/pstoraster/gpcheck.h new file mode 100644 index 0000000000..c9308931c4 --- /dev/null +++ b/pstoraster/gpcheck.h @@ -0,0 +1,58 @@ +/* Copyright (C) 1992, 1994 Aladdin Enterprises. All rights reserved. + + This file is part of GNU Ghostscript. + + GNU Ghostscript is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to + anyone for the consequences of using it or for whether it serves any + particular purpose or works at all, unless he says so in writing. Refer to + the GNU General Public License for full details. + + Everyone is granted permission to copy, modify and redistribute GNU + Ghostscript, but only under the conditions described in the GNU General + Public License. A copy of this license is supposed to have been given to + you along with GNU Ghostscript so you can know your rights and + responsibilities. It should be in a file named COPYING. Among other + things, the copyright notice and this notice must be preserved on all + copies. + + Aladdin Enterprises is not affiliated with the Free Software Foundation or + the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, + does not depend on any other GNU software. +*/ + +/* gpcheck.h */ +/* Interrupt check interface */ + +/* + * On some platforms, the interpreter must check periodically for user- + * initiated actions. (Eventually, this may be extended to all platforms, + * to handle multi-tasking through the 'context' facility.) Routines that + * run for a long time must periodically call gp_check_interrupts(), and + * if it returns true, must clean up whatever they are doing and return an + * e_interrupted (or gs_error_interrupted) exceptional condition. + * The return_if_interrupt macro provides a convenient way to do this. + * + * On platforms that require an interrupt check, the makefile defines + * a symbol CHECK_INTERRUPTS. Currently this is only the Microsoft + * Windows platform. + */ + +#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();\ + if ( icode_ )\ + return gs_note_error((icode_ > 0 ? gs_error_interrupt : icode_));\ + } +# define return_check_interrupt(code)\ + return gs_return_check_interrupt(code) +#else +# define gp_check_interrupts() 0 +# define process_interrupts() DO_NOTHING +# define return_if_interrupt() DO_NOTHING +# define return_check_interrupt(code)\ + return (code) +#endif diff --git a/pstoraster/gs_btokn.ps b/pstoraster/gs_btokn.ps new file mode 100644 index 0000000000..9a37cce19c --- /dev/null +++ b/pstoraster/gs_btokn.ps @@ -0,0 +1,287 @@ +% Copyright (C) 1994, 1996 Aladdin Enterprises. All rights reserved. +% +% This file is part of GNU Ghostscript. +% +% GNU Ghostscript is distributed in the hope that it will be useful, but +% WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to +% anyone for the consequences of using it or for whether it serves any +% particular purpose or works at all, unless he says so in writing. Refer to +% the GNU General Public License for full details. +% +% Everyone is granted permission to copy, modify and redistribute GNU +% Ghostscript, but only under the conditions described in the GNU General +% Public License. A copy of this license is supposed to have been given to +% you along with GNU Ghostscript so you can know your rights and +% responsibilities. It should be in a file named COPYING. Among other +% things, the copyright notice and this notice must be preserved on all +% copies. +% +% Aladdin Enterprises is not affiliated with the Free Software Foundation or +% the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, +% does not depend on any other GNU software. + +% Initialization file for binary tokens. +% When this is run, systemdict is still writable, +% but everything defined here goes into level2dict. + +% Define whether or not to allow writing dictionaries. +/WRITEDICTS true def + +languagelevel 1 .setlanguagelevel +level2dict begin + +% Initialization for the system name table. + +mark +% 0 + /abs /add /aload /anchorsearch /and + /arc /arcn /arct /arcto /array + /ashow /astore /awidthshow /begin /bind + /bitshift /ceiling /charpath /clear /cleartomark +% 20 + /clip /clippath /closepath /concat /concatmatrix + /copy /count /counttomark /currentcmykcolor /currentdash + /currentdict /currentfile /currentfont /currentgray /currentgstate + /currenthsbcolor /currentlinecap /currentlinejoin /currentlinewidth /currentmatrix +% 40 + /currentpoint /currentrgbcolor /currentshared /curveto /cvi + /cvlit /cvn /cvr /cvrs /cvs + /cvx /def /defineusername /dict /div + /dtransform /dup /end /eoclip /eofill +% 60 + /eoviewclip /eq /exch /exec /exit + /file /fill /findfont /flattenpath /floor + /flush /flushfile /for /forall /ge + /get /getinterval /grestore /gsave /gstate +% 80 + /gt /identmatrix /idiv /idtransform /if + /ifelse /image /imagemask /index /ineofill + /infill /initviewclip /inueofill /inufill /invertmatrix + /itransform /known /le /length /lineto +% 100 + /load /loop /lt /makefont /matrix + /maxlength /mod /moveto /mul /ne + /neg /newpath /not /null /or + /pathbbox /pathforall /pop /print /printobject +% 120 + /put /putinterval /rcurveto /read /readhexstring + /readline /readstring /rectclip /rectfill /rectstroke + /rectviewclip /repeat /restore /rlineto /rmoveto + /roll /rotate /round /save /scale +% 140 + /scalefont /search /selectfont /setbbox /setcachedevice + /setcachedevice2 /setcharwidth /setcmykcolor /setdash /setfont + /setgray /setgstate /sethsbcolor /setlinecap /setlinejoin + /setlinewidth /setmatrix /setrgbcolor /setshared /shareddict +% 160 + /show /showpage /stop /stopped /store + /string /stringwidth /stroke /strokepath /sub + /systemdict /token /transform /translate /truncate + /type /uappend /ucache /ueofill /ufill +% 180 + /undef /upath /userdict /ustroke /viewclip + /viewclippath /where /widthshow /write /writehexstring + /writeobject /writestring /wtranslation /xor /xshow + /xyshow /yshow /FontDirectory /SharedFontDirectory /Courier +% 200 + /Courier-Bold /Courier-BoldOblique /Courier-Oblique /Helvetica /Helvetica-Bold + /Helvetica-BoldOblique /Helvetica-Oblique /Symbol /Times-Bold /Times-BoldItalic + /Times-Italic /Times-Roman /execuserobject /currentcolor /currentcolorspace + /currentglobal /execform /filter /findresource /globaldict +% 220 + /makepattern /setcolor /setcolorspace /setglobal /setpagedevice + /setpattern +% pad to 256 + counttomark 256 exch sub { 0 } repeat +% 256 + /= /== /ISOLatin1Encoding /StandardEncoding +% 260 + ([) cvn (]) cvn /atan /banddevice /bytesavailable + /cachestatus /closefile /colorimage /condition /copypage + /cos /countdictstack /countexecstack /cshow /currentblackgeneration + /currentcacheparams /currentcolorscreen /currentcolortransfer /currentcontext /currentflat +% 280 + /currenthalftone /currenthalftonephase /currentmiterlimit /currentobjectformat /currentpacking + /currentscreen /currentstrokeadjust /currenttransfer /currentundercolorremoval /defaultmatrix + /definefont /deletefile /detach /deviceinfo /dictstack + /echo /erasepage /errordict /execstack /executeonly +% 300 + /exp /false /filenameforall /fileposition /fork + /framedevice /grestoreall /handleerror /initclip /initgraphics + /initmatrix /instroke /inustroke /join /kshow + /ln /lock /log /mark /monitor +% 320 + /noaccess /notify /nulldevice /packedarray /quit + /rand /rcheck /readonly /realtime /renamefile + /renderbands /resetfile /reversepath /rootfont /rrand + /run /scheck /setblackgeneration /setcachelimit /setcacheparams +% 340 + /setcolorscreen /setcolortransfer /setfileposition /setflat /sethalftone + /sethalftonephase /setmiterlimit /setobjectformat /setpacking /setscreen + /setstrokeadjust /settransfer /setucacheparams /setundercolorremoval /sin + /sqrt /srand /stack /status /statusdict +% 360 + /true /ucachestatus /undefinefont /usertime /ustrokepath + /version /vmreclaim /vmstatus /wait /wcheck + /xcheck /yield /defineuserobject /undefineuserobject /UserObjects + /cleardictstack +% 376 + /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 + /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 +% 428 + /setvmthreshold (<<) cvn + (>>) cvn /currentcolorrendering /currentdevparams /currentoverprint /currentpagedevice + /currentsystemparams /currentuserparams /defineresource /findencoding /gcheck +% 440 + /glyphshow /languagelevel /product /pstack /resourceforall + /resourcestatus /revision /serialnumber /setcolorrendering /setdevparams + /setoverprint /setsystemparams /setuserparams /startjob /undefineresource + /GlobalFontDirectory /ASCII85Decode /ASCII85Encode /ASCIIHexDecode /ASCIIHexEncode +% 460 + /CCITTFaxDecode /CCITTFaxEncode /DCTDecode /DCTEncode /LZWDecode + /LZWEncode /NullEncode /RunLengthDecode /RunLengthEncode /SubFileDecode + /CIEBasedA /CIEBasedABC /DeviceCMYK /DeviceGray /DeviceRGB + /Indexed /Pattern /Separation +% 478 -- end +.packtomark + +% Install the system and user name tables. +% The user name table is read-only for ordinary programs, +% since it doesn't obey save/restore and must be managed specially. + +dup /SystemNames exch def +100 array readonly dup /UserNames exch def +.installnames + +% Define printobject and writeobject. +% These are mostly implemented in PostScript, so that we don't have to +% worry about interrupts or callbacks when writing to the output file. + +% Define procedures for accumulating the space required to represent +% an object in binary form. +/cntdict mark % <#refs> <#chars> -proc- <#refs> <#chars> + /integertype /pop load + /realtype 1 index + /marktype 1 index + /nulltype 1 index + /booleantype 1 index + /nametype { length add } bind + /stringtype 1 index + /arraytype null + WRITEDICTS { /dicttype null } if +.dicttomark def +cntdict /arraytype + { dup dup length 5 -1 roll add 4 2 roll + { dup type //cntdict exch get exec } forall + } bind put +WRITEDICTS + { cntdict /dicttype + { dup dup length 2 mul 5 -1 roll add 4 2 roll + { 4 1 roll dup type //cntdict exch get exec + 3 -1 roll dup type //cntdict exch get exec + } forall + } bind put + } if + +/w2dict mark + /nametype { 2 copy .writecvs pop } bind + /stringtype 1 index +.dicttomark def + +/.writeobjects % .writeobjects - + { + mark exch + + % Count the space required for refs and strings. + dup length 0 3 -1 roll + % Stack: -mark- <#refs> <#chars> + + dup 4 1 roll + { dup type //cntdict exch get exec + } forall + + % Write the header. + % Stack: -mark- ... <#refs> <#chars> + counttomark 3 add -2 roll 4 1 roll + % Stack: -mark- ... <#refs> <#chars> + dup counttomark 1 sub index length + 4 index 3 bitshift 4 index add + (xxxxxxxx) .bosheader writestring + + % Write the objects per se. + 3 1 roll pop + counttomark 1 sub index length 3 bitshift exch + 3 bitshift + % Stack: -mark- ... + + counttomark 4 sub + { counttomark -1 roll dup 6 1 roll + dup type /dicttype eq % can't be first object + { { 5 1 roll (xxxxxxxx) .bosobject + 3 index exch writestring + 4 -1 roll (xxxxxxxx) .bosobject + 3 index exch writestring + } forall + } + { { (xxxxxxxx) .bosobject + dup 1 6 index put + 3 index exch writestring + 4 -1 roll pop 0 4 1 roll % clear tag + } forall + } + ifelse + } + repeat + + % Write the strings and names. + pop pop exch pop + % Stack: -mark- ... + + counttomark 1 sub + { counttomark -1 roll + { % The counting pass ensured that the keys and values + % of any dictionary must be writable objects. + % Hence, we are processing a dictionary iff + % the next-to-top stack element is not a file. + 1 index type /filetype ne + { exch 2 index exch dup type //w2dict exch .knownget + { exec } { pop } ifelse pop + } + if + dup type //w2dict exch .knownget { exec } { pop } ifelse + } forall + } + repeat + + % Clean up. + % Stack: -mark- + + pop pop + + } odef +currentdict /cntdict .undef +currentdict /w2dict .undef + +/printobject { (%stdout) (w) file 3 1 roll writeobject } odef +/writeobject { exch 1 array astore .writeobjects } odef + +% Implement binary error message output. + /.printerror + { $error /binary get .languagelevel 2 eq and + { currentobjectformat 0 ne + { [ /Error $error /errorname get $error /command get false + ] 250 printobject + } + //.printerror + ifelse + } + //.printerror + ifelse + } bind def + +% End of level2dict + +end +.setlanguagelevel diff --git a/pstoraster/gs_ccfnt.ps b/pstoraster/gs_ccfnt.ps new file mode 100644 index 0000000000..faec930f9c --- /dev/null +++ b/pstoraster/gs_ccfnt.ps @@ -0,0 +1,98 @@ +% Copyright (C) 1994, 1996 Aladdin Enterprises. All rights reserved. +% +% This file is part of GNU Ghostscript. +% +% GNU Ghostscript is distributed in the hope that it will be useful, but +% WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to +% anyone for the consequences of using it or for whether it serves any +% particular purpose or works at all, unless he says so in writing. Refer to +% the GNU General Public License for full details. +% +% Everyone is granted permission to copy, modify and redistribute GNU +% Ghostscript, but only under the conditions described in the GNU General +% Public License. A copy of this license is supposed to have been given to +% you along with GNU Ghostscript so you can know your rights and +% responsibilities. It should be in a file named COPYING. Among other +% things, the copyright notice and this notice must be preserved on all +% copies. +% +% Aladdin Enterprises is not affiliated with the Free Software Foundation or +% the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, +% does not depend on any other GNU software. + +% Find and register all the precompiled font operators in systemdict. + +/registerfont % registerfont + { DEBUG { (Registering ) print 1 index = } if + dup begin + Encoding type /nametype eq + { Encoding .findencoding /Encoding exch def + } + if + dup /PrefEnc known + { PrefEnc type /nametype eq + { PrefEnc .findencoding /PrefEnc exch def + } + if + } + if + dup /FDepVector known + { /FDepVector [ FDepVector + { FontDirectory 1 index .knownget + { exch pop } + { ccfonts 1 index .knownget + { registerfont + } + { Fontmap 1 index known + { findfont } + { pop NullFont } + ifelse + } + ifelse + } + ifelse + } + forall ] readonly def + } + if + end + % Use the value of definefont appropriate at run-time, not bind-time + /definefont load exec + } bind odef +% Bind recursive call (bind descends into oparrays: feature!) +/registerfont dup load bind def + +/.loadinitialfonts { + //.loadinitialfonts exec + /ccfonts mark + 0 1 null .getccfont 1 sub { .getccfont dup /FontName get exch } for + .dicttomark def + ccfonts + { FontDirectory 2 index known { pop pop } { registerfont pop } ifelse } + forall + currentdict /ccfonts .undef +} bind def + +currentdict /registerfont .undef + + +% If we're in a Level 2 system but running in Level 1 mode, +% register the fonts explicitly as resources. +% This is a bit of a hack, but doing better is too much work. + +/level2dict where + { pop /findresource where + { % Level 2 system, Level 2 mode + pop + } + { % Level 2 system, Level 1 mode + /Font /Category level2dict /findresource get exec begin + FontDirectory + { dup .gcheck { Instances } { LocalInstances } ifelse + 3 1 roll [exch 0 -1] .growput + } + forall end + } + ifelse + } +if diff --git a/pstoraster/gs_cidfn.ps b/pstoraster/gs_cidfn.ps new file mode 100644 index 0000000000..395986462c --- /dev/null +++ b/pstoraster/gs_cidfn.ps @@ -0,0 +1,127 @@ +% Copyright (C) 1995 Aladdin Enterprises. All rights reserved. +% +% This file is part of GNU Ghostscript. +% +% GNU Ghostscript is distributed in the hope that it will be useful, but +% WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to +% anyone for the consequences of using it or for whether it serves any +% particular purpose or works at all, unless he says so in writing. Refer to +% the GNU General Public License for full details. +% +% Everyone is granted permission to copy, modify and redistribute GNU +% Ghostscript, but only under the conditions described in the GNU General +% Public License. A copy of this license is supposed to have been given to +% you along with GNU Ghostscript so you can know your rights and +% responsibilities. It should be in a file named COPYING. Among other +% things, the copyright notice and this notice must be preserved on all +% copies. +% +% Aladdin Enterprises is not affiliated with the Free Software Foundation or +% the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, +% does not depend on any other GNU software. + +% ProcSet for implementing CID-keyed fonts. +% When this is run, systemdict is still writable. + +%**************** This file is not ready for use: +% - It doesn't include the actual character mapper (BuildGlyph). +% - It loads the entire font into RAM. +% - It has never been tested on a real font. + +/.setlanguagelevel where { pop 2 .setlanguagelevel } if +.currentglobal true .setglobal + +/GS_CIDInit_ProcSet 30 dict dup begin + +% ---------------- CIDFont operators ---------------- % + +/StartData % <(Binary)|(Hex)> + % StartData - + { 2 index begin % CID font dict + 20 dict begin % temporary dict + /datalength exch def + (Hex) eq /hex exch def + /cidfont exch def + /startdata currentfile fileposition def + + % Read the character data into an array of strings. + % There's no particular reason to prefer long strings over short, + % so we just create a separate string for each character. + + /charstrings CIDCount array def + /fontindices CIDCount FDBytes 1 eq { string } { array } ifelse def + 0 1 CIDCount 1 sub + { /cid exch def + currentfile FDBytes GDBytes add cid mul startdata add setfileposition + fontindices cid FDBytes .readint put + charstrings cid + /pos GDBytes .readint def + FDBytes .readint pop % skip FD of next entry + GDBytes .readint pos sub + dup 0 eq + { pop null } + { currentfile pos setfileposition string readstring pop } + ifelse put + } + for + + % Process each font in the FDArray. + % For Type 3 fonts, just do a definefont with an empty Encoding. + % For Type 1 fonts, read the Subrs (don't bother to check for + % duplicates), and set CharStrings to the character data array. + % We don't support embedded Type 0 fonts, but it isn't clear + % whether they're allowed anyway. + + cidfont /FDepVector [ FDArray + { dup /FontType get 1 eq + { dup /CharStrings charstrings put + /Private get + dup /SubrCount known + { begin /Subrs [ % Private + 0 1 SubrCount 1 sub + { SDBytes mul SubrMapOffset add startdata add + currentfile exch setfileposition + /pos SDBytes .readint def + SDBytes .readint pos sub + currentfile pos setfileposition string readstring pop + } + ] readonly def end % Private + } + if pop + } + if + dup /Encoding [] put + dup /FontName get exch definefont + } + forall ] readonly def + + % Install the rest of the data in the font. + + cidfont /CharStrings charstrings readonly put + cidfont /FontIndices fontindices readonly put + FontName cidfont /CIDFont defineresource pop + + % Wrap up. + + end % temporary dict + end % CID font dict + end % resource dict + } bind def + +/.readint % .readint + { 0 exch { 8 bitshift currentfile read pop add } repeat + } bind def + +% ---------------- Resource category definition ---------------- % + +end readonly def + +/defineresource where + { pop + /CIDFont /Generic /Category findresource dup length dict .copydict + /Category defineresource pop + /CIDInit GS_CIDInit_ProcSet /ProcSet defineresource pop + } +if + +.setglobal diff --git a/pstoraster/gs_cmap.ps b/pstoraster/gs_cmap.ps new file mode 100644 index 0000000000..8b699811ec --- /dev/null +++ b/pstoraster/gs_cmap.ps @@ -0,0 +1,235 @@ +% Copyright (C) 1995 Aladdin Enterprises. All rights reserved. +% +% This file is part of GNU Ghostscript. +% +% GNU Ghostscript is distributed in the hope that it will be useful, but +% WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to +% anyone for the consequences of using it or for whether it serves any +% particular purpose or works at all, unless he says so in writing. Refer to +% the GNU General Public License for full details. +% +% Everyone is granted permission to copy, modify and redistribute GNU +% Ghostscript, but only under the conditions described in the GNU General +% Public License. A copy of this license is supposed to have been given to +% you along with GNU Ghostscript so you can know your rights and +% responsibilities. It should be in a file named COPYING. Among other +% things, the copyright notice and this notice must be preserved on all +% copies. +% +% Aladdin Enterprises is not affiliated with the Free Software Foundation or +% the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, +% does not depend on any other GNU software. + +% ProcSet for implementing CMap resource. +% When this is run, systemdict is still writable. + +%**************** This file is not ready for use: +% - Rearranged fonts are not implemented. +% - It has never been tested on a real font. + +/.setlanguagelevel where { pop 2 .setlanguagelevel } if +.currentglobal true .setglobal + +/GS_CMapInit_ProcSet 30 dict dup begin + +% ---------------- CMap operators ---------------- % + +% We create the following structures for character code mapping. +% Map - a multi-level array indexed by the successive bytes of +% the character code. All of the arrays are read-only. +% NotdefMap - the same. + +% ------ Font-level operators ------ % + +% composefont doesn't appear in CMap files -- it's documented in +% the "PostScript Language Reference Manual Supplement". +/composefont % composefont + { exch dup /dicttype ne { /CMap findresource } if + 10 dict + dup /FontType 0 put + dup /FMapType 9 put + dup /CMap 5 -1 roll put + dup /Encoding [ 0 1 6 index length 1 sub { } for ] put + dup /FDepVector 4 -1 roll put + /Font defineresource + } bind def + +/begincmap % - begincmap - + { /Map 256 array def + /NotdefMap 256 array def + } bind def +/endcmap % - endcmap - + { /Map Map .endmap def + /NotdefMap NotdefMap .endmap def + } bind def + +/begincodespacerange % begincodespacerange - + { pop mark + } bind def +/endcodespacerange % ... endcodespacerange - + { counttomark 2 idiv + { 2 copy Map .addcodespacerange NotdefMap .addcodespacerange + } repeat pop + } bind def + +/.addcodespacerange % .addcodespacerange - + { 2 index length 1 eq + { 2 { 3 -1 roll 0 get } repeat 1 exch + { 2 copy 0 put pop } for pop + } + { 2 index 0 get 1 3 index 0 get + 6 -2 roll + 2 { 1 1 index length 1 sub getinterval 6 1 roll } repeat + % Stack: lo hi map lo0 1 hi0 + { 2 copy get null eq { 2 copy 256 array put } if + 4 copy get .addcodespacerange pop + } + for pop pop pop + } + ifelse + } bind def +/.endmap % .endmap + { dup type /arraytype eq { dup { .endmap exch } forall astore readonly } if + } bind def + +/usecmap % usecmap - + { /CMap findresource + dup length dict .copydict + currentdict end exch .copydict begin + } bind def + +% ------ Rearranged font operators ------ % + +/beginrearrangedfont % beginrearrangedfont - + { (NOT IMPLEMENTED YET.\n) print flush + } bind def +/endrearrangedfont % - endrearrangedfont - + { (NOT IMPLEMENTED YET.\n) print flush + } bind def + +/usefont % usefont - + { (NOT IMPLEMENTED YET.\n) print flush + } bind def + +/beginusematrix % beginusematrix - + { (NOT IMPLEMENTED YET.\n) print flush + } bind def +/endusematrix % endusematrix - + { (NOT IMPLEMENTED YET.\n) print flush + } bind def + +% ------ Character name/code selector operators ------ % + +/beginbfchar % beginbfchar - + { pop mark + } bind def +/endbfchar % ... endbfchar + { Map .endmapchar /Map exch store pop + } bind def + +/beginbfrange % beginbfrange - + { pop mark + } bind def +/endbfrange % ... + % endbfrange - + { Map counttomark 3 idiv { .addbfrange } repeat /Map exch store pop + } bind def + +/.addbfrange % + % .addbfrange + { 1 index type /stringtype eq + { { dup length string copy dup dup length 1 sub 2 copy get 1 add put } + exch .addmaprange + } + { 2 dict begin exch /codes 1 index def 0 get exch + { codes dup length 1 sub 1 exch getinterval /codes 1 index def + dup length 0 gt { 0 get } if + } + exch .addmaprange end + } + ifelse exch pop + } bind def + +% ------ CID selector operators ------ % + +/begincidchar % begincidchar - + { pop mark + } bind def +/endcidchar % ... endcidchar - + { Map .endmapchar /Map exch store pop + } bind def + +/begincidrange % begincidrange - + { pop mark + } bind def +/endcidrange % ... endcidrange - + { Map counttomark 3 idiv { { 1 add } exch .addmaprange exch pop } repeat + /Map exch store pop + } bind def + +/.endmapchar % ... .endmapchar - + { counttomark 2 idiv + { 2 index 3 1 roll { } exch .addmaprange exch pop + } repeat exch pop + } bind def + +/.addmaprange % + % .addcidrange + { % We may be updating a (partly) read-only map from another CMap. + % If so, implement copy-on-write. + dup wcheck not { dup length array copy } if + 4 index length 1 eq + { 2 { 5 -1 roll 0 get } repeat 1 exch + { % Stack: value proc map code + 2 copy 5 index put pop + 3 -1 roll 2 index exec 3 1 roll + } for + } + { 4 index 0 get 1 5 index 0 get + 8 -2 roll + 2 { 1 1 index length 1 sub getinterval 8 1 roll } repeat + % Stack: lo hi next proc map lo0 1 hi0 + { 6 copy get .addmaprange + % Stack: lo hi oldnext proc map i next submap + exch 6 1 roll 5 -1 roll pop + % Stack: lo hi next proc map i submap + 3 copy put pop pop + } + for 5 -2 roll pop pop + } + ifelse exch pop + } bind def + +% ------ notdef operators ------ % + +/beginnotdefchar % beginnotdefchar - + { pop mark + } bind def +/endnotdefchar % ... endnotdefchar - + { counttomark 2 idiv { 1 index exch .addnotdefrange } repeat pop + } bind def + +/beginnotdefrange % beginnotdefrange - + { pop mark + } bind def +/endnotdefrange % ... endnotdefrange - + { counttomark 3 idiv { .addnotdefrange } repeat pop + } bind def + +/.addnotdefrange % .addnotdefrange - + { { } NotdefMap .addmaprange /NotdefMap exch store pop + } bind def + +% ---------------- Resource category definition ---------------- % + +end readonly def + +/defineresource where + { pop + /CMap /Generic /Category findresource dup length dict .copydict + /Category defineresource pop + /CMapInit GS_CMapInit_ProcSet /ProcSet defineresource pop + } +if + +.setglobal diff --git a/pstoraster/gs_cmdl.ps b/pstoraster/gs_cmdl.ps new file mode 100644 index 0000000000..ad6dfbcc05 --- /dev/null +++ b/pstoraster/gs_cmdl.ps @@ -0,0 +1,186 @@ +% Copyright (C) 1994, 1996 Aladdin Enterprises. All rights reserved. +% +% This file is part of GNU Ghostscript. +% +% GNU Ghostscript is distributed in the hope that it will be useful, but +% WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to +% anyone for the consequences of using it or for whether it serves any +% particular purpose or works at all, unless he says so in writing. Refer to +% the GNU General Public License for full details. +% +% Everyone is granted permission to copy, modify and redistribute GNU +% Ghostscript, but only under the conditions described in the GNU General +% Public License. A copy of this license is supposed to have been given to +% you along with GNU Ghostscript so you can know your rights and +% responsibilities. It should be in a file named COPYING. Among other +% things, the copyright notice and this notice must be preserved on all +% copies. +% +% Aladdin Enterprises is not affiliated with the Free Software Foundation or +% the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, +% does not depend on any other GNU software. + +% Parse and execute the command line. +% C code handles the following switches: -h/-? -I -M -v + +/cmddict 50 dict def +cmddict begin + +% ---------------- Utility procedures ---------------- % + +% Get the next argument from the parsed argument list. +/nextarg % - nextarg true + % - nextarg false + { argv length 0 eq + { false } + { argv dup 0 get exch dup length 1 sub 1 exch getinterval /argv exch def } + ifelse + } bind def + +% Run a file, under job control if implemented. +/runjob % runjob - + { end % cmddict + /startjob where { pop false () startjob pop } + run + //cmddict begin + } bind def +/runfilejob % runfilejob - + { findlibfile { exch pop } { (r) file } runjob + } bind def + +% Expand arguments. Free variables: expand@. +/expandarg % expandarg + { dup () eq + { pop + } + { dup dup (--) eq exch (-+) eq or + { pop /expand@ false def + } + { expand@ { (@) anchorsearch } { false } ifelse + { pop findlibfile + { exch pop } + { (r) file } % let the error happen + expandargfile + } + if + } + ifelse + } + } bind def +/expandargfile % expandargfile + { [ exch cvlit + { token not { exit } if + dup type /stringtype ne { =string cvs dup length string copy } if + expandarg + } + /exec cvx + ] cvx loop + } bind def + +% ---------------- Recognized switches ---------------- % + +% Switches with arguments are defined as ; +% switches without arguments are defined as -. + +% Switches without arguments +/-- + { nextarg not + { (-- and -+ require a file name.\n) print flush } + { //systemdict /ARGUMENTS argv put /argv [] def runjob } + ifelse + } bind def +/-+ /-- load def +/-@ /-- load def +/-A { (@) Z } bind def +/-c + { { argv length 0 eq { exit } if + argv 0 get (-) anchorsearch { pop pop exit } if + pop nextarg token + { exch pop % Probably should check for empty. + end exec //cmddict begin + } + if + } + loop + } bind def +/-e { (#) Z } bind def +/-E /-e load def +/-f { } def +/-q { //systemdict /QUIET true put } bind def + +% Switches with arguments +/d + { (=) search not { (#) search not { () exch dup } if } if + exch pop cvn dup where + { pop (Redefining ) print print ( is not allowed.\n) print flush pop } + { exch token + { exch pop } % Probably should check for empty. + { true } + ifelse + //systemdict 3 1 roll put + } + ifelse + } bind def +/D /d load def +/f { dup length 0 ne { runfilejob } if } bind def +/g + { (x) search { cvi pop exch cvi } { cvi dup } ifelse + //systemdict begin /DEVICEHEIGHT exch def /DEVICEWIDTH exch def end + } bind def +/r + { (x) search { cvr pop exch cvr } { cvr dup } ifelse + //systemdict begin /DEVICEYRESOLUTION exch def /DEVICEXRESOLUTION exch def end + } bind def +/s + { (=) search not { (#) search not { () exch dup } if } if + exch pop cvn dup where { pop dup load } { () } ifelse + type /stringtype ne + { (Redefining ) print print ( is not allowed.\n) print flush pop } + { exch //systemdict 3 1 roll put } + ifelse + } bind def +/S /s load def +/Z { true .setdebug } bind def + +% ---------------- Main program ---------------- % + +% We process the command line in two passes. In the first pass, +% we read and expand any @-files as necessary. The second pass +% does the real work. + +/cmdstart + { //cmddict begin + /expand@ true def + [ + % Process the GS_OPTIONS environment variable. + (GS_OPTIONS) getenv { 0 () /SubFileDecode filter expandargfile } if + % Process the actual command line. + .getargv { expandarg } forall + ] readonly /argv exch def + % Now interpret the commands. + { nextarg not { exit } if + dup 0 get (-) 0 get eq + { dup length 1 eq + { pop (%stdin) (r) file runjob + } + { dup length 2 gt + { dup dup length 2 sub 2 exch getinterval exch 1 1 getinterval } + if currentdict .knownget + { exec + } + { (Ignoring unknown switch ) print + dup length 1 eq { (-) print print } if print + (\n) print flush + } + ifelse + } + ifelse + } + { runfilejob + } + ifelse + } + loop end + } bind def + +end % cmddict diff --git a/pstoraster/gs_dbt_e.ps b/pstoraster/gs_dbt_e.ps new file mode 100644 index 0000000000..70c1537623 --- /dev/null +++ b/pstoraster/gs_dbt_e.ps @@ -0,0 +1,65 @@ +% Copyright (C) 1993, 1994 Aladdin Enterprises. All rights reserved. +% +% This file is part of GNU Ghostscript. +% +% GNU Ghostscript is distributed in the hope that it will be useful, but +% WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to +% anyone for the consequences of using it or for whether it serves any +% particular purpose or works at all, unless he says so in writing. Refer to +% the GNU General Public License for full details. +% +% Everyone is granted permission to copy, modify and redistribute GNU +% Ghostscript, but only under the conditions described in the GNU General +% Public License. A copy of this license is supposed to have been given to +% you along with GNU Ghostscript so you can know your rights and +% responsibilities. It should be in a file named COPYING. Among other +% things, the copyright notice and this notice must be preserved on all +% copies. +% +% Aladdin Enterprises is not affiliated with the Free Software Foundation or +% the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, +% does not depend on any other GNU software. + +% Define the Dingbats encoding vector. +/currentglobal where + { pop currentglobal { setglobal } true setglobal } + { { } } +ifelse +/DingbatsEncoding +% \000 + StandardEncoding 0 32 getinterval aload pop % /.notdef +% \040 + /space /a1 /a2 /a202 /a3 /a4 /a5 /a119 + /a118 /a117 /a11 /a12 /a13 /a14 /a15 /a16 + /a105 /a17 /a18 /a19 /a20 /a21 /a22 /a23 + /a24 /a25 /a26 /a27 /a28 /a6 /a7 /a8 +% \100 + /a9 /a10 /a29 /a30 /a31 /a32 /a33 /a34 + /a35 /a36 /a37 /a38 /a39 /a40 /a41 /a42 + /a43 /a44 /a45 /a46 /a47 /a48 /a49 /a50 + /a51 /a52 /a53 /a54 /a55 /a56 /a57 /a58 +% \140 + /a59 /a60 /a61 /a62 /a63 /a64 /a65 /a66 + /a67 /a68 /a69 /a70 /a71 /a72 /a73 /a74 + /a203 /a75 /a204 /a76 /a77 /a78 /a79 /a81 + /a82 /a83 /a84 /a97 /a98 /a99 /a100 /.notdef +% \200 + StandardEncoding 0 32 getinterval aload pop % /.notdef +% \240 + /.notdef /a101 /a102 /a103 /a104 /a106 /a107 /a108 + /a112 /a111 /a110 /a109 /a120 /a121 /a122 /a123 + /a124 /a125 /a126 /a127 /a128 /a129 /a130 /a131 + /a132 /a133 /a134 /a135 /a136 /a137 /a138 /a139 +% \300 + /a140 /a141 /a142 /a143 /a144 /a145 /a146 /a147 + /a148 /a149 /a150 /a151 /a152 /a153 /a154 /a155 + /a156 /a157 /a158 /a159 /a160 /a161 /a163 /a164 + /a196 /a165 /a192 /a166 /a167 /a168 /a169 /a170 +% \340 + /a171 /a172 /a173 /a162 /a174 /a175 /a176 /a177 + /a178 /a179 /a193 /a180 /a199 /a181 /a200 /a182 + /.notdef /a201 /a183 /a184 /a197 /a185 /a194 /a198 + /a186 /a195 /a187 /a188 /a189 /a190 /a191 /.notdef +256 packedarray .defineencoding +3 DingbatsEncoding .registerencoding +exec diff --git a/pstoraster/gs_diskf.ps b/pstoraster/gs_diskf.ps new file mode 100644 index 0000000000..4d55fd6f13 --- /dev/null +++ b/pstoraster/gs_diskf.ps @@ -0,0 +1,230 @@ +% Copyright (C) 1996 Aladdin Enterprises. All rights reserved. +% +% This file is part of GNU Ghostscript. +% +% GNU Ghostscript is distributed in the hope that it will be useful, but +% WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to +% anyone for the consequences of using it or for whether it serves any +% particular purpose or works at all, unless he says so in writing. Refer to +% the GNU General Public License for full details. +% +% Everyone is granted permission to copy, modify and redistribute GNU +% Ghostscript, but only under the conditions described in the GNU General +% Public License. A copy of this license is supposed to have been given to +% you along with GNU Ghostscript so you can know your rights and +% responsibilities. It should be in a file named COPYING. Among other +% things, the copyright notice and this notice must be preserved on all +% copies. +% +% Aladdin Enterprises is not affiliated with the Free Software Foundation or +% the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, +% does not depend on any other GNU software. + +% Support for converting Type 1 fonts without eexec encryption to +% Type 4 fonts that load individual character outlines on demand. + +% If DISKFONTS is true, we load individual CharStrings as they are needed. +% (This is intended primarily for machines with very small memories.) +% Initially, the character definition is the file position of the definition; +% this gets replaced with the actual CharString. +% Note that if we are loading characters lazily, CharStrings is writable. + +% _Cstring must be long enough to hold the longest CharString for +% a character defined using seac. This is lenIV + 4 * 5 (for the operands +% of sbw, assuming div is not used) + 2 (for sbw) + 3 * 5 (for the operands +% of seac other than the character codes) + 2 * 2 (for the character codes) +% + 2 (for seac), i.e., lenIV + 43. + +/_Cstring 60 string def + +% When we initially load the font, we call +% cskip_C +% to skip over each character definition and return the file position instead. +% This substitutes for the procedure +% string currentfile exch read[hex]string pop +% [encrypt] +% What we actually store in the CharString is fileposition * 1000 + length, +% negated if the string is stored in binary form. + +/cskip_C + { exch dup 1000 ge 3 index type /nametype ne or + { % This is a Subrs string, or the string is so long we can't represent + % its length. Load it now. + exch exec + } + { % Record the position and length, and skip the string. + dup currentfile fileposition 1000 mul add + 2 index 3 get /readstring cvx eq { neg } if + 3 1 roll + dup _Cstring length idiv + { currentfile _Cstring 3 index 3 get exec pop pop + } repeat + _Cstring length mod _Cstring exch 0 exch getinterval + currentfile exch 3 -1 roll 3 get exec pop pop + } + ifelse + } bind def + +% Load a CharString from the file. The font is the top entry +% on the dictionary stack. +/load_C % load_C - + { dup abs 1000 idiv FontFile exch setfileposition + CharStrings 3 1 roll + .currentglobal CharStrings .gcheck .setglobal exch + dup 0 lt + { neg 1000 mod string FontFile exch readstring } + { 1000 mod string FontFile exch readhexstring } + ifelse pop + exch .setglobal +% If the CharStrings aren't encrypted on the file, encrypt now. + Private /-| get 0 get + dup type /nametype ne + { dup length 5 sub 5 exch getinterval exec } + { pop } + ifelse dup 4 1 roll put +% If the character is defined with seac, load its components now. + mark exch seac_C + counttomark + { StandardEncoding exch get dup CharStrings exch get + dup type /integertype eq { load_C } { pop pop } ifelse + } repeat + pop % the mark + } bind def + +/seac_C % seac_C ..or nothing.. + { dup length _Cstring length le + { 4330 exch _Cstring .type1decrypt exch pop + dup dup length 2 sub 2 getinterval <0c06> eq % seac + { dup length + Private /lenIV known { Private /lenIV get } { 4 } ifelse + exch 1 index sub getinterval +% Parse the string just enough to extract the seac information. +% We assume that the only possible operators are hsbw, sbw, and seac, +% and that there are no 5-byte numbers. + mark 0 3 -1 roll + { exch + { { dup 32 lt + { pop 0 } + { dup 247 lt + { 139 sub 0 } + { dup 251 lt + { 247 sub 256 mul 108 add 1 1 } + { 251 sub -256 mul -108 add -1 1 } + ifelse + } + ifelse + } + ifelse + } % 0 + { mul add 0 } % 1 + } + exch get exec + } + forall pop + counttomark 1 add 2 roll cleartomark % pop all but achar bchar + } + { pop % not seac + } + ifelse + } + { pop % punt + } + ifelse + } bind def + +% Define replacement procedures for loading fonts. +% If DISKFONTS is true and the body of the font is not encrypted with eexec: +% - Prevent the CharStrings from being made read-only. +% - Substitute a different CharString-reading procedure. +% (eexec disables this because the implicit 'systemdict begin' hides +% the redefinitions that make the scheme work.) +% We assume that: +% - The magic procedures (-|, -!, |-, and |) are defined with +% executeonly or readonly; +% - The contents of the reading procedures are as defined in bdftops.ps; +% - The font includes the code +% /CharStrings readonly put +/.loadfontdict 6 dict def mark + /begin % push this dict after systemdict + { dup begin + //systemdict eq { //.loadfontdict begin } if + } bind + /end % match begin + { currentdict end + //.loadfontdict eq currentdict //systemdict eq and { end } if + } bind + /dict % leave room for FontFile, BuildChar, BuildGlyph + { 3 add dict + } bind + /executeonly % for reading procedures + { readonly + } + /noaccess % for Subrs strings and Private dictionary + { readonly + } + /readonly % for procedures and CharStrings dictionary + { % We want to take the following non-standard actions here: + % - If the operand is the CharStrings dictionary, do nothing; + % - If the operand is a number (a file position replacing the + % actual CharString), do nothing; + % - If the operand is either of the reading procedures (-| or -!), + % substitute a different one. + dup type /dicttype eq % CharStrings or Private + count 2 gt and + { 1 index /CharStrings ne { readonly } if } + { dup type /arraytype eq % procedure or data array + { dup length 5 ge 1 index xcheck and + { dup 0 get /string eq + 1 index 1 get /currentfile eq and + 1 index 2 get /exch eq and + 1 index 3 get dup /readstring eq exch /readhexstring eq or and + 1 index 4 get /pop eq and + { /cskip_C cvx 2 packedarray cvx + } + { readonly + } + ifelse + } + { readonly + } + ifelse + } + { dup type /stringtype eq % must be a Subr string + { readonly } + if + } + ifelse + } + ifelse + } bind + /definefont % to insert BuildChar/Glyph and change FontType + { dup /FontType get 1 eq + { dup /FontType 4 put + dup /BuildChar /build_C load put + dup /BuildGlyph /build_C load put + } + if definefont + } bind +counttomark 2 idiv { .loadfontdict 3 1 roll put } repeat pop +.loadfontdict readonly pop + +% Define the BuildChar and BuildGlyph procedures for modified fonts. +% A single procedure serves for both. +/build_C % build_C - + { 1 index begin + dup dup type /integertype eq { Encoding exch get } if + % Stack: font code|name name + dup CharStrings exch .knownget not + { 2 copy eq { exch pop /.notdef exch } if + QUIET not + { (Substituting .notdef for ) print = flush } + { pop } + ifelse + /.notdef CharStrings /.notdef get + } if + % Stack: font code|name name charstring + dup type /integertype eq + { load_C end build_C } + { end .type1execchar } + ifelse + } bind def diff --git a/pstoraster/gs_dps1.ps b/pstoraster/gs_dps1.ps new file mode 100644 index 0000000000..ebf5e98883 --- /dev/null +++ b/pstoraster/gs_dps1.ps @@ -0,0 +1,307 @@ +% Copyright (C) 1990, 1996 Aladdin Enterprises. All rights reserved. +% +% This file is part of GNU Ghostscript. +% +% GNU Ghostscript is distributed in the hope that it will be useful, but +% WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to +% anyone for the consequences of using it or for whether it serves any +% particular purpose or works at all, unless he says so in writing. Refer to +% the GNU General Public License for full details. +% +% Everyone is granted permission to copy, modify and redistribute GNU +% Ghostscript, but only under the conditions described in the GNU General +% Public License. A copy of this license is supposed to have been given to +% you along with GNU Ghostscript so you can know your rights and +% responsibilities. It should be in a file named COPYING. Among other +% things, the copyright notice and this notice must be preserved on all +% copies. +% +% Aladdin Enterprises is not affiliated with the Free Software Foundation or +% the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, +% does not depend on any other GNU software. + +% Initialization file for analogs of Display PostScript functions +% that are also included in Level 2. +% When this is run, systemdict is still writable, +% but (almost) everything defined here goes into level2dict. + +level2dict begin + +% ------ Virtual memory ------ % + +/currentshared /.currentglobal load def +/scheck /.gcheck load def +%****** FOLLOWING IS WRONG ****** +/shareddict currentdict /globaldict .knownget not { 20 dict } if def + +% Global and LocalFontDirectory must remain in systemdict +% even if we temporarily exit Level 2 mode. + +end % level2dict +systemdict begin + +/SharedFontDirectory FontDirectory .gcheck + { .currentglobal false .setglobal + /LocalFontDirectory FontDirectory dup maxlength dict copy def + .setglobal FontDirectory + } + { /LocalFontDirectory FontDirectory def + 50 dict + } +ifelse def + +end % systemdict +level2dict begin + +% setshared must rebind FontDirectory to the appropriate one of +% Local or SharedFontDirectory. + +/.setglobal + { .setglobal + //systemdict /FontDirectory .currentglobal + { //SharedFontDirectory } + { //systemdict /LocalFontDirectory get } % can't embed ref to local VM + ifelse .forceput + } .bind odef % must bind .forceput and .setglobal + % even if NOBIND in effect +/setshared /.setglobal load def +.currentglobal setshared + +% ------ Fonts ------ % + +/selectfont + { exch findfont exch + dup type /arraytype eq { makefont } { scalefont } ifelse + setfont + } odef +% Undefinefont has to take local/global VM into account. +/undefinefont + { FontDirectory 1 index .undef + .currentglobal + { % Current mode is global; delete from local directory too. + //systemdict /LocalFontDirectory .knownget + { exch .undef } + { pop } + ifelse + } + { % Current mode is local; if there was a shadowed global + % definition, copy it into the local directory. + //systemdict /SharedFontDirectory .knownget + { 1 index .knownget + { FontDirectory 3 1 roll put } + { pop } + ifelse + } + if + } + ifelse + } odef + +% If we load a font into global VM within an inner save, the restore +% will delete it from FontDirectory but not from SharedFontDirectory. +% We have to handle this by making restore copy missing entries from +% SharedFontDirectory to FontDirectory. Since this could slow down restore +% considerably, we define a new operator .dictcopynew for this purpose. +% Furthermore, if FAKEFONTS is in effect, we want global real fonts to +% override fake local ones. We handle this by brute force. +/restore + { //restore + //systemdict /LocalFontDirectory get + FAKEFONTS + { mark + % We want to delete a fake font from the local directory + % iff the global directory now has no definition for it, + % or a non-fake definition. + 1 index dup + { % Stack: lfd mark lfd key ... lfd key value + length 1 gt + { % This is a real local definition; don't do anything. + pop + } + { % This is a fake local definition, check for global. + //SharedFontDirectory 1 index .knownget + { % A global definition exists, check for fake. + length 1 eq { pop } { 1 index } ifelse + } + { % No global definition, delete the local one. + 1 index + } + ifelse + } + ifelse + } forall + pop counttomark 2 idiv { .undef } repeat pop + } + if + //SharedFontDirectory exch .dictcopynew pop + } bind odef + +% ------ Halftones ------ % + +/.makestackdict + { { counttomark -1 roll } forall .dicttomark + } bind def +/currenthalftone + { mark .currenthalftone + { { exch pop } % halftone + { /HalftoneType 1 % screen + { /Frequency /Angle /SpotFunction } + .makestackdict + } + { /HalftoneType 2 % colorscreen + { /RedFrequency /RedAngle /RedSpotFunction + /GreenFrequency /GreenAngle /GreenSpotFunction + /BlueFrequency /BlueAngle /BlueSpotFunction + /GrayFrequency /GrayAngle /GraySpotFunction + } + .makestackdict + } + } + exch get exec + } odef +% Define sethalftone so it converts all other types to type 5. +/.sethalftoneRGBV % + { 4 -1 roll exch { 1 index exch get exch } forall 15 1 roll + 14 -2 roll mark 15 1 roll { /Gray /Blue /Green /Red } + { % stack: v0 v1 v2 type keys comp + mark + 2 index 0 get 8 -1 roll + 4 index 1 get 9 -1 roll + 6 index 2 get 10 -1 roll + % stack: type keys comp mark k0 v0 k1 v1 k2 v2 + /HalftoneType 10 index .dicttomark + counttomark 2 roll + } + forall pop pop + /Default 1 index .dicttomark .sethalftone5 + } bind def +/sethalftone + { dup /HalftoneType get 1 sub + { { mark /Default 2 index .dicttomark .sethalftone5 } + { 1 { /Frequency /Angle /SpotFunction } + { /RedFrequency /RedAngle /RedSpotFunction + /GreenFrequency /GreenAngle /GreenSpotFunction + /BlueFrequency /BlueAngle /BlueSpotFunction + /GrayFrequency /GrayAngle /GraySpotFunction + } .sethalftoneRGBV + } + { mark /Default 2 index .dicttomark .sethalftone5 } + { 3 { /Width /Height /Thresholds } + { /RedWidth /RedHeight /RedThresholds + /GreenWidth /GreenHeight /GreenThresholds + /BlueWidth /BlueHeight /BlueThresholds + /GrayWidth /GrayHeight /GrayThresholds + } .sethalftoneRGBV + } + { dup .sethalftone5 } + } exch get exec + } odef +% Redefine setscreen and setcolorscreen to recognize halftone dictionaries, +% and to insert the Frequency and Angle into Type 1 halftones, per +% Adobe TN 5085. +/.fixsethalftonescreen + { dup /HalftoneType get 1 eq + { dup wcheck not { dup length .copydict } if + dup /Frequency 4 index put + dup /Angle 3 index put + } + if + } bind def +/setscreen + { dup type /dicttype eq + { .fixsethalftonescreen sethalftone pop pop } + { //setscreen } + ifelse + } odef +/setcolorscreen + { dup type /dicttype eq + { .fixsethalftonescreen sethalftone 11 { pop } repeat } + { //setcolorscreen } + ifelse + } odef +% Redefine currentscreen and currentcolorscreen to extract the Frequency +% and Angle from Type 1 halftones, per Adobe TN 5085. +/.fixcurrenthalftonescreen % .fix... + { dup /HalftoneType get 1 eq + { dup /Frequency get 1 index /Angle get } + { 60 0 } + ifelse 3 2 roll + } bind def +/currentscreen + { .currenthalftone + { { .fixcurrenthalftonescreen } % halftone + { } % screen + { 12 3 roll 9 { pop } repeat % colorscreen + dup type /dicttype eq { .fixcurrenthalftonescreen } if + } + } + exch get exec + } odef +/currentcolorscreen + { .currenthalftone + { { .fixcurrenthalftonescreen 3 copy 6 copy } % halftone + { 3 copy 6 copy } % screen + { } % colorscreen + } + exch get exec + } odef + +% ------ User objects ------ % + +/.localarray where + { pop } + { /.localarray + { currentglobal false setglobal + exch array exch setglobal + } bind def + } +ifelse +/defineuserobject + { userdict /.UserObjects known + { 1 index userdict /.UserObjects get length ge + { 1 index 1 add .localarray userdict /.UserObjects get + 1 index copy pop + userdict /.UserObjects 3 -1 roll put + } + if + } + { userdict /.UserObjects 3 index 1 add .localarray put + } + ifelse + userdict /.UserObjects get 3 1 roll put + } odef +/execuserobject + { userdict /.UserObjects get exch get exec + } odef +/undefineuserobject + { userdict /.UserObjects get exch null put + } odef + +% ------ User paths ------ % + +% We define upath carefully so it won't leave garbage on the stack +% if an error occurs. +/upath + { [ + { 1 index {/ucache cvx} if true .pathbbox /setbbox cvx + {/moveto cvx} {/lineto cvx} {/curveto cvx} {/closepath cvx} + pathforall ] + } + .internalstopped + { cleartomark /upath load $error /errorname get signalerror + } + if cvx exch pop + } odef + +% Dummy definitions for cache control operators + +/ucachestatus + { mark 0 0 0 0 0 } odef +/setucacheparams + { cleartomark } odef + +% ------ Miscellaneous ------ % + +/undef /.undef load def + +end % level2dict diff --git a/pstoraster/gs_fform.ps b/pstoraster/gs_fform.ps new file mode 100644 index 0000000000..13d6547d2e --- /dev/null +++ b/pstoraster/gs_fform.ps @@ -0,0 +1,115 @@ +% Copyright (C) 1995, 1996 Aladdin Enterprises. All rights reserved. +% +% This file is part of GNU Ghostscript. +% +% GNU Ghostscript is distributed in the hope that it will be useful, but +% WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to +% anyone for the consequences of using it or for whether it serves any +% particular purpose or works at all, unless he says so in writing. Refer to +% the GNU General Public License for full details. +% +% Everyone is granted permission to copy, modify and redistribute GNU +% Ghostscript, but only under the conditions described in the GNU General +% Public License. A copy of this license is supposed to have been given to +% you along with GNU Ghostscript so you can know your rights and +% responsibilities. It should be in a file named COPYING. Among other +% things, the copyright notice and this notice must be preserved on all +% copies. +% +% Aladdin Enterprises is not affiliated with the Free Software Foundation or +% the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, +% does not depend on any other GNU software. + +% gs_fform.ps +% Monochrome Form caching implemented in PostScript. + +% This implementation is pretty unreasonable: +% - It doesn't remember transparent pixels. +% - It reduces everything to black and white. +% - It doesn't handle halftone or Pattern phasing. +% However, it's good enough to produce some useful output. + +% In order to prevent restore from clearing the cache, we explicitly +% push the cache entries on the stack before a restore and reinstall them. +/formcachedict 20 dict def +currentglobal true setglobal +/restore + { mark formcachedict { } forall + counttomark 1 add index { restore } .internalstopped + { cleartomark restore } + { counttomark 2 idiv { formcachedict 3 1 roll put } repeat pop pop } + ifelse + } bind odef + +/.form.buffer 65000 string def +/execform + { dup /Implementation known not + { dup /FormType get 1 ne { /rangecheck signalerror } if + formcachedict 1 index .knownget not + { currentglobal true setglobal + % Stack: form global + 10 dict + dup /ImageType 1 put + dup /ImageMatrix [0 0 0 0 0 0] put + dup /DataSource + { % Stack: y (impl is on dict stack) + Height 1 index sub + //.form.buffer length Width 7 add 8 idiv idiv .min + 1 index add exch + Device exch //.form.buffer copyscanlines + } + put + dup /BitsPerComponent 1 put + dup /Decode [0 1] put + dup /Device null put + % Stack: form global impl + formcachedict 3 index 2 index put + exch setglobal + } + if 1 index /Implementation 3 -1 roll put + } + if + gsave dup /Matrix get concat + dup /Implementation get + % Check whether we can use the cached value. + % Stack: form implementation + dup /ImageMatrix get matrix currentmatrix + true 0 1 3 + { % Stack: form impl cachemat curmat true index + 3 index 1 index get exch 3 index exch get ne { pop false exit } if + } + for % Stack: form impl cachemat curmat valid + exch pop exch pop not + { % Cache is invalid. Execute the Form and save the bits. + gsave begin + currentglobal exch true setglobal + ImageMatrix currentmatrix pop + dup /BBox get aload pop + exch 3 index sub exch 2 index sub rectclip + % Make the cache device. + clippath gsave matrix setmatrix pathbbox grestore + % We now have the bounding box in device space. + 2 { 4 -1 roll floor cvi } repeat + 2 { 4 -1 roll ceiling cvi } repeat + 2 index sub /Height exch def + 2 index sub /Width exch def + ImageMatrix aload pop + exch 7 index sub exch 6 index sub + 6 array astore + 3 1 roll pop pop + dup ImageMatrix copy pop + Width Height <00 ff> makeimagedevice + /Device 1 index def + nulldevice setdevice initgraphics + exch setglobal + dup dup /PaintProc get exec + nulldevice grestore currentdict end + } + if + % Now paint the bits. + % Stack: form implementation + /DeviceGray setcolorspace dup begin 0 exch image end pop + pop grestore + } odef + +setglobal diff --git a/pstoraster/gs_fonts.ps b/pstoraster/gs_fonts.ps new file mode 100644 index 0000000000..ddcd93cdb1 --- /dev/null +++ b/pstoraster/gs_fonts.ps @@ -0,0 +1,797 @@ +% Copyright (C) 1990, 1995, 1996 Aladdin Enterprises. All rights reserved. +% +% This file is part of GNU Ghostscript. +% +% GNU Ghostscript is distributed in the hope that it will be useful, but +% WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to +% anyone for the consequences of using it or for whether it serves any +% particular purpose or works at all, unless he says so in writing. Refer to +% the GNU General Public License for full details. +% +% Everyone is granted permission to copy, modify and redistribute GNU +% Ghostscript, but only under the conditions described in the GNU General +% Public License. A copy of this license is supposed to have been given to +% you along with GNU Ghostscript so you can know your rights and +% responsibilities. It should be in a file named COPYING. Among other +% things, the copyright notice and this notice must be preserved on all +% copies. +% +% Aladdin Enterprises is not affiliated with the Free Software Foundation or +% the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, +% does not depend on any other GNU software. + +% Font initialization and management code. + +% Define the default font. +/defaultfontname /Courier def + +% Define the name of the font map file. +/defaultfontmap (Fontmap) def + +% ------ End of editable parameters ------ % + +% If DISKFONTS is true, we load individual CharStrings as they are needed. +% (This is intended primarily for machines with very small memories.) +% In this case, we define another dictionary, parallel to FontDirectory, +% that retains an open file for every font loaded. +/FontFileDirectory 10 dict def + +% Split up a search path into individual directories or files. +/.pathlist % .pathlist ... + { { dup length 0 eq { pop exit } if + .filenamelistseparator search not { exit } if + exch pop exch + } + loop + } bind def + +% Load a font name -> font file name map. +userdict /Fontmap FontDirectory maxlength dict put +/.loadFontmap % .loadFontmap - + { % We would like to simply execute .definefontmap as we read, + % but we have to maintain backward compatibility with an older + % specification that makes later entries override earlier. + 50 dict exch + { dup token not { closefile exit } if + % stack: fontname + % This is a hack to get around the absurd habit of MS-DOS editors + % of adding an EOF character at the end of the file. + dup (\032) eq { pop closefile exit } if + 1 index token not + { (Fontmap entry for ) print dup =only + ( has no associated file or alias name! Giving up.\n) print flush + {.loadFontmap} 0 get 1 .quit + } if + dup type dup /stringtype eq exch /nametype eq or not + { (Fontmap entry for ) print 1 index =only + ( has an invalid file or alias name! Giving up.\n) print flush + {.loadFontmap} 0 get 1 .quit + } if + % stack: dict file fontname filename|aliasname + % Read and pop tokens until a semicolon. + { 2 index token not + { (Fontmap entry for ) print 1 index =only + ( ends prematurely! Giving up.\n) print flush + {.loadFontmap} 0 get 1 .quit + } if + dup /; eq { pop 3 index 3 1 roll .growput exit } if + pop + } loop + } loop + { .definefontmap } forall + } bind def +% Add an entry in Fontmap. We redefine this if the Level 2 +% resource machinery is loaded. +/.definefontmap % .definefontmap - + { % Since Fontmap is global, make sure the values are storable. + .currentglobal 3 1 roll true .setglobal + dup type /stringtype eq + { dup .gcheck not { dup length string copy } if + } + if + Fontmap 3 -1 roll 2 copy .knownget + { % Add an element to the end of the existing value, + % unless it's the same as the current last element. + mark exch aload pop counttomark 4 add -1 roll + 2 copy eq { cleartomark pop pop } { ] readonly .growput } ifelse + } + { % Make a new entry. + mark 4 -1 roll ] readonly .growput + } + ifelse .setglobal + } bind def + +% Parse a font file just enough to find the FontName or FontType. +/.findfontvalue % .findfontvalue true + % .findfontvalue false + % Closes the file in either case. + { exch dup read not { -1 } if + 2 copy unread 16#80 eq + { dup (xxxxxx) readstring pop pop } % skip .PFB header + if + % Stack: key file + { dup token not { false exit } if % end of file + dup /eexec eq { pop false exit } if % reached eexec section + dup /Subrs eq { pop false exit } if % Subrs without eexec + dup /CharStrings eq { pop false exit } if % CharStrings without eexec + dup 3 index eq + { xcheck not { dup token exit } if } % found key + { pop } + ifelse + } loop + % Stack: key file value true (or) + % Stack: key file false + dup { 4 } { 3 } ifelse -2 roll closefile pop + } bind def +/.findfontname + { /FontName .findfontvalue + } bind def + +% If there is no FONTPATH, try to get one from the environment. +NOFONTPATH { /FONTPATH () def } if +/FONTPATH where + { pop } + { /FONTPATH (GS_FONTPATH) getenv not { () } if def } +ifelse +FONTPATH length 0 eq { (%END FONTPATH) .skipeof } if +/FONTPATH [ FONTPATH .pathlist ] def + +% Scan directories looking for plausible fonts. "Plausible" means that +% the file begins with %!PS-AdobeFont or %!FontType1, or with \200\001 +% followed by four arbitrary bytes and then either of these strings. +% To speed up the search, we skip any file whose name appears in +% the Fontmap (with any extension and upper/lower case variation) already, +% and any file whose extension definitely indicates it is not a font. +% +% NOTE: The current implementation of this procedure is somewhat Unix/DOS- +% specific. It assumes that '/' and '\' are directory separators, and that +% the part of a file name following the last '.' is the extension. +% +/.lowerstring % .lowerstring + { 0 1 2 index length 1 sub + { 2 copy get dup 65 ge exch 90 le and + { 2 copy 2 copy get 32 add put } + if pop + } + for + } bind def +/.splitfilename % .basename + { { (/) search { true } { (\\) search } ifelse + { pop pop } + { exit } + ifelse + } + loop + dup { (.) search { pop pop } { exit } ifelse } loop + 2 copy eq + { pop () } + { exch dup length 2 index length 1 add sub 0 exch getinterval exch } + ifelse +% Following is debugging code. +% (*** Split => ) print 2 copy exch ==only ( ) print ==only +% ( ***\n) print flush + } bind def +/.scanfontdict 1 dict def % establish a binding +/.scanfontbegin + { % Construct the table of all file names already in Fontmap. + currentglobal true setglobal + .scanfontdict dup maxlength Fontmap length 2 add .max .setmaxlength + Fontmap + { exch pop + { dup type /stringtype eq + { .splitfilename pop =string copy .lowerstring cvn + .scanfontdict exch true put + } + { pop + } + ifelse + } + forall + } + forall + setglobal + } bind def +/.scanfontskip mark + % Strings are converted to names anyway, so.... + /afm true + /bat true + /c true + /cmd true + /com true + /dll true + /doc true + /drv true + /exe true + /fon true + /fot true + /h true + /o true + /obj true + /pfm true + /txt true +.dicttomark def +/.scan1fontstring 128 string def +/.scanfontheaders [(%!PS-AdobeFont*) (%!FontType1*)] def +0 .scanfontheaders { length max } forall 6 add % extra for PFB header +/.scan1fontfirst exch string def +/.scanfontdir % .scanfontdir - + { currentglobal exch true setglobal + QUIET not { (Scanning ) print dup print ( for fonts...) print flush } if + (*) 2 copy .filenamedirseparator + dup (\\) eq { pop (\\\\) } if % double \ for pattern match + exch concatstrings concatstrings + 0 0 0 4 -1 roll % found scanned files + { % stack: + exch 1 add exch % increment filecount + dup .splitfilename .lowerstring + % stack: + % + .scanfontskip exch known exch .scanfontdict exch known or + { pop + % stack: + } + { 3 -1 roll 1 add 3 1 roll + % stack: + dup (r) { file } .internalstopped + { pop pop null () + % stack: + % null () + } + { + % On some platforms, the file operator will open directories, + % but an error will occur if we try to read from one. + % Handle this possibility here. + dup .scan1fontfirst { readstring } .internalstopped + { pop pop () } + { pop } + ifelse + % stack: + %
+ } + ifelse + % Check for PFB file header. + dup (\200\001????*) .stringmatch + { dup length 6 sub 6 exch getinterval } + if + % Check for font file headers. + false .scanfontheaders + { 2 index exch .stringmatch or + } + forall exch pop + { % stack: + % + dup 0 setfileposition .findfontname + { dup Fontmap exch known + { pop pop + } + { exch copystring exch + DEBUG { ( ) print dup =only } if + 1 index .definefontmap + .splitfilename pop true .scanfontdict 3 1 roll .growput + % Increment fontcount. + 3 -1 roll 1 add 3 1 roll + } + ifelse + } + { pop + } + ifelse + } + % .findfontname will have done a closefile in the above case. + { dup null eq { pop } { closefile } ifelse pop + } + ifelse + } + ifelse + } + .scan1fontstring filenameforall + QUIET + { pop pop pop } + { ( ) print =only ( files, ) print =only ( scanned, ) print + =only ( new fonts.\n) print flush + } + ifelse + setglobal + } bind def + +%END FONTPATH + +% Define definefont. This is a procedure built on a set of operators +% that do all the error checking and key insertion. +mark + /.buildfont0 where { pop 0 /.buildfont0 cvx } if + /.buildfont1 where { pop 1 /.buildfont1 cvx } if + /.buildfont3 where { pop 3 /.buildfont3 cvx } if + /.buildfont4 where { pop 4 /.buildfont4 cvx } if + /.buildfont42 where { pop 42 /.buildfont42 cvx } if +.dicttomark /buildfontdict exch def +/.growfontdict + { % Grow the font dictionary, if necessary, to ensure room for an + % added entry, making sure there is at least one slot left for FID. + dup maxlength 1 index length sub 2 lt + { dup dup wcheck + { .growdict } + { .growdictlength dict .copydict } + ifelse + } + { dup wcheck not { dup maxlength dict .copydict } if + } + ifelse + } bind def +/definefont + { 1 dict begin count /d exch def % save stack depth in case of error + { % Check for disabled platform fonts. + NOPLATFONTS + { % Make sure we leave room for FID. + .growfontdict dup /ExactSize 0 put + } + { % Hack: if the Encoding looks like it might be the + % Symbol or Dingbats encoding, load those now (for the + % benefit of platform font matching) just in case + % the font didn't actually reference them. + dup /Encoding get length 65 ge + { dup /Encoding get 64 get + dup /congruent eq { SymbolEncoding pop } if + /a9 eq { DingbatsEncoding pop } if + } + if + } + ifelse + dup /FontType get //buildfontdict exch get exec + DISKFONTS + { FontFileDirectory 2 index known + { dup /FontFile FontFileDirectory 4 index get .growput + } + if + } + if + readonly + } + stopped + { count d sub { pop } repeat end /invalidfont signalerror + } + { end % stack: name fontdict + % If the current allocation mode is global, also enter + % the font in LocalFontDirectory. + .currentglobal + { //systemdict /LocalFontDirectory .knownget + { 2 index 2 index .growput } + if + } + if + dup FontDirectory 4 -2 roll .growput + } + ifelse + } odef + +% Define a procedure for defining aliased fonts. +% We can't just copy the font (or even use the same font unchanged), +% because a significant number of PostScript files assume that +% the FontName of a font is the same as the font resource name or +% the key in [Shared]FontDirectory; on the other hand, some Adobe files +% rely on the FontName of a substituted font *not* being the same as +% the requested resource name. We address this issue heuristically: +% we substitute the new name iff the font name doesn't have MM in it. +/.aliasfont % .aliasfont + { .currentglobal 3 1 roll dup .gcheck .setglobal + dup length 2 add dict + dup 3 -1 roll { 1 index /FID eq { pop pop } { put dup } ifelse } forall + % Stack: global fontname newfont newfont. + % We might be defining a global font whose FontName + % is a local string. This is weird, but legal, + % and doesn't cause problems anywhere else. + % To avoid any possible problems, do a cvn. + 2 index =string cvs (MM) search + { pop pop pop pop + } + { /FontName exch dup type /stringtype eq { cvn } if put + } + ifelse + //systemdict /definefont get exec % Don't bind, since Level 2 + % redefines definefont + exch .setglobal + } odef % so findfont will bind it + +% Define .loadfontfile for loading a font. If we recognize Type 1 and/or +% TrueType fonts, gs_type1.ps and/or gs_ttf.ps will redefine this. +/.loadfontfile { cvx exec } bind def +/.loadfont + { % Some buggy fonts leave extra junk on the stack, + % so we have to make a closure that records the stack depth + % in a fail-safe way. + /.loadfontfile cvx count 1 sub 2 packedarray cvx exec + count exch sub { pop } repeat + } bind def + +% Find an alternate font to substitute for an unknown one. +% We go to some trouble to parse the font name and extract +% properties from it. Later entries take priority over earlier. +/.substitutefaces [ + % Guess at suitable substitutions for random unknown fonts. + [(Grot) /Times] + [(Roman) /Times] + [(Book) /NewCenturySchlbk] + % If the family name appears in the font name, + % use a font from that family. + [(Arial) /Helvetica] + [(Avant) /AvantGarde] + [(Bookman) /Bookman] + [(Century) /NewCenturySchlbk] + [(Cour) /Courier] + [(Geneva) /Helvetica] + [(Helv) /Helvetica] + [(NewYork) /Times] + [(Pala) /Palatino] + [(Sans) /Helvetica] + [(Schlbk) /NewCenturySchlbk] + [(Serif) /Times] + [(Swiss) /Helvetica] + [(Times) /Times] + % Substitute for Adobe Multiple Master fonts. + [(Myriad) /Times] + [(Minion) /Helvetica] + % Condensed or narrow fonts map to the only narrow family we have. + [(Cond) /Helvetica-Narrow] + [(Narrow) /Helvetica-Narrow] + % If the font wants to be monospace, use Courier. + [(Monospace) /Courier] + [(Typewriter) /Courier] +] readonly def +/.substituteproperties [ + [(It) 1] [(Oblique) 1] + [(Bd) 2] [(Bold) 2] [(bold) 2] [(Demi) 2] [(Heavy) 2] [(Sb) 2] +] readonly def +/.substitutefamilies mark + /AvantGarde + {/AvantGarde-Book /AvantGarde-BookOblique + /AvantGarde-Demi /AvantGarde-DemiOblique} + /Bookman + {/Bookman-Demi /Bookman-DemiItalic /Bookman-Light /Bookman-LightItalic} + /Courier + {/Courier /Courier-Oblique /Courier-Bold /Courier-BoldOblique} + /Helvetica + {/Helvetica /Helvetica-Oblique /Helvetica-Bold /Helvetica-BoldOblique} + /Helvetica-Narrow + {/Helvetica-Narrow /Helvetica-Narrow-Oblique + /Helvetica-Narrow-Bold /Helvetica-Narrow-BoldOblique} + /NewCenturySchlbk + {/NewCenturySchlbk-Roman /NewCenturySchlbk-Italic + /NewCenturySchlbk-Bold /NewCenturySchlbk-BoldItalic} + /Palatino + {/Palatino-Roman /Palatino-Italic /Palatino-Bold /Palatino-BoldItalic} + /Times + {/Times-Roman /Times-Italic /Times-Bold /Times-BoldItalic} +.dicttomark readonly def +/.substitutefont % .substitutefont + { % Look for properties and/or a face name in the font name. + % If we find any, use Helvetica as the base font; + % otherwise, use the default font. + % Note that the "substituted" font name may be the same as + % the requested one; the caller must check this. + dup length string cvs + {defaultfontname /Helvetica-Oblique /Helvetica-Bold /Helvetica-BoldOblique} + exch 0 exch % stack: fontname facelist properties fontname + % Look for a face name. + .substitutefaces + { 2 copy 0 get search + { pop pop pop 1 get .substitutefamilies exch get + 4 -1 roll pop 3 1 roll + } + { pop pop + } + ifelse + } + forall + .substituteproperties + { 2 copy 0 get search + { pop pop pop 1 get 3 -1 roll or exch } + { pop pop } + ifelse + } + forall pop get + % If SUBSTFONT is defined, use it. + /SUBSTFONT where + { pop pop /SUBSTFONT load cvn } + { exec } + ifelse + % Only accept fonts known in the Fontmap. + Fontmap 1 index known not { pop defaultfontname } if + } bind def + +% If requested, make (and recognize) fake entries in FontDirectory for fonts +% present in Fontmap but not actually loaded. Thanks to Ray Johnston for +% the idea behind this code. +FAKEFONTS not { (%END FAKEFONTS) .skipeof } if + +% We use the presence or absence of the FontMatrix key to indicate whether +% a font is real or fake. + +/definefont % definefont + { dup /FontMatrix known not { /FontName get findfont } if + //definefont + } bind odef + +/scalefont % scalefont + { exch dup /FontMatrix known not { /FontName get findfont } if + exch //scalefont + } bind odef + +/makefont % makefont + { exch dup /FontMatrix known not { /FontName get findfont } if + exch //makefont + } bind def + +/setfont % setfont - + { dup /FontMatrix known not { /FontName get findfont } if + //setfont + } bind odef + +%END FAKEFONTS + +% Define findfont so it tries to load a font if it's not found. +% The Red Book requires that findfont be a procedure, not an operator. +/findfont + { mark exch + { .dofindfont + } stopped + { counttomark 1 sub { pop } repeat exch pop stop + } + { % Define any needed aliases. + counttomark 1 sub { .aliasfont } repeat + exch pop + } + ifelse + } bind def +% Check whether the font name we are about to look for is already on the list +% of aliases we're accumulating; if so, cause an error. +/.checkalias % -mark- ... .checkalias <> + { counttomark 1 sub -1 1 + { index 1 index eq + { pop QUIET not + { (Unable to substitute for font.\n) print flush + } if + /findfont cvx /invalidfont signalerror + } + if + } + for + } bind def +% Get a (non-fake) font if present in a FontDirectory. +/.fontknownget % .fontknownget true + % .fontknownget false + { .knownget + { FAKEFONTS + { dup /FontMatrix known { true } { pop false } ifelse } + { true } + ifelse + } + { false + } + ifelse + } bind def +% Do the work of findfont, including substitution, defaulting, and +% scanning of FONTPATH. +/.dofindfont % .dofindfont + { { .tryfindfont { exit } if + % We didn't find the font. If we haven't scanned + % all the directories in FONTPATH, scan the next one now, + % and look for the font again. + null 0 1 FONTPATH length 1 sub + { FONTPATH 1 index get null ne { exch pop exit } if pop + } + for dup null ne + { dup 0 eq { .scanfontbegin } if + FONTPATH 1 index get .scanfontdir + FONTPATH exch null put + % Start over with an empty alias list. + counttomark 1 sub { pop } repeat + .dofindfont exit + } + if pop + % No luck, substitute for the font. + dup defaultfontname eq + { QUIET not + { (Unable to load default font ) print + dup =only (! Giving up.\n) print flush + } + if /findfont cvx /invalidfont signalerror + } + if dup .substitutefont + 2 copy eq { pop defaultfontname } if + .checkalias + QUIET not + { (Substituting font ) print dup =only ( for ) print + 1 index =only (.\n) print flush + } + if + } + loop + } bind def +% Try to find a font using only the present contents of Fontmap. +/.tryfindfont % .tryfindfont true + % .tryfindfont false + { FontDirectory 1 index .fontknownget + { % Already loaded + exch pop true + } + { dup Fontmap exch .knownget not + { % Unknown font name + false + } + + { % Try each element of the Fontmap in turn. + false exch % (in case we exhaust the list) + { exch pop + dup type /nametype eq + { % Font alias + .checkalias .tryfindfont exit + } + { dup dup type dup /arraytype eq exch /packedarraytype eq or exch xcheck and + { % Font with a procedural definition + exec % The procedure will load the font. + % Check to make sure this really happened. + FontDirectory 1 index .knownget + { exch pop true exit } + if + } + { % Font file name + .loadfontloop { true exit } if + } + ifelse + } + ifelse false + } + forall + } + ifelse + } + ifelse + } bind def +% Attempt to load a font from a file. +/.loadfontloop % .loadfontloop true + % .loadfontloop false + { % See above regarding the use of 'loop'. + + { + % Can we open the file? + findlibfile not + { QUIET not + { (Can't find \(or can't open\) font file ) print dup print + (.\n) print flush + } + if pop false exit + } + if + + % Stack: fontname fontfilename fontfile + DISKFONTS + { .currentglobal true .setglobal + 2 index (r) file + FontFileDirectory exch 5 index exch .growput + .setglobal + } + if + QUIET not + { (Loading ) print 2 index =only + ( font from ) print 1 index print (... ) print flush + } + if + % If LOCALFONTS isn't set, load the font into local or global + % VM according to FontType; if LOCALFONTS is set, load the font + % into the current VM, which is what Adobe printers (but not + % DPS or CPSI) do. + LOCALFONTS { false } { /setglobal where } ifelse + { pop /FontType .findfontvalue { 1 eq } { false } ifelse + % .setglobal, like setglobal, aliases FontDirectory to + % GlobalFontDirectory if appropriate. However, we mustn't + % allow the current version of .setglobal to be bound in, + % because it's different depending on language level. + .currentglobal exch /.setglobal load exec + % Remove the fake definition, if any. + FontDirectory 3 index .undef + 1 index (r) file .loadfont FontDirectory exch + /.setglobal load exec + } + { .loadfont FontDirectory + } + ifelse + % Stack: fontname fontfilename fontdirectory + QUIET not + { //systemdict /level2dict known + { .currentglobal false .setglobal vmstatus + true .setglobal vmstatus 3 -1 roll pop + 6 -1 roll .setglobal 5 + } + { vmstatus 3 + } + ifelse { =only ( ) print } repeat + (done.\n) print flush + } if + + % Check to make sure the font was actually loaded. + dup 3 index .fontknownget + { 4 1 roll pop pop pop true exit } if + + % Maybe the file had a different FontName. + % See if we can get a FontName from the file, and if so, + % whether a font by that name exists now. + exch (r) file .findfontname + { 2 copy .fontknownget + { % Yes. Stack: origfontname fontdirectory filefontname fontdict + 3 -1 roll pop exch + QUIET + { pop + } + { (Using ) print =only + ( font for ) print 1 index =only + (.\n) print flush + } + ifelse true exit + } + if pop + } + if pop + + % The font definitely did not load correctly. + QUIET not + { (Loading ) print dup =only + ( font failed.\n) print flush + } if + false exit + + } loop % end of loop + + } bind def + +% Define a procedure to load all known fonts. +% This isn't likely to be very useful. +/loadallfonts + { Fontmap { pop findfont pop } forall + } bind def + +% If requested, load all the fonts defined in the Fontmap into FontDirectory +% as "fake" fonts i.e., font dicts with only FontName defined. +% We must ensure that this happens in both global and local directories. +/.definefakefonts + { + } + { (gs_fonts FAKEFONTS) VMDEBUG + 2 + { .currentglobal not .setglobal + Fontmap + { pop dup type /stringtype eq { cvn } if + FontDirectory 1 index known not + { 1 dict dup /FontName 3 index put + FontDirectory 3 1 roll put + } + if + } + forall + } + repeat + } +FAKEFONTS { exch } if pop def % don't bind, .current/setglobal get redefined + +% Install initial fonts from Fontmap. +/.loadinitialfonts + { NOFONTMAP not + { /FONTMAP where + { pop [ FONTMAP .pathlist ] + { dup VMDEBUG findlibfile + { exch pop .loadFontmap } + { /undefinedfilename signalerror } + ifelse + } + } + { LIBPATH + { defaultfontmap 2 copy .filenamedirseparator + exch concatstrings concatstrings dup VMDEBUG + (r) { file } .internalstopped + { pop pop } { .loadFontmap } ifelse + } + } + ifelse forall + } + if + .definefakefonts + } def % don't bind, .current/setglobal get redefined diff --git a/pstoraster/gs_init.ps b/pstoraster/gs_init.ps new file mode 100644 index 0000000000..acf0e5e383 --- /dev/null +++ b/pstoraster/gs_init.ps @@ -0,0 +1,1269 @@ +% Copyright (C) 1989, 1996 Aladdin Enterprises. All rights reserved. +% +% This file is part of GNU Ghostscript. +% +% GNU Ghostscript is distributed in the hope that it will be useful, but +% WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to +% anyone for the consequences of using it or for whether it serves any +% particular purpose or works at all, unless he says so in writing. Refer to +% the GNU General Public License for full details. +% +% Everyone is granted permission to copy, modify and redistribute GNU +% Ghostscript, but only under the conditions described in the GNU General +% Public License. A copy of this license is supposed to have been given to +% you along with GNU Ghostscript so you can know your rights and +% responsibilities. It should be in a file named COPYING. Among other +% things, the copyright notice and this notice must be preserved on all +% copies. +% +% Aladdin Enterprises is not affiliated with the Free Software Foundation or +% the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, +% does not depend on any other GNU software. + +% Initialization file for the interpreter. +% When this is run, systemdict is still writable. + +% Comment lines of the form +% %% Replace +% indicate places where the next lines should be replaced by +% the contents of , when creating a single merged init file. + +% The interpreter can call out to PostScript code. All procedures +% called in this way, and no other procedures defined in these +% initialization files, have names that begin with %, e.g., +% (%Type1BuildChar) cvn. + +% Check the interpreter revision. NOTE: the interpreter code requires +% that the first non-comment token in this file be an integer. +40000 +dup revision ne + { (pstoraster: Interpreter revision \() print revision 10 string cvs print + (\) does not match gs_init.ps revision \() print 10 string cvs print + (\).\n) print flush null 1 .quit + } +if pop + +% Acquire userdict, and set its length if necessary. +/userdict where + { pop userdict maxlength 0 eq } + { true } +ifelse + { % userdict wasn't already set up by iinit.c. + /userdict + currentdict dup 200 .setmaxlength % userdict + systemdict begin def % can't use 'put', userdict is local + } + { systemdict begin + } +ifelse + +% Define dummy local/global operators if needed. +systemdict /.setglobal known + { true .setglobal + } + { /.setglobal { pop } bind def + /.currentglobal { false } bind def + /.gcheck { pop false } bind def + } +ifelse + +% Define .languagelevel if needed. +systemdict /.languagelevel known not { /.languagelevel 1 def } if + +% Optionally choose a default paper size other than U.S. letter. +% (a4) /PAPERSIZE where { pop pop } { /PAPERSIZE exch def } ifelse + +% Turn on array packing for the rest of initialization. +true setpacking + +% Define the old MS-DOS EOF character as a no-op. +% This is a hack to get around the absurd habit of MS-DOS editors +% of adding an EOF character at the end of the file. +<1a> cvn { } def + +% Acquire the debugging flags. +currentdict /DEBUG known /DEBUG exch def + /VMDEBUG + DEBUG {{print mark + systemdict /level2dict known + { .currentglobal dup false .setglobal vmstatus + true .setglobal vmstatus 3 -1 roll pop + 6 -2 roll pop .setglobal + } + { vmstatus 3 -1 roll pop + } + ifelse usertime 16#fffff and counttomark + { ( ) print ( ) cvs print } + repeat pop + ( ) print systemdict length ( ) cvs print + ( ) print countdictstack ( ) cvs print + ( <) print count ( ) cvs print (>\n) print flush + }} + {{pop + }} + ifelse + def + +currentdict /DELAYBIND known /DELAYBIND exch def +currentdict /DISKFONTS known /DISKFONTS exch def +currentdict /ESTACKPRINT known /ESTACKPRINT exch def +currentdict /FAKEFONTS known /FAKEFONTS exch def +currentdict /FIXEDMEDIA known /FIXEDMEDIA exch def +currentdict /FIXEDRESOLUTION known /FIXEDRESOLUTION exch def +currentdict /LOCALFONTS known /LOCALFONTS exch def +currentdict /NOBIND known /NOBIND exch def +/.bind /bind load def +NOBIND { /bind { } def } if +currentdict /NOCACHE known /NOCACHE exch def +currentdict /NOCIE known /NOCIE exch def +currentdict /NODISPLAY known not /DISPLAYING exch def +currentdict /NOFONTMAP known /NOFONTMAP exch def +currentdict /NOFONTPATH known /NOFONTPATH exch def +currentdict /NOGC known /NOGC exch def +currentdict /NOPAUSE known /NOPAUSE exch def +currentdict /NOPLATFONTS known /NOPLATFONTS exch def +currentdict /NOPROMPT known /NOPROMPT exch def +% The default value of ORIENT1 is true, not false. +currentdict /ORIENT1 known not { /ORIENT1 true def } if +currentdict /OSTACKPRINT known /OSTACKPRINT exch def +currentdict /OUTPUTFILE known % obsolete + { /OutputFile /OUTPUTFILE load def + currentdict /OUTPUTFILE .undef + } if +currentdict /QUIET known /QUIET exch def +currentdict /SAFER known /SAFER exch def +currentdict /SHORTERRORS known /SHORTERRORS exch def +currentdict /WRITESYSTEMDICT known /WRITESYSTEMDICT exch def + +% Acquire environment variables. +currentdict /DEVICE known not + { (GS_DEVICE) getenv { /DEVICE exch def } if } if + +(START) VMDEBUG + +% Open the standard files, so they will be open at the outermost save level. +(%stdin) (r) file pop +(%stdout) (w) file pop +(%stderr) (w) file pop + +% Define a procedure for skipping over an unneeded section of code. +% This avoids allocating space for the skipped procedures. +% We can't use readline, because that imposes a line length limit. +/.skipeof % .skipeof - + { currentfile exch 1 exch .subfiledecode flushfile + } bind def + +% If we're delaying binding, remember everything that needs to be bound later. +DELAYBIND NOBIND not and + { .currentglobal false .setglobal + userdict /.delaybind 1500 array put + .setglobal + userdict /.delaycount 0 put + % When we've done the delayed bind, we want to stop saving. + % Detect this by the disappearance of .delaybind. + /bind + { userdict /.delaybind .knownget + { .delaycount 2 index put + userdict /.delaycount .delaycount 1 add put + } + { .bind + } + ifelse + } bind def + } if + +% Define procedures to assist users who don't read the documentation. +userdict begin +/help + { (Enter PostScript commands. '(filename) run' runs a file, 'quit' exits.\n) + print flush + } bind def +/? /help load def +end + +% Define =string, which is used by some PostScript programs even though +% it isn't documented anywhere. +% Put it in userdict so that each context can have its own copy. +userdict /=string 256 string put + +% Print the greeting. + +/printgreeting + { mark + product (Ghostscript) search + { pop pop pop + (This software comes with NO WARRANTY: see the file COPYING for details.\n) + } + { pop + } + ifelse + (\n) copyright + (\)\n) revisiondate 100 mod (-) + revisiondate 100 idiv 100 mod (-) + revisiondate 10000 idiv ( \() + revision 10 mod + revision 10 idiv 10 mod (.) + revision 100 idiv ( ) + product + counttomark + { (%stdout) (w) file exch false .writecvp + } repeat pop + } bind def + +QUIET not { printgreeting flush } if + +% Define a special version of def for making operator procedures. +/odef % odef - + { 1 index exch .makeoperator def + } .bind def + +%**************** BACKWARD COMPATIBILITY +/getdeviceprops + { null .getdeviceparams + } bind odef +/.putdeviceprops + { null true counttomark 1 add 3 roll .putdeviceparams + dup type /booleantype ne + { dup mark eq { /unknown /rangecheck } if + counttomark 4 add 1 roll cleartomark pop pop pop + /.putdeviceprops load exch signalerror + } + if + } bind odef +/.devicenamedict 1 dict dup /OutputDevice dup put def +/.devicename + { //.devicenamedict .getdeviceparams exch pop exch pop + } bind odef +/max { .max } bind def +/min { .min } bind def +/.currentfilladjust { .currentfilladjust2 pop } bind odef +/.setfilladjust { dup .setfilladjust2 } bind odef +/.writecvs { false .writecvp } bind odef + +% Define predefined procedures substituting for operators, +% in alphabetical order. + +userdict /#copies 1 put +% Adobe implementations don't accept /[ or /], so we don't either. +([) cvn + /mark load def +(]) cvn + {counttomark array astore exch pop} odef +/abs {dup 0 lt {neg} if} odef +% .beginpage is an operator in Level 2. +/.beginpage { } odef +/copypage + { 1 .endpage + { .currentnumcopies false .outputpage + (>>copypage, press to continue<<\n) .confirm + } + if .beginpage + } odef +% .currentnumcopies is redefined in Level 2. +/.currentnumcopies { #copies } odef +/setcolorscreen where { pop % not in all Level 1 configurations + /currentcolorscreen + { .currenthalftone + { { 60 exch 0 exch 3 copy 6 copy } % halftone - not possible + { 3 copy 6 copy } % screen + { } % colorscreen + } + exch get exec + } odef +} if +/currentscreen + { .currenthalftone + { { 60 exch 0 exch } % halftone - not possible + { } % screen + { 12 3 roll 9 { pop } repeat } % colorscreen + } + exch get exec + } odef +/.echo /echo load def +userdict /.echo.mode true put +/echo {dup /.echo.mode exch store .echo} odef +/eexec + { 55665 //filterdict /eexecDecode get exec + cvx //systemdict begin stopped + % Only pop systemdict if it is still the top element, + % because this is apparently what Adobe interpreters do. + currentdict //systemdict eq { end } if + { stop } if + } odef +% .endpage is an operator in Level 2. +/.endpage { 2 ne } odef +% erasepage mustn't use gsave/grestore, because we call it before +% the graphics state stack has been fully initialized. +/erasepage + { /currentcolor where + { pop currentcolor currentcolorspace { setcolorspace setcolor } } + { /currentcmykcolor where + { pop currentcmykcolor { setcmykcolor } } + { currentrgbcolor { setrgbcolor } } + ifelse + } + ifelse 1 setgray .fillpage exec + } odef +/executive + { { prompt + { (%statementedit) (r) file } stopped + { pop pop $error /errorname get /undefinedfilename eq + { .clearerror exit } if % EOF + handleerror null % ioerror?? + } + if + cvx execute + } loop + } odef +/filter + { //filterdict 1 index .knownget + { exch pop exec } + { /filter load /undefined signalerror } + ifelse + } odef +/handleerror + { errordict /handleerror get exec } bind def +/identmatrix [1.0 0.0 0.0 1.0 0.0 0.0] readonly def +/identmatrix + { //identmatrix exch copy } odef +/initgraphics + { initmatrix newpath initclip + 1 setlinewidth 0 setlinecap 0 setlinejoin + [] 0 setdash 0 setgray 10 setmiterlimit + } odef +/languagelevel 1 def % gs_lev2.ps may change this +/makeimagedevice { false makewordimagedevice } odef +/matrix { 6 array identmatrix } odef +/pathbbox { false .pathbbox } odef +/prompt { flush flushpage + (GS) print + count 0 ne { (<) print count =only } if + (>) print flush + } bind def +/pstack { 0 1 count 3 sub { index == } for } bind def +/putdeviceprops + { .putdeviceprops { erasepage } if } odef +/quit { /quit load 0 .quit } odef +/run { dup type /filetype ne { (r) file } if + % We must close the file when execution terminates, + % regardless of the state of the stack, + % and then propagate an error, if any. + cvx .runexec + } odef +/setdevice + { .setdevice { erasepage } if } odef +/showpage + { 0 .endpage + { .currentnumcopies true .outputpage + (>>showpage, press to continue<<\n) .confirm + erasepage + } + if initgraphics .beginpage + } odef +% Code output by Adobe Illustrator relies on the fact that +% `stack' is a procedure, not an operator!!! +/stack { 0 1 count 3 sub { index = } for } bind def +/start { executive } def +/stop { true .stop } odef +% Internal uses of stopped that aren't going to do a stop if an error occurs +% should use .internalstopped to avoid setting newerror et al. +/stopped { false .stopped } odef +/.internalstopped { null .stopped null ne } bind def +/store { 1 index where { 3 1 roll put } { def } ifelse } odef +% When running in Level 1 mode, this interpreter is supposed to be +% compatible with PostScript "version" 54.0 (I think). +/version (54.0) def + +% internaldict is defined in systemdict, but is allocated in local VM. +systemdict /internaldict .knownget not { 0 } if type /operatortype ne + { .currentglobal false .setglobal + //systemdict /internaldict known not { /internaldict 5 dict def } if + /internaldict + [ /dup load 1183615869 /eq load + [ /pop load internaldict ] cvx + [ /internaldict /cvx load /invalidaccess /signalerror cvx ] cvx + /ifelse load + ] cvx bind odef + .setglobal + } if + +% Define some additional built-in procedures (beyond the ones defined by +% the PostScript Language Reference Manual). +% Warning: these are not guaranteed to stay the same from one release +% to the next! +/concatstrings + { exch dup length 2 index length add string % str2 str1 new + dup dup 4 2 roll copy % str2 new new new1 + length 4 -1 roll putinterval + } bind def +/copyarray + { dup length array copy } bind def +% Copy a dictionary per the Level 2 spec even in Level 1. +/.copydict % .copydict + { dup 3 -1 roll { put dup } forall pop } bind def +/copystring + { dup length string copy } bind def +/finddevice + { //systemdict /devicedict get exch get + dup 1 get null eq + { % This is the first request for this type of device. + % Create a default instance now. + % Stack: [proto null] + .currentglobal true .setglobal exch + dup dup 0 get copydevice 1 exch put + exch .setglobal + } + if 1 get + } bind def +/.growdictlength % get size for growing a dictionary + { length 3 mul 2 idiv 1 add + } bind def +/.growdict % grow a dictionary + { dup .growdictlength .setmaxlength + } bind def +/.growput % put, grow the dictionary if needed + { 2 index length 3 index maxlength eq + { 3 copy pop known not { 2 index .growdict } if + } if + put + } bind def +/.packtomark + { counttomark packedarray exch pop } bind def +/ppstack + { 0 1 count 3 sub { index === } for } bind def +/runlibfile + { findlibfile + { exch pop run } + { /undefinedfilename signalerror } + ifelse + } bind def +/selectdevice + { finddevice setdevice .setdefaultscreen } bind def +/signalerror % signalerror - + { errordict exch get exec } bind def + +% Define the =[only] procedures. Also define =print, +% which is used by some PostScript programs even though +% it isn't documented anywhere. +/write=only + { { .writecvs } .internalstopped + { pop (--nostringval--) writestring + } + if + } bind def +/write= + { 1 index exch write=only (\n) writestring + } bind def +/=only { (%stdout) (w) file exch write=only } bind def +/= { =only (\n) print } bind def +/=print /=only load def +% Temporarily define == as = for the sake of runlibfile0. +/== /= load def + +% Define procedures for getting and setting the current device resolution. + +/gsgetdeviceprop % gsgetdeviceprop + { 2 copy mark exch null .dicttomark .getdeviceparams + dup mark eq % if true, not found + { pop dup /undefined signalerror } + { 5 1 roll pop pop pop pop } + ifelse + } bind def +/gscurrentresolution % - gscurrentresolution <[xres yres]> + { currentdevice /HWResolution gsgetdeviceprop + } bind def +/gssetresolution % <[xres yres]> gssetresolution - + { 2 array astore mark exch /HWResolution exch + currentdevice copydevice putdeviceprops setdevice + } bind def + +% Define auxiliary procedures needed for the above. +/shellarguments % -> shell_arguments true (or) false + { /ARGUMENTS where + { /ARGUMENTS get dup type /arraytype eq + { aload pop /ARGUMENTS null store true } + { pop false } + ifelse } + { false } ifelse + } bind def +/.confirm + { DISPLAYING NOPAUSE not and + { % Print a message (unless NOPROMPT is true) + % and wait for the user to type something. + % If the user just types a newline, flush it. + NOPROMPT { pop } { print flush } ifelse + .echo.mode false echo + (%stdin) (r) file dup read + { dup (\n) 0 get eq { pop pop } { unread } ifelse } + { pop } + ifelse echo + } + { pop + } + ifelse + } bind def + +% Define the procedure used by .runfile, .runstdin and .runstring +% for executing user input. +% This is called with a procedure or executable file on the operand stack. +/execute + { stopped + $error /newerror get and + { handleerror flush + } if + } odef +% Define an execute analogue of runlibfile0. +/execute0 + { stopped + $error /newerror get and + { handleerror flush /execute0 cvx 1 .quit + } if + } bind def +% Define the procedure that the C code uses for running files +% named on the command line. +/.runfile { { runlibfile } execute } def +% Define the procedure that the C code uses for running piped input. +/.runstdin { (%stdin) (r) file cvx execute0 } bind def +% Define the procedure that the C code uses for running commands +% given on the command line with -c. +/.runstring { cvx execute } def + +% Define a special version of runlibfile that aborts on errors. +/runlibfile0 + { cvlit dup /.currentfilename exch def + { findlibfile not { stop } if } + stopped + { (Can't find \(or open\) initialization file ) print + .currentfilename == flush /runlibfile0 cvx 1 .quit + } if + exch pop cvx stopped + { (While reading ) print .currentfilename print (:\n) print flush + handleerror /runlibfile0 1 .quit + } if + } bind def +% Temporarily substitute it for the real runlibfile. +/.runlibfile /runlibfile load def +/runlibfile /runlibfile0 load def + +% Create the error handling machinery. +% Define the standard error handlers. +% The interpreter has created the ErrorNames array. +/.unstoppederrorhandler % .unstoppederrorhandler - + { % This is the handler that gets used for recursive errors, + % or errors outside the scope of a 'stopped'. + 2 copy SHORTERRORS + { (%%[ Error: ) print =only flush + (; OffendingCommand: ) print =only ( ]%%\n) print + } + { (Unrecoverable error: ) print =only flush + ( in ) print = flush + count 2 gt + { (Operand stack:\n ) print + 2 1 count 3 sub { ( ) print index =only flush } for + (\n) print flush + } if + } + ifelse + -1 0 1 //ErrorNames length 1 sub + { dup //ErrorNames exch get 3 index eq + { not exch pop exit } { pop } ifelse + } + for exch pop .quit + } bind def +/.errorhandler % .errorhandler - + { % Detect an internal 'stopped'. + .instopped { null eq { pop pop stop } if } if + $error /.inerror get .instopped { pop } { pop true } ifelse + { .unstoppederrorhandler + } if % detect error recursion + $error /globalmode .currentglobal false .setglobal put + $error /.inerror true put + $error /newerror true put + $error exch /errorname exch put + $error exch /command exch put + $error /recordstacks get $error /errorname get /VMerror ne and + { % Attempt to store the stack contents atomically. + count array astore dup $error /ostack 4 -1 roll + countexecstack array execstack $error /estack 3 -1 roll + countdictstack array dictstack $error /dstack 3 -1 roll + put put put aload pop + } + { $error /dstack .undef + $error /estack .undef + $error /ostack .undef + } + ifelse + $error /position currentfile status + { currentfile { fileposition } .internalstopped { pop null } if + } + { % If this was a scanner error, the file is no longer current, + % but the command holds the file, which may still be open. + $error /command get dup type /filetype eq + { { fileposition } .internalstopped { pop null } if } + { pop null } + ifelse + } + ifelse put + % During initialization, we don't reset the allocation + % mode on errors. + $error /globalmode get $error /.nosetlocal get and .setglobal + $error /.inerror false put + stop + } bind def +% Define the standard handleerror. We break out the printing procedure +% (.printerror) so that it can be extended for binary output +% if the Level 2 facilities are present. + /.printerror + { $error begin + /command load errorname SHORTERRORS + { (%%[ Error: ) print =only flush + (; OffendingCommand: ) print =only + currentdict /errorinfo .knownget + { (;\nErrorInfo:) print + dup type /arraytype eq + { { ( ) print =only } forall } + { ( ) print =only } + ifelse + } if + ( ]%%\n) print flush + } + { (Error: ) print ==only flush + ( in ) print ==only flush + currentdict /errorinfo .knownget + { (\nAdditional information: ) print ==only flush + } if + .printerror_long + } + ifelse + .clearerror + end + flush + } bind def + /.printerror_long % long error printout, + % $error is on the dict stack + { % Push the (anonymous) stack printing procedure. + % <==flag> proc + { + currentdict exch .knownget % stackname defined in $error? + { + 4 1 roll % stack: <==flag> + errordict exch .knownget % overridename defined? + { + exch pop exch pop exec % call override with + } + { + exch print exch % print heading. stack <==flag> + 1 index not { (\n) print } if + { 1 index { (\n ) } { ( ) } ifelse print + dup type /dicttype eq + { + (--dict:) print + dup rcheck + { dup length =only (/) print maxlength =only } + { pop } + ifelse + (--) print + } + { + dup type /stringtype eq 2 index or + { ===only } { =only } ifelse + } ifelse + } forall + pop + } + ifelse % overridden + } + { pop pop pop + } + ifelse % stack known + } + + (\nOperand stack:) OSTACKPRINT /.printostack /ostack 4 index exec + (\nExecution stack:) ESTACKPRINT /.printestack /estack 4 index exec + (\nBacktrace:) true /.printbacktrace /backtrace 4 index exec + (\nDictionary stack:) false /.printdstack /dstack 4 index exec + (\n) print + pop % printing procedure + + errorname /VMerror eq + { (VM status:) print mark vmstatus + counttomark { ( ) print counttomark -1 roll dup =only } repeat + cleartomark (\n) print + } if + + .languagelevel 2 ge + { (Current allocation mode is ) print + globalmode { (global\n) } { (local\n) } ifelse print + } if + + .oserrno dup 0 ne + { (Last OS error: ) print + errorname /VMerror ne + { dup .oserrorstring { = pop } { = } ifelse } + { = } + ifelse + } + { pop + } + ifelse + + position null ne + { (Current file position is ) print position = } + if + + } bind def +% Define a procedure for clearing the error indication. +/.clearerror + { $error /newerror false put + $error /errorinfo .undef + 0 .setoserrno + } bind def + +% Define $error. This must be in local VM. +.currentglobal false .setglobal +/$error 40 dict def % newerror, errorname, command, errorinfo, + % ostack, estack, dstack, recordstacks, + % binary, globalmode, + % .inerror, .nosetlocal, position, + % plus extra space for badly designed error handers. +$error begin + /newerror false def + /recordstacks true def + /binary false def + /globalmode .currentglobal def + /.inerror false def + /.nosetlocal true def + /position null def +end +% Define errordict similarly. It has one entry per error name, +% plus handleerror. +/errordict ErrorNames length 1 add dict def +.setglobal % contents of errordict are global +errordict begin + ErrorNames + { mark 1 index systemdict /.errorhandler get /exec load .packtomark cvx def + } forall +% The handlers for interrupt and timeout are special; there is no +% 'current object', so they push their own name. + { /interrupt /timeout } + { mark 1 index dup systemdict /.errorhandler get /exec load .packtomark cvx def + } forall +/handleerror + { //systemdict /.printerror get exec + } bind def +end + +% Define the [write]==[only] procedures. +/.dict 26 dict dup +begin def + /.cvp {1 index exch .writecvs} bind def + /.nop {exch pop .p} bind def + /.p {1 index exch writestring} bind def + /.p1 {2 index exch writestring} bind def + /.p2 {3 index exch writestring} bind def + /.print + { dup type .dict exch .knownget + { dup type /stringtype eq { .nop } { exec } ifelse } + { (-) .p1 type .cvp (-) .p } + ifelse + } bind def + /.pstring + { { dup dup 32 lt exch 127 ge or + { (\\) .p1 2 copy -6 bitshift 48 add write + 2 copy -3 bitshift 7 and 48 add write + 7 and 48 add + } + { dup dup -2 and 40 eq exch 92 eq or {(\\) .p1} if + } + ifelse 1 index exch write + } + forall + } bind def + /booleantype /.cvp load def + /conditiontype (-condition-) def + /devicetype (-device-) def + /dicttype (-dict-) def + /filetype (-file-) def + /fonttype (-fontID-) def + /gstatetype (-gstate-) def + /integertype /.cvp load def + /locktype (-lock-) def + /marktype (-mark-) def + /nulltype (null) def + /realtype {1 index exch true .writecvp} bind def + /savetype (-save-) def + /nametype + {dup xcheck not {(/) .p1} if + 1 index exch .writecvs} bind def + /arraytype + {dup rcheck + {() exch dup xcheck + {({) .p2 + {exch .p1 + 1 index exch .print pop ( )} forall + (})} + {([) .p2 + {exch .p1 + 1 index exch .print pop ( )} forall + (])} + ifelse exch pop .p} + {(-array-) .nop} + ifelse} bind def + /operatortype + {(--) .p1 .cvp (--) .p} bind def + /packedarraytype + { dup rcheck + { arraytype } + { (-packedarray-) .nop } + ifelse + } bind def + /stringtype + { dup rcheck + { (\() .p1 dup length 200 le + { .pstring } + { 0 200 getinterval .pstring (...) .p } + ifelse (\)) .p + } + { (-string-) .nop + } + ifelse + } bind def +{//.dict begin .print pop end} + bind +end + +/write==only exch def +/write== {1 index exch write==only (\n) writestring} bind def +/==only { (%stdout) (w) file exch write==only } bind def +/== {==only (\n) print} bind def + +% Define [write]===[only], an extension that prints dictionaries +% in readable form and doesn't truncate strings. +/.dict /write==only load 0 get dup length dict .copydict dup +begin def + /dicttype + { dup rcheck + { (<< ) .p1 + { 2 index 3 -1 roll .print pop ( ) .p1 + 1 index exch .print pop ( ) .p + } + forall (>>) .p + } + { (-dict-) .nop + } + ifelse + } bind def + /stringtype + { dup rcheck + { (\() .p1 .pstring (\)) .p } + { (-string-) .nop } + ifelse + } bind def + +{//.dict begin .print pop end} + bind +end + +/write===only exch def +/write=== {1 index exch write===only (\n) writestring} bind def +/===only { (%stdout) (w) file exch write===only } bind def +/=== { ===only (\n) print } bind def + +(END PROCS) VMDEBUG + +% Define the font directory. +/FontDirectory false .setglobal 100 dict true .setglobal def + +% Define the encoding dictionary. +/EncodingDirectory 10 dict def % enough for Level 2 + PDF standard encodings + +% Define .findencoding. (This is redefined in Level 2.) +/.findencoding + { //EncodingDirectory exch get exec + } bind def +/.defineencoding + { //EncodingDirectory 3 1 roll put + } bind def +% If we've got the composite font extensions, define findencoding. +/rootfont where { pop /findencoding { .findencoding } odef } if + +% Load StandardEncoding. +%% Replace 1 (gs_std_e.ps) +(gs_std_e.ps) dup runlibfile VMDEBUG + +% Load ISOLatin1Encoding. +%% Replace 1 (gs_iso_e.ps) +(gs_iso_e.ps) dup runlibfile VMDEBUG + +% Define stubs for the Symbol and Dingbats encodings. +% Note that the first element of the procedure must be the file name, +% since gs_lev2.ps extracts it to set up the Encoding resource category. + + /SymbolEncoding { /SymbolEncoding .findencoding } bind def +%% Replace 3 (gs_sym_e.ps) + EncodingDirectory /SymbolEncoding + { (gs_sym_e.ps) //systemdict begin runlibfile SymbolEncoding end } + bind put + + /DingbatsEncoding { /DingbatsEncoding .findencoding } bind def +%% Replace 3 (gs_dbt_e.ps) + EncodingDirectory /DingbatsEncoding + { (gs_dbt_e.ps) //systemdict begin runlibfile DingbatsEncoding end } + bind put + +(END FONTDIR/ENCS) VMDEBUG + +% Construct a dictionary of all available devices. +% These are (read-only) device prototypes that can't be +% installed or have their parameters changed. For this reason, +% the value in the dictionary is actually a 2-element writable array, +% to allow us to create a default instance of the prototype on demand. + + % Loop until the .getdevice gets a rangecheck. +errordict /rangecheck 2 copy get +errordict /rangecheck { pop stop } put % pop the command + 0 { {dup .getdevice exch 1 add} loop} null .stopped pop + 1 add dict /devicedict 1 index def + begin % 2nd copy of count is on stack + { dup .devicename exch + dup wcheck { dup } { null } ifelse 2 array astore def + } repeat + end +put % errordict /rangecheck +.clearerror +/devicenames devicedict { pop } forall devicedict length packedarray def + +% Determine the default device. +/defaultdevice DISPLAYING + { systemdict /DEVICE .knownget + { devicedict 1 index known not + { (Unknown device: ) print = + flush /defaultdevice cvx 1 .quit + } + if + } + { 0 .getdevice .devicename + } + ifelse + } + { /nullpage + } +ifelse +/.defaultdevicename 1 index def +finddevice % make a copy +def +devicedict /Default devicedict .defaultdevicename get put + +(END DEVS) VMDEBUG + +% Define statusdict, for the benefit of programs +% that think they are running on a LaserWriter or similar printer. +%% Replace 1 (gs_statd.ps) +(gs_statd.ps) runlibfile + +(END STATD) VMDEBUG + +% Load the standard font environment. +%% Replace 1 (gs_fonts.ps) +(gs_fonts.ps) runlibfile + +(END GS_FONTS) VMDEBUG + +% Load the initialization files for optional features. +%% Replace 4 INITFILES +systemdict /INITFILES known + { INITFILES { dup runlibfile VMDEBUG } forall + } +if + +% If Level 2 functionality is implemented, enable it now. +/.setlanguagelevel where + { pop 2 .setlanguagelevel + } if + +(END INITFILES) VMDEBUG + +% Create a null font. This is the initial font. +8 dict dup begin + /FontMatrix [ 1 0 0 1 0 0 ] readonly def + /FontType 3 def + /FontName () def + /Encoding StandardEncoding def + /FontBBox { 0 0 0 0 } readonly def % executable is bogus, but customary ... + /BuildChar { pop pop 0 0 setcharwidth } bind def + /PaintType 0 def % shouldn't be needed! +end +/NullFont exch definefont setfont + +% Define NullFont as the font. +/NullFont currentfont def + +% Load initial fonts from FONTPATH directories, Fontmap file, +% and/or .getccfont as appropriate. +.loadinitialfonts + +% Remove NullFont from FontDirectory, so it can't be accessed by mistake. +FontDirectory /NullFont .undef + +(END FONTS) VMDEBUG + +% Restore the real definition of runlibfile. +/runlibfile /.runlibfile load def +currentdict /.runlibfile .undef + +% Bind all the operators defined as procedures. +/.bindoperators % binds operators in currentdict + { % Temporarily disable the typecheck error. + errordict /typecheck 2 copy get + errordict /typecheck { pop } put % pop the command + currentdict + { dup type /operatortype eq + { % This might be a real operator, so bind might cause a typecheck, + % but we've made the error a no-op temporarily. + .bind % do a real bind even if NOBIND is set + } + if pop pop + } forall + put + } def +NOBIND DELAYBIND or not { .bindoperators } if + +% Establish a default environment. + +defaultdevice +DISPLAYING not { setdevice (%END DISPLAYING) .skipeof } if +systemdict /DEVICEWIDTH known +systemdict /DEVICEHEIGHT known or +systemdict /DEVICEWIDTHPOINTS known or +systemdict /DEVICEHEIGHTPOINTS known or +systemdict /DEVICEXRESOLUTION known or +systemdict /DEVICEYRESOLUTION known or +systemdict /PAPERSIZE known or +not { (%END DEVICE) .skipeof } if +% Let DEVICE{WIDTH,HEIGHT}[POINTS] override PAPERSIZE. +systemdict /PAPERSIZE known +systemdict /DEVICEWIDTH known not and +systemdict /DEVICEHEIGHT known not and +systemdict /DEVICEWIDTHPOINTS known not and +systemdict /DEVICEHEIGHTPOINTS known not and + { % Convert the paper size to device dimensions. + true statusdict /.pagetypenames get + { PAPERSIZE eq + { PAPERSIZE load + dup 0 get /DEVICEWIDTHPOINTS exch def + 1 get /DEVICEHEIGHTPOINTS exch def + pop false exit + } + if + } + forall + { (Unknown paper size: ) print PAPERSIZE ==only (.\n) print + } + if + } +if +% Adjust the device parameters per the command line. +% It is possible to specify resolution, pixel size, and page size; +% since any two of these determine the third, conflicts are possible. +% We simply pass them to .setdeviceparams and let it sort things out. + mark /HWResolution null /HWSize null /PageSize null .dicttomark + .getdeviceparams .dicttomark begin + mark + % Check for resolution. + /DEVICEXRESOLUTION where dup + { exch pop HWResolution 0 DEVICEXRESOLUTION put } + if + /DEVICEYRESOLUTION where dup + { exch pop HWResolution 1 DEVICEYRESOLUTION put } + if + or { /HWResolution HWResolution } if + % Check for device sizes specified in pixels. + /DEVICEWIDTH where dup + { exch pop HWSize 0 DEVICEWIDTH put } + if + /DEVICEHEIGHT where dup + { exch pop HWSize 1 DEVICEHEIGHT put } + if + or { /HWSize HWSize } if + % Check for device sizes specified in points. + /DEVICEWIDTHPOINTS where dup + { exch pop PageSize 0 DEVICEWIDTHPOINTS put } + if + /DEVICEHEIGHTPOINTS where dup + { exch pop PageSize 1 DEVICEHEIGHTPOINTS put } + if + or { /PageSize PageSize } if + % Check whether any parameters were set. + dup mark eq { pop } { defaultdevice putdeviceprops } ifelse + end +%END DEVICE +% Set any device properties defined on the command line. +% If BufferSpace is defined but not MaxBitmap, set MaxBitmap to BufferSpace. +systemdict /BufferSpace known +systemdict /MaxBitmap known not and + { systemdict /MaxBitmap BufferSpace put + } if +dup getdeviceprops +counttomark 2 idiv + { systemdict 2 index known + { pop dup load counttomark 2 roll } + { pop pop } + ifelse + } repeat +counttomark dup 0 ne + { 2 add -1 roll putdeviceprops } + { pop pop } +ifelse +setdevice % does an erasepage +% If the media size is fixed, update the current page device dictionary. +FIXEDMEDIA +dup { pop systemdict /.currentpagedevice known } if +dup { pop .currentpagedevice exch pop } if +not { (%END MEDIA) .skipeof } if +currentpagedevice dup length dict .copydict +dup /InputAttributes +2 copy get dup length dict .copydict + % Stack: /InputAttributes +dup length dict .copydict dup +0 2 copy get dup length dict .copydict + % Stack: /InputAttributes + % 0 +dup /PageSize 7 index /PageSize get +put % PageSize in 0 +put % 0 in InputAttributes +put % InputAttributes in pagedevice +.setpagedevice +%END MEDIA +%END DISPLAYING + +(END DEVICE) VMDEBUG + +% Establish a default upper limit in the character cache, +% namely, enough room for a 18-point character at the resolution +% of the default device, or for a character consuming 1% of the +% maximum cache size, whichever is larger. +mark + % Compute limit based on character size. + 18 dup dtransform + exch abs cvi 31 add 32 idiv 4 mul % X raster + exch abs cvi mul % Y + % Compute limit based on allocated space. + cachestatus pop pop pop pop pop exch pop 0.01 mul cvi + .max dup 10 idiv exch +setcacheparams +% Conditionally disable the character cache. +NOCACHE { 0 setcachelimit } if + +(END CONFIG) VMDEBUG + +% Set the default screen based on the device resolution. +/.setdefaultscreen +{ + << + /HalftoneType 3 + /Width 16 + /Height 16 + /Thresholds + < 00 80 20 A0 08 88 28 A8 02 82 22 A2 0A 8A 2A AA + C0 40 E0 60 C8 48 E8 68 C2 42 E2 62 CA 4A EA 6A + 30 B0 10 90 38 B8 18 98 32 B2 12 92 3A BA 1A 9A + F0 70 D0 50 F8 78 D8 58 F2 72 D2 52 FA 7A DA 5A + 0C 8C 2C AC 04 84 24 A4 0E 8E 2E AE 06 86 26 A6 + CC 4C EC 6C C4 44 E4 64 CE 4E EE 6E C6 46 E6 66 + 3C BC 1C 9C 34 B4 14 94 3E BE 1E 9E 36 B6 16 96 + FC 7C DC 5C F4 74 D4 54 FE 7E DE 5E F6 76 D6 56 + 03 83 23 A3 0B 8B 2B AB 01 81 21 A1 09 89 29 A9 + C3 43 E3 63 CB 4B EB 6B C1 41 E1 61 C9 49 E9 69 + 33 B3 13 93 3B BB 1B 9B 31 B1 11 91 39 B9 19 99 + F3 73 D3 53 FB 7B DB 5B F1 71 D1 51 F9 79 D9 59 + 0F 8F 2F AF 07 87 27 A7 0D 8D 2D AD 05 85 25 A5 + CF 4F EF 6F C7 47 E7 67 CD 4D ED 6D C5 45 E5 65 + 3F BF 1F 9F 37 B7 17 97 3D BD 1D 9D 35 B5 15 95 + FF 7F DF 5F F7 77 D7 57 FD 7D DD 5D F5 75 D5 55 > + >> sethalftone +} bind def +.setdefaultscreen +initgraphics +% The interpreter relies on there being at least 2 entries +% on the graphics stack. Establish the second one now. +gsave + +% Define some control sequences as no-ops. +% This is a hack to get around problems +% in some common PostScript-generating applications. +% Note that <04> and <1a> are self-delimiting characters, like [. +<04> cvn { } def % Apple job separator +%<0404> cvn { } def % two of the same +<1b> cvn { } def % MS Windows LaserJet 4 prologue +%<041b> cvn { } def % MS Windows LaserJet 4 epilogue +(\001M) cvn % TBCP initiator + { currentfile /TBCPDecode filter cvx exec + } bind def +/@PJL % H-P job control + { currentfile //=string readline { pop } if + } bind def + +% If we want a "safer" system, disable some obvious ways to cause havoc. +SAFER not { (%END SAFER) .skipeof } if +/file + { dup (r) eq 2 index (%pipe*) .stringmatch not and + { file } + { /invalidfileaccess signalerror } + ifelse + } .bind odef +/renamefile { /invalidfileaccess signalerror } odef +/deletefile { /invalidfileaccess signalerror } odef +/putdeviceprops + { counttomark + dup 2 mod 0 eq { pop /rangecheck signalerror } if + 3 2 3 2 roll + { dup index /OutputFile eq + { -2 roll + dup () ne { /putdeviceprops load /invalidfileaccess signalerror } if + 3 -1 roll + } + { pop + } + ifelse + } for + putdeviceprops + } .bind odef + +%END SAFER + +% If we delayed binding, make it possible to do it later. +/.bindnow + { //systemdict begin .bindoperators end + % Temporarily disable the typecheck error. + errordict /typecheck 2 copy get + errordict /typecheck { pop } put % pop the command + 0 1 .delaycount 1 sub { .delaybind exch get .bind pop } for + userdict /.delaybind .undef % reclaim the space + userdict /.delaycount .undef + put + } .bind def + +% Turn off array packing, since some PostScript code assumes that +% procedures are writable. +false setpacking + +% Close up systemdict. +currentdict /.forceput .undef % remove temptation +currentdict /filterdict .undef % bound in where needed +end +WRITESYSTEMDICT not { systemdict readonly pop } if + +(END INIT) VMDEBUG + +% Establish local VM as the default. +false /setglobal where { pop setglobal } { .setglobal } ifelse +$error /.nosetlocal false put + +% Clean up VM, and enable GC. +/vmreclaim where + { pop NOGC not { 2 vmreclaim 0 vmreclaim } if + } if + +(END GC) VMDEBUG + +% The interpreter will run the initial procedure (start). diff --git a/pstoraster/gs_iso_e.ps b/pstoraster/gs_iso_e.ps new file mode 100644 index 0000000000..9be8b8aab7 --- /dev/null +++ b/pstoraster/gs_iso_e.ps @@ -0,0 +1,72 @@ +% Copyright (C) 1993, 1994 Aladdin Enterprises. All rights reserved. +% +% This file is part of GNU Ghostscript. +% +% GNU Ghostscript is distributed in the hope that it will be useful, but +% WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to +% anyone for the consequences of using it or for whether it serves any +% particular purpose or works at all, unless he says so in writing. Refer to +% the GNU General Public License for full details. +% +% Everyone is granted permission to copy, modify and redistribute GNU +% Ghostscript, but only under the conditions described in the GNU General +% Public License. A copy of this license is supposed to have been given to +% you along with GNU Ghostscript so you can know your rights and +% responsibilities. It should be in a file named COPYING. Among other +% things, the copyright notice and this notice must be preserved on all +% copies. +% +% Aladdin Enterprises is not affiliated with the Free Software Foundation or +% the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, +% does not depend on any other GNU software. + +% Define the ISO Latin-1 encoding vector. +% The first half is the same as the standard encoding, +% except for minus instead of hyphen at code 055. +/ISOLatin1Encoding +StandardEncoding 0 45 getinterval aload pop + /minus +StandardEncoding 46 82 getinterval aload pop +% NOTE: the following are missing in the Adobe documentation, +% but appear in the displayed table: +% macron at 0225, dieresis at 0230, cedilla at 0233, space at 0240. +% This is an error in the Red Book, corrected in Adobe TN 5085. +% \20x + /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef + /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef + /dotlessi /grave /acute /circumflex /tilde /macron /breve /dotaccent + /dieresis /.notdef /ring /cedilla /.notdef /hungarumlaut /ogonek /caron +% \24x + /space /exclamdown /cent /sterling + /currency /yen /brokenbar /section + /dieresis /copyright /ordfeminine /guillemotleft + /logicalnot /minus /registered /macron + /degree /plusminus /twosuperior /threesuperior + /acute /mu /paragraph /periodcentered + /cedilla /onesuperior /ordmasculine /guillemotright + /onequarter /onehalf /threequarters /questiondown +% \30x + /Agrave /Aacute /Acircumflex /Atilde + /Adieresis /Aring /AE /Ccedilla + /Egrave /Eacute /Ecircumflex /Edieresis + /Igrave /Iacute /Icircumflex /Idieresis + /Eth /Ntilde /Ograve /Oacute + /Ocircumflex /Otilde /Odieresis /multiply + /Oslash /Ugrave /Uacute /Ucircumflex + /Udieresis /Yacute /Thorn /germandbls +% \34x + /agrave /aacute /acircumflex /atilde + /adieresis /aring /ae /ccedilla + /egrave /eacute /ecircumflex /edieresis + /igrave /iacute /icircumflex /idieresis + /eth /ntilde /ograve /oacute + /ocircumflex /otilde /odieresis /divide + /oslash /ugrave /uacute /ucircumflex + /udieresis /yacute /thorn /ydieresis +% Make an array on large systems, a packed array on small ones. +256 +vmstatus exch pop exch pop +100000 ge { array astore readonly } { packedarray } ifelse +def +1 ISOLatin1Encoding .registerencoding +/ISOLatin1Encoding ISOLatin1Encoding .defineencoding diff --git a/pstoraster/gs_kanji.ps b/pstoraster/gs_kanji.ps new file mode 100644 index 0000000000..c45dddfb9d --- /dev/null +++ b/pstoraster/gs_kanji.ps @@ -0,0 +1,164 @@ +% Copyright (C) 1994, 1995, 1996 Aladdin Enterprises. All rights reserved. +% +% This file is part of GNU Ghostscript. +% +% GNU Ghostscript is distributed in the hope that it will be useful, but +% WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to +% anyone for the consequences of using it or for whether it serves any +% particular purpose or works at all, unless he says so in writing. Refer to +% the GNU General Public License for full details. +% +% Everyone is granted permission to copy, modify and redistribute GNU +% Ghostscript, but only under the conditions described in the GNU General +% Public License. A copy of this license is supposed to have been given to +% you along with GNU Ghostscript so you can know your rights and +% responsibilities. It should be in a file named COPYING. Among other +% things, the copyright notice and this notice must be preserved on all +% copies. +% +% Aladdin Enterprises is not affiliated with the Free Software Foundation or +% the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, +% does not depend on any other GNU software. + +% Scaffolding for Kanji fonts. This is based on the Wadalab free font +% from the University of Tokyo; it may not be appropriate for other +% Kanji fonts. + +/currentglobal where + { pop currentglobal { setglobal } true setglobal } + { { } } +ifelse + +% Define the encoding for the root font. + +/KanjiEncoding +% \x00 + 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 +% \x20 + 0 1 2 3 4 5 6 7 + 8 0 0 0 0 0 0 0 + 9 10 11 12 13 14 15 16 + 17 18 19 20 21 22 23 24 +% \x40 + 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 +% \x60 + 57 58 59 60 61 62 63 64 + 65 66 67 68 69 70 71 72 + 73 74 75 76 77 0 0 0 + 0 0 0 0 0 0 0 0 +% \x80 + 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 +% \xA0 + 0 1 2 3 4 5 6 7 + 8 0 0 0 0 0 0 0 + 9 10 11 12 13 14 15 16 + 17 18 19 20 21 22 23 24 +% \xC0 + 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 +% \xE0 + 57 58 59 60 61 62 63 64 + 65 66 67 68 69 70 71 72 + 73 74 75 76 77 0 0 0 + 0 0 0 0 0 0 0 0 +256 packedarray def + +% Define a stub for the base font encoding. + + /KanjiSubEncoding { /KanjiSubEncoding .findencoding } bind def +%% Replace 3 (gs_ksb_e.ps) + EncodingDirectory /KanjiSubEncoding + { (gs_ksb_e.ps) //systemdict begin runlibfile KanjiSubEncoding end } + bind put + +% Support procedures and data. + +/T1FontInfo 8 dict begin + /version (001.001) readonly def + /FullName (KanjiBase) readonly def + /FamilyName (KanjiBase) readonly def + /Weight (Medium) readonly def + /ItalicAngle 0 def + /isFixedPitch false def + /UnderlinePosition 0 def + /UnderlineThickness 0 def +currentdict end readonly def + +/T1NF % T1NF +{ +20 dict begin + /FontName exch def + /FontType 1 def + /FontInfo T1FontInfo def + /FontMatrix [.001 0 0 .001 0 0] def + /FontBBox [0 0 1000 1000] def + /Encoding KanjiSubEncoding def + /CharStrings 150 dict def + /PaintType 0 def + /Private 2 dict def + Private begin + /BlueValues [] def + /password 5839 def + end +FontName currentdict end definefont +} def + +/T0NF % T0NF +{ +20 dict begin + /FontName exch def + /FDepVector exch def + /FontType 0 def + /FontMatrix [1 0 0 1 0 0] def + /FMapType 2 def + /Encoding KanjiEncoding def +FontName currentdict end definefont +} def + +% Define the composite font and all the base fonts. + +/CompNF % CompNF +{ +/newname1 exch def +newname1 dup length string cvs /str exch def +str length /len exch def +/fdepvector 78 array def +/j 1 def +16#21 1 16#74 { +/i exch def +KanjiEncoding i get 0 gt { +len 4 add string /newstr exch def +newstr 0 str putinterval +newstr len (.r) putinterval +newstr len 2 add i 16 2 string cvrs putinterval +newstr cvn /newlit exch def +newlit T1NF /newfont exch def +fdepvector j newfont put +/j j 1 add def +} if +} for +fdepvector 0 fdepvector 1 get put +/j 0 def +fdepvector newname1 T0NF +} def + +% Define an individual character in a composite font. +/CompD % <(HL)> CompD - + { currentfont /Encoding get 1 index 0 get get % FDepVector index + currentfont /FDepVector get exch get % base font + dup /Encoding get 3 -1 roll 1 get get % base font character name + exch /CharStrings get exch 3 -1 roll put + } bind def + +exec diff --git a/pstoraster/gs_ksb_e.ps b/pstoraster/gs_ksb_e.ps new file mode 100644 index 0000000000..765a05e3bc --- /dev/null +++ b/pstoraster/gs_ksb_e.ps @@ -0,0 +1,70 @@ +% Copyright (C) 1994 Aladdin Enterprises. All rights reserved. +% +% This file is part of GNU Ghostscript. +% +% GNU Ghostscript is distributed in the hope that it will be useful, but +% WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to +% anyone for the consequences of using it or for whether it serves any +% particular purpose or works at all, unless he says so in writing. Refer to +% the GNU General Public License for full details. +% +% Everyone is granted permission to copy, modify and redistribute GNU +% Ghostscript, but only under the conditions described in the GNU General +% Public License. A copy of this license is supposed to have been given to +% you along with GNU Ghostscript so you can know your rights and +% responsibilities. It should be in a file named COPYING. Among other +% things, the copyright notice and this notice must be preserved on all +% copies. +% +% Aladdin Enterprises is not affiliated with the Free Software Foundation or +% the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, +% does not depend on any other GNU software. + +% Define the KanjiSub encoding vector. +/currentglobal where + { pop currentglobal { setglobal } true setglobal } + { { } } +ifelse +/KanjiSubEncoding +%\x00 + /.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 +%\x20 + /.notdef /c21 /c22 /c23 /c24 /c25 /c26 /c27 + /c28 /c29 /c2A /c2B /c2C /c2D /c2E /c2F + /c30 /c31 /c32 /c33 /c34 /c35 /c36 /c37 + /c38 /c39 /c3A /c3B /c3C /c3D /c3E /c3F +%\x40 + /c40 /c41 /c42 /c43 /c44 /c45 /c46 /c47 + /c48 /c49 /c4A /c4B /c4C /c4D /c4E /c4F + /c50 /c51 /c52 /c53 /c54 /c55 /c56 /c57 + /c58 /c59 /c5A /c5B /c5C /c5D /c5E /c5F +%\x60 + /c60 /c61 /c62 /c63 /c64 /c65 /c66 /c67 + /c68 /c69 /c6A /c6B /c6C /c6D /c6E /c6F + /c70 /c71 /c72 /c73 /c74 /c75 /c76 /c77 + /c78 /c79 /c7A /c7B /c7C /c7D /c7E /.notdef +%\x80 + /.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 +%\xA0 + /.notdef /c21 /c22 /c23 /c24 /c25 /c26 /c27 + /c28 /c29 /c2A /c2B /c2C /c2D /c2E /c2F + /c30 /c31 /c32 /c33 /c34 /c35 /c36 /c37 + /c38 /c39 /c3A /c3B /c3C /c3D /c3E /c3F +%\xC0 + /c40 /c41 /c42 /c43 /c44 /c45 /c46 /c47 + /c48 /c49 /c4A /c4B /c4C /c4D /c4E /c4F + /c50 /c51 /c52 /c53 /c54 /c55 /c56 /c57 + /c58 /c59 /c5A /c5B /c5C /c5D /c5E /c5F +%\xE0 + /c60 /c61 /c62 /c63 /c64 /c65 /c66 /c67 + /c68 /c69 /c6A /c6B /c6C /c6D /c6E /c6F + /c70 /c71 /c72 /c73 /c74 /c75 /c76 /c77 + /c78 /c79 /c7A /c7B /c7C /c7D /c7E /.notdef +256 packedarray .defineencoding +exec diff --git a/pstoraster/gs_l2img.ps b/pstoraster/gs_l2img.ps new file mode 100644 index 0000000000..2a24c3cb02 --- /dev/null +++ b/pstoraster/gs_l2img.ps @@ -0,0 +1,191 @@ +% Copyright (C) 1995, 1996 Aladdin Enterprises. All rights reserved. +% +% This file is part of GNU Ghostscript. +% +% GNU Ghostscript is distributed in the hope that it will be useful, but +% WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to +% anyone for the consequences of using it or for whether it serves any +% particular purpose or works at all, unless he says so in writing. Refer to +% the GNU General Public License for full details. +% +% Everyone is granted permission to copy, modify and redistribute GNU +% Ghostscript, but only under the conditions described in the GNU General +% Public License. A copy of this license is supposed to have been given to +% you along with GNU Ghostscript so you can know your rights and +% responsibilities. It should be in a file named COPYING. Among other +% things, the copyright notice and this notice must be preserved on all +% copies. +% +% Aladdin Enterprises is not affiliated with the Free Software Foundation or +% the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, +% does not depend on any other GNU software. + +% Emulate the Level 2 dictionary-based image operator in Level 1, +% except for Interpolate (ignored) and MultipleDataSources = true; +% also, we require that the data source be either a procedure of a +% particular form or a stream, not a string or a general procedure. + +% pdf2ps copies the portion of this file from %BEGIN to %END if Level 1 +% compatible output is requested. + +/currentglobal where + { pop currentglobal { setglobal } true setglobal } + { { } } +ifelse + +/packedarray where + { pop } + { /packedarray { array astore readonly } bind def } +ifelse + +%BEGIN + +11 dict /.csncompdict 1 index def begin + /DeviceGray { 1 /setgray load } bind def + /DeviceRGB { 3 /setrgbcolor load } bind def + /DeviceCMYK { 4 /setcmykcolor load } bind def + /Indexed + { dup 1 index 1 get //.csncompdict exch get exec + % Stack: [/Indexed base hival map] ncomp basesetcolor + 3 -1 roll 3 get mark 3 1 roll + % Stack: ncomp -mark- basesetcolor map + dup type /stringtype eq + { { - + { exch round cvi get 255 div + } + - + { exch round cvi 3 mul 2 copy 2 copy get 255 div + 3 1 roll 1 add get 255 div + 4 2 roll 2 add get 255 div + } + { exch round cvi 4 mul 2 copy 2 copy 2 copy get 255 div + 3 1 roll 1 add get 255 div + 4 2 roll 2 add get 255 div + 5 3 roll 3 add get 255 div + } + } + 4 index get aload pop counttomark -1 roll + } + { /exec load 3 -1 roll + % Stack: -mark- mapproc --exec-- basesetcolor + } + ifelse .packtomark cvx + exch pop 1 exch + } bind def + /Separation + { dup 2 index //.csncompdict exch get exec + % Stack: [/Separation name alt xform] ncomp altsetcolor + 3 -1 roll 3 get /exec load 3 -1 roll 3 array astore readonly cvx + exch pop 1 exch + } bind def + % Substitute device spaces for CIE spaces. + /CIEBasedA /DeviceGray load def + /CIEBasedABC /DeviceRGB load def + /CIEBasedDEF /DeviceRGB load def + /CIEBasedDEFG /DeviceCMYK load def +end + +/.packtomark { counttomark packedarray exch pop } bind def + +/.csinextbits % - .csinextbits + % Uses b, nnb, i, row, mask, BitsPerComponent; + % sets b, nnb, i. + { /nnb nnb BitsPerComponent add + { dup 0 le { exit } if + /b b 8 bitshift row i get add def + /i i 1 add def 8 sub + } + loop def + b nnb bitshift mask and + } bind def + +% Note that the ColorSpace key must be present in the image dictionary. +/.colorspaceimage % .colorspaceimage - + { save exch + dup length 15 add dict begin { cvlit def } forall + ColorSpace dup dup type /nametype ne { 0 get } if + .csncompdict exch get exec + /setpixelcolor exch def /ncomp exch def pop + /row ncomp BitsPerComponent mul Width mul 7 add 8 idiv string def + /mask 1 BitsPerComponent bitshift 1 sub def + /nextbits BitsPerComponent 8 eq + { { row i get /i i 1 add def } } + { /.csinextbits load } + ifelse def + /nextpixel mark 0 2 ncomp 1 sub 2 mul + { /nextbits cvx exch + Decode exch 2 getinterval + dup aload pop exch sub + dup mask eq { pop } { mask div /mul load 3 -1 roll } ifelse + 0 get dup 0 eq { pop } { /sub load 3 -1 roll } ifelse + } + for + /setpixelcolor load dup type /operatortype ne { /exec load } if + .packtomark cvx def + /readrow + /DataSource load dup type + dup /arraytype eq exch /packedarraytype eq or + { % Must be { ... } + aload length 1 add array /pop load exch astore + dup 1 row put cvx + } + { pop + % Adobe requires readstring to signal an error if given + % an empty string. Work around this nonsense here. + row length 0 eq + { { } } + { { DataSource row readstring pop pop } } + ifelse + } + ifelse def + ImageMatrix matrix invertmatrix concat + /imat matrix def + 0 1 Height 1 sub + { imat 5 3 -1 roll neg put +%(.) print flush + readrow + /b 0 def /nnb 0 def /i 0 def + 0 1 Width 1 sub + { imat 4 3 -1 roll neg put nextpixel + 1 1 true imat {<80>} imagemask + } + for + } + for + end restore + } bind def + +%END +exec +currentfile closefile + +% Patch for testing. +/.cincompdict 3 dict begin + 1 { {0 1} {/DeviceGray} } def + 3 { {0 1 0 1 0 1} {/DeviceRGB} } def + 4 { {0 1 0 1 0 1 0 1} {/DeviceCMYK} } def +currentdict end def +/.imagekeys [ + /Decode /DataSource /ImageMatrix /BitsPerComponent /Height /Width +] def +/colorimage % + % false colorimage - + { 1 index { /colorimage load /rangecheck signalerror } if exch pop + //.cincompdict exch get exec + 7 dict begin /ColorSpace exch cvlit def + .imagekeys { exch cvlit def } forall + currentdict end .colorspaceimage + } bind odef +/image + { dup type /dicttype ne + { 7 dict begin /ColorSpace /DeviceGray def [0 1] + .imagekeys { exch cvlit def } forall + currentdict end + } + { dup length 1 add dict .copydict dup /ColorSpace currentcolorspace put + } + ifelse + .colorspaceimage + } bind odef + +exec diff --git a/pstoraster/gs_lev2.ps b/pstoraster/gs_lev2.ps new file mode 100644 index 0000000000..125872f1ff --- /dev/null +++ b/pstoraster/gs_lev2.ps @@ -0,0 +1,332 @@ +% Copyright (C) 1990, 1996 Aladdin Enterprises. All rights reserved. +% +% This file is part of GNU Ghostscript. +% +% GNU Ghostscript is distributed in the hope that it will be useful, but +% WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to +% anyone for the consequences of using it or for whether it serves any +% particular purpose or works at all, unless he says so in writing. Refer to +% the GNU General Public License for full details. +% +% Everyone is granted permission to copy, modify and redistribute GNU +% Ghostscript, but only under the conditions described in the GNU General +% Public License. A copy of this license is supposed to have been given to +% you along with GNU Ghostscript so you can know your rights and +% responsibilities. It should be in a file named COPYING. Among other +% things, the copyright notice and this notice must be preserved on all +% copies. +% +% Aladdin Enterprises is not affiliated with the Free Software Foundation or +% the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, +% does not depend on any other GNU software. + +% Initialization file for Level 2 functions. +% When this is run, systemdict is still writable, +% but (almost) everything defined here goes into level2dict. + +level2dict begin + +% ------ Miscellaneous ------ % + +(<<) cvn /mark load def +(>>) cvn /.dicttomark load def +/currentsystemparams { mark .currentsystemparams .dicttomark } odef +/currentuserparams { mark .currentuserparams .dicttomark } odef +/deviceinfo { currentdevice getdeviceprops .dicttomark readonly } odef +/languagelevel 2 def +% When running in Level 2 mode, this interpreter is supposed to be +% compatible with PostScript version 2017 (I think). +/version (2017) def + +% If binary tokens are supported by this interpreter, +% set an appropriate default binary object format. +/setobjectformat where + { pop + currentsystemparams dup + /RealFormat get (IEEE) eq { 1 } { 3 } ifelse + exch /ByteOrder get { 1 add } if + setobjectformat + } if + +% ------ Virtual memory ------ % + +/currentglobal /currentshared load def +/gcheck /scheck load def +/setglobal /setshared load def +% We can make the global dictionaries very small, because they auto-expand. +/globaldict currentdict /shareddict .knownget not { 4 dict } if def +/GlobalFontDirectory SharedFontDirectory def + +% ------ IODevices ------ % + +/.getdevparams where + { pop /currentdevparams { .getdevparams .dicttomark } odef + } if +/.putdevparams where + { pop /setdevparams { mark exch { } forall counttomark 2 add -1 roll .putdevparams } odef + } if + +% ------ Job control ------ % + +serverdict begin + +% We could protect the job information better, but we aren't attempting +% (currently) to protect ourselves against maliciousness. + +/.jobsave null def % top-level save object +/.jobsavelevel 0 def % save depth of job (0 if .jobsave is null, + % 1 otherwise) +/.adminjob true def % status of current unencapsulated job + +/exitserver + { true exch startjob not { /exitserver /invalidaccess signalerror } if + } bind def + +end % serverdict + +%**************** The definition of startjob is not complete yet, since +% it doesn't clear the exec stack, doesn't reset stdin/stdout, +% doesn't run the job under its own control, and doesn't reset +% other aspects of the interpreter. +/startjob + { vmstatus pop pop serverdict /.jobsavelevel get eq + 1 index .checkpassword 0 gt and + { .checkpassword count 2 roll count 2 sub { pop } repeat + cleardictstack + serverdict /.jobsave get dup null eq { pop } { restore } ifelse + exch + { % unencapsulated job + serverdict /.jobsave null put + serverdict /.jobsavelevel 0 put + serverdict /.adminjob 3 -1 roll 1 gt put + } + { % encapsulated job + serverdict /.jobsave save put + serverdict /.jobsavelevel 1 put + userdict /quit /stop load put + pop + } + ifelse true + } + { pop pop false + } + ifelse + } odef + +systemdict begin +/quit + { //systemdict /serverdict get /.jobsave get null eq + { //quit } + { //systemdict /quit get /invalidaccess signalerror } + ifelse + } bind odef +end + +% ------ Compatibility ------ % + +% In Level 2 mode, the following replace the definitions that gs_statd.ps +% installs in statusdict and serverdict. +% Note that statusdict must be allocated in local VM. +% We don't bother with many of these yet, and the ones defined in terms +% of currentsystemparams are cavalier about allocating a dictionary +% in order to retrieve a single element from it.... + +/.dict1 { exch mark 3 1 roll .dicttomark } bind def + +currentglobal false setglobal 25 dict exch setglobal begin +currentsystemparams + +/buildtime 1 index /BuildTime get def +/byteorder 1 index /ByteOrder get def +/checkpassword { .checkpassword 0 gt } bind def +/defaulttimeouts + { currentsystemparams dup + /JobTimeout .knownget not { 0 } if + exch /WaitTimeout .knownget not { 0 } if + currentpagedevice /ManualFeedTimeout .knownget not { 0 } if + } bind def +dup /DoStartPage known + { /dostartpage { currentsystemparams /DoStartPage get } bind def + /setdostartpage { /DoStartPage .dict1 setsystemparams } bind def + } if +dup /StartupMode known + { /dosysstart { currentsystemparams /StartupMode get 0 ne } bind def + /setdosysstart { { 1 } { 0 } ifelse /StartupMode .dict1 setsystemparams } bind def + } if +%****** Setting jobname is supposed to set userparams.JobName, too. +/jobname { currentuserparams /JobName get } bind def +/jobtimeout { currentuserparams /JobTimeout get } bind def +%manualfeed +%manualfeedtimeout +/margins + { currentpagedevice /Margins .knownget { exch } { [0 0] } ifelse + } bind def +%pagecount +%pagestackorder +/printername + { currentsystemparams /PrinterName .knownget not { () } if exch copy + } bind def +%/ramsize { currentsystemparams /RamSize get } bind def +/realformat 1 index /RealFormat get def + +/.setpagedevice where + { pop + /setdefaulttimeouts + { exch mark /ManualFeedTimeout 3 -1 roll + /Policies mark /ManualFeedTimeout 1 .dicttomark + .dicttomark setpagedevice + /WaitTimeout exch mark /JobTimeout 5 2 roll .dicttomark setsystemparams + } bind def + /setmargins + { exch 2 array astore /Margins .dict1 setpagedevice + } bind def + } +if +%setpagestackorder +dup /PrinterName known + { /setprintername { /PrinterName .dict1 setsystemparams } bind def + } if +currentuserparams /WaitTimeout known + { /waittimeout { currentuserparams /WaitTimeout get } bind def + } if + +/.setpagedevice where + { pop + /pagemargin + { currentpagedevice /PageOffset .knownget { 0 get } { 0 } ifelse + } bind def + /pageparams + { currentpagedevice + dup /Orientation .knownget { 1 and ORIENT1 { 1 xor } if } { 0 } ifelse exch + dup /PageSize get aload pop 3 index 0 ne { exch } if 3 2 roll + /PageOffset .knownget { 0 get } { 0 } ifelse 4 -1 roll + } bind def + /.setpagesize { 2 array astore /PageSize .dict1 setpagedevice } bind def + /setduplexmode { /Duplex .dict1 setpagedevice } bind def + /setpagemargin { 0 2 array astore /PageOffset .dict1 setpagedevice } bind def + /setpageparams + { mark /PageSize 6 -2 roll + 4 index 1 and ORIENT1 { 1 } { 0 } ifelse ne { exch } if 2 array astore + /Orientation 5 -1 roll ORIENT1 { 1 xor } if + /PageOffset counttomark 2 add -1 roll 0 2 array astore + .dicttomark setpagedevice + } bind def + /setresolution + { dup 2 array astore /HWResolution .dict1 setpagedevice + } bind def + } +if + +pop % currentsystemparams + +% Flag the current dictionary so it will be swapped when we +% change language levels. (See zmisc2.c for more information.) +/statusdict currentdict def + +currentdict end +/statusdict exch def + +% ------ Color spaces ------ % + +% Define the setcolorspace procedures. +/colorspacedict mark + /DeviceGray { pop 0 setgray } bind + /DeviceRGB { pop 0 0 0 setrgbcolor } bind + /setcmykcolor where + { pop /DeviceCMYK { pop 0 0 0 1 setcmykcolor } bind + } if + /.setcieaspace where + { pop /CIEBasedA { NOCIE { pop 0 setgray } { 1 get .setcieaspace } ifelse } bind + } if + /.setcieabcspace where + { pop /CIEBasedABC { NOCIE { pop 0 0 0 setrgbcolor } { 1 get .setcieabcspace } ifelse } bind + } if + /.setciedefspace where + { pop /CIEBasedDEF { NOCIE { pop 0 0 0 setrgbcolor } { 1 get .setciedefspace } ifelse } bind + } if + /.setciedefgspace where + { pop /CIEBasedDEFG { NOCIE { pop 0 0 0 1 setcmykcolor } { 1 get .setciedefgspace } ifelse } bind + } if + /.setseparationspace where + { pop /Separation { dup 2 get setcolorspace .setseparationspace } bind + } if + /.setindexedspace where + { pop /Indexed { dup 1 get setcolorspace .setindexedspace } bind + } if + /.setpatternspace where + { pop /Pattern + { dup length 1 gt { dup 1 get setcolorspace } if + .setpatternspace + } bind + } if +.dicttomark def + +/.devcs [/DeviceGray /DeviceRGB /DeviceCMYK] readonly def +/currentcolorspace + { .currentcolorspace dup type /integertype eq + { //.devcs exch 1 getinterval + } if + } odef +currentdict /.devcs .undef + +/setcolorspace + { dup type /nametype eq { 1 array astore } if + dup //colorspacedict 1 index 0 get get exec + .setcolorspace + } odef + +% Initialize the CIE rendering dictionary if necessary. +% The most common CIE files seem to assume the "calibrated RGB color space" +% described on p. 189 of the PostScript Language Reference Manual, +% 2nd Edition; we simply invert this transformation back to RGB. +/setcolorrendering where + { pop mark + /ColorRenderingType 1 +% We must make RangePQR and RangeLMN large enough so that values computed by +% the assumed encoding MatrixLMN don't get clamped. + /RangePQR [0 0.9505 0 1 0 1.0890] + /TransformPQR [ { } dup dup ] + /RangeLMN [0 0.9505 0 1 0 1.0890] + /MatrixABC + [ 3.24063 -0.96893 0.05571 + -1.53721 1.87576 -0.20402 + -0.49863 0.04152 1.05700 + ] + /EncodeABC [{0 max 0.45 exp} bind dup dup] + /WhitePoint [0.9505 1 1.0890] + .dicttomark setcolorrendering + } if + +% ------ Painting ------ % + +% A straightforward definition of execform that doesn't actually +% do any caching. +/execform + { dup /Implementation known not + { dup /FormType get 1 ne { /rangecheck signalerror } if + dup /Implementation null put readonly + } if + gsave dup /Matrix get concat + dup /BBox get aload pop + exch 3 index sub exch 2 index sub rectclip + dup /PaintProc get exec + grestore + } odef + +/makepattern + { currentglobal + { false setglobal .buildpattern true setglobal } + { .buildpattern } + ifelse + exch dup length 1 add dict .copydict + dup /Implementation 4 -1 roll put + readonly + } odef + +/setpattern + { currentcolorspace 0 get /Pattern ne + { [ /Pattern currentcolorspace ] setcolorspace } if + setcolor + } odef + +end % level2dict diff --git a/pstoraster/gs_mex_e.ps b/pstoraster/gs_mex_e.ps new file mode 100644 index 0000000000..fb4ba6936e --- /dev/null +++ b/pstoraster/gs_mex_e.ps @@ -0,0 +1,70 @@ +% Copyright (C) 1994 Aladdin Enterprises. All rights reserved. +% +% This file is part of GNU Ghostscript. +% +% GNU Ghostscript is distributed in the hope that it will be useful, but +% WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to +% anyone for the consequences of using it or for whether it serves any +% particular purpose or works at all, unless he says so in writing. Refer to +% the GNU General Public License for full details. +% +% Everyone is granted permission to copy, modify and redistribute GNU +% Ghostscript, but only under the conditions described in the GNU General +% Public License. A copy of this license is supposed to have been given to +% you along with GNU Ghostscript so you can know your rights and +% responsibilities. It should be in a file named COPYING. Among other +% things, the copyright notice and this notice must be preserved on all +% copies. +% +% Aladdin Enterprises is not affiliated with the Free Software Foundation or +% the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, +% does not depend on any other GNU software. + +% Define the MacExpert encoding vector. +/currentglobal where + { pop currentglobal { setglobal } true setglobal } + { { } } +ifelse +/MacExpertEncoding +% \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 /exclamsmall /Hungarumlautsmall /centoldstyle /dollaroldstyle /dollarsuperior /ampersandsmall /Acutesmall + /parenleftsuperior /parenrightsuperior /twodotenleader /onedotenleader /comma /hyphen /period /fraction + /zerooldstyle /oneoldstyle /twooldstyle /threeoldstyle /fouroldstyle /fiveoldstyle /sixoldstyle /sevenoldstyle + /eightoldstyle /nineoldstyle /colon /semicolon /.notdef /threequartersemdash /.notdef /questionsmall +% \10x + /.notdef /.notdef /.notdef /.notdef /Ethsmall /.notdef /.notdef /onequarter + /onehalf /threequarters /oneeighth /threeeighths /fiveeighths /seveneighths /onethird /twothirds + /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /ff /fi + /fl /ffi /ffl /parenleftinferior /.notdef /parenrightinferior /Circumflexsmall /hypheninferior +% \14x + /Gravesmall /Asmall /Bsmall /Csmall /Dsmall /Esmall /Fsmall /Gsmall + /Hsmall /Ismall /Jsmall /Ksmall /Lsmall /Msmall /Nsmall /Osmall + /Psmall /Qsmall /Rsmall /Ssmall /Tsmall /Usmall /Vsmall /Wsmall + /Xsmall /Ysmall /Zsmall /colonmonetary /onefitted /rupiah /Tildesmall /.notdef +% \20x + /.notdef /asuperior /centsuperior /.notdef /.notdef /.notdef /.notdef /Aacutesmall + /Agravesmall /Acircumflexsmall /Adieresissmall /Atildesmall /Aringsmall /Ccedillasmall /Eacutesmall /Egravesmall + /Ecircumflexsmall /Edieresissmall /Iacutesmall /Igravesmall /Icircumflexsmall /Idieresissmall /Ntildesmall /Oacutesmall + /Ogravesmall /Ocircumflexsmall /Odieresissmall /Otildesmall /Uacutesmall /Ugravesmall /Ucircumflexsmall /Udieresissmall +% \24x + /.notdef /eightsuperior /fourinferior /threeinferior /sixinferior /eightinferior /seveninferior /Scaronsmall + /.notdef /centinferior /twoinferior /.notdef /Dieresissmall /.notdef /Caronsmall /osuperior + /fiveinferior /.notdef /commainferior /periodinferior /Yacutesmall /.notdef /dollarinferior /.notdef + /.notdef /Thornsmall /.notdef /nineinferior /zeroinferior /Zcaronsmall /AEsmall /Oslashsmall +% \30x + /questiondownsmall /oneinferior /Lslashsmall /.notdef /.notdef /.notdef /.notdef /.notdef + /.notdef /Cedillasmall /.notdef /.notdef /.notdef /.notdef /.notdef /OEsmall + /figuredash /hyphensuperior /.notdef /.notdef /.notdef /.notdef /exclamdownsmall /.notdef + /Ydieresissmall /.notdef /onesuperior /twosuperior /threesuperior /foursuperior /fivesuperior /sixsuperior +% \34x + /sevensuperior /ninesuperior /zerosuperior /.notdef /esuperior /rsuperior /tsuperior /.notdef + /.notdef /isuperior /ssuperior /dsuperior /.notdef /.notdef /.notdef /.notdef + /.notdef /lsuperior /Ogoneksmall /Brevesmall /Macronsmall /bsuperior /nsuperior /msuperior + /commasuperior /periodsuperior /Dotaccentsmall /Ringsmall /.notdef /.notdef /.notdef /.notdef +256 packedarray .defineencoding +exec diff --git a/pstoraster/gs_mro_e.ps b/pstoraster/gs_mro_e.ps new file mode 100644 index 0000000000..f77cc74610 --- /dev/null +++ b/pstoraster/gs_mro_e.ps @@ -0,0 +1,63 @@ +% Copyright (C) 1994 Aladdin Enterprises. All rights reserved. +% +% This file is part of GNU Ghostscript. +% +% GNU Ghostscript is distributed in the hope that it will be useful, but +% WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to +% anyone for the consequences of using it or for whether it serves any +% particular purpose or works at all, unless he says so in writing. Refer to +% the GNU General Public License for full details. +% +% Everyone is granted permission to copy, modify and redistribute GNU +% Ghostscript, but only under the conditions described in the GNU General +% Public License. A copy of this license is supposed to have been given to +% you along with GNU Ghostscript so you can know your rights and +% responsibilities. It should be in a file named COPYING. Among other +% things, the copyright notice and this notice must be preserved on all +% copies. +% +% Aladdin Enterprises is not affiliated with the Free Software Foundation or +% the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, +% does not depend on any other GNU software. + +% Define the MacRoman encoding vector. +/currentglobal where + { pop currentglobal { setglobal } true setglobal } + { { } } +ifelse +/MacRomanEncoding +StandardEncoding 0 39 getinterval aload pop + /quotesingle +StandardEncoding 40 56 getinterval aload pop + /grave +StandardEncoding 97 31 getinterval aload pop +% \20x + /Adieresis /Aring /Ccedilla /Eacute /Ntilde /Odieresis /Udieresis /aacute + /agrave /acircumflex /adieresis /atilde /aring /ccedilla /eacute /egrave + /ecircumflex /edieresis /iacute /igrave + /icircumflex /idieresis /ntilde /oacute + /ograve /ocircumflex /odieresis /otilde + /uacute /ugrave /ucircumflex /udieresis +% \24x + /dagger /degree /cent /sterling /section /bullet /paragraph /germandbls + /registered /copyright /trademark /acute /dieresis /.notdef /AE /Oslash + /.notdef /plusminus /.notdef /.notdef /yen /mu /.notdef /.notdef + /.notdef /.notdef /.notdef /ordfeminine /ordmasculine /.notdef /ae /oslash +% \30x + /questiondown /exclamdown /logicalnot /.notdef + /florin /.notdef /.notdef /guillemotleft + /guillemotright /ellipsis /space /Agrave /Atilde /Otilde /OE /oe + /endash /emdash /quotedblleft /quotedblright + /quoteleft /quoteright /divide /.notdef + /ydieresis /Ydieresis /fraction /currency + /guilsingleft /guilsingright /fi /fl +% \34x + /daggerdbl /periodcentered /quotesinglbase /quotedblbase + /perthousand /Acircumflex /Ecircumflex /Aacute + /Edieresis /Egrave /Iacute /Icircumflex + /Idieresis /Igrave /Oacute /Ocircumflex + /.notdef /Ograve /Uacute /Ucircumflex + /Ugrave /dotlessi /circumflex /tilde + /macron /breve /dotaccent /ring /cedilla /hungarumlaut /ogonek /caron +256 packedarray .defineencoding +exec diff --git a/pstoraster/gs_pdf.ps b/pstoraster/gs_pdf.ps new file mode 100644 index 0000000000..2c4ce8df49 --- /dev/null +++ b/pstoraster/gs_pdf.ps @@ -0,0 +1,575 @@ +% Copyright (C) 1994, 1996 Aladdin Enterprises. All rights reserved. +% +% This file is part of GNU Ghostscript. +% +% GNU Ghostscript is distributed in the hope that it will be useful, but +% WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to +% anyone for the consequences of using it or for whether it serves any +% particular purpose or works at all, unless he says so in writing. Refer to +% the GNU General Public License for full details. +% +% Everyone is granted permission to copy, modify and redistribute GNU +% Ghostscript, but only under the conditions described in the GNU General +% Public License. A copy of this license is supposed to have been given to +% you along with GNU Ghostscript so you can know your rights and +% responsibilities. It should be in a file named COPYING. Among other +% things, the copyright notice and this notice must be preserved on all +% copies. +% +% Aladdin Enterprises is not affiliated with the Free Software Foundation or +% the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, +% does not depend on any other GNU software. + +% gs_pdf.ps +% ProcSet for PostScript files created by the PDF to PostScript converter. +% This ProcSet requires only a Level 1 interpreter. + +% pdf2ps copies this file from %BEGIN to the end. + +%BEGIN +mark % patches +/currentglobal { false } +/setglobal { pop } +/packedarray { array astore readonly } +/setcmykcolor + { 1 exch sub + 4 -1 roll 1 exch sub 1 index mul + 4 -1 roll 1 exch sub 2 index mul + 4 -2 roll exch 1 exch sub mul + setrgbcolor + } +/.copydict + { dup 3 -1 roll { put dup } forall pop } +/.dicttomark + { counttomark 2 idiv dup dict begin { def } repeat pop currentdict end } +/.knownget + { 2 copy known { get true } { pop pop false } ifelse } +counttomark 2 idiv + { 1 index where { pop pop pop } { bind executeonly def } ifelse + } repeat pop + +currentglobal true setglobal + +% Define pdfmark. Don't allow it to be bound in. +% Also don't define it in systemdict, because this leads some Adobe code +% to think this interpreter is a distiller. +% (If this interpreter really is a distiller, don't do this.) +systemdict /pdfmark known not + { userdict /pdfmark { cleartomark } bind put } if + +% This ProcSet is designed so that it can be used either to execute PDF +% (the default) or to convert PDF to PostScript. See ! and ~ below. + +userdict /GS_PDF_ProcSet 119 dict dup begin + +% ---------------- Abbreviations ---------------- % + +/bdef { bind def } bind def + +% ---------------- Operator execution ---------------- % + +% We record "operator" names in a dictionary with their argument counts, +% so that they can easily be redefined later to write PostScript in +% addition to (or instead of) being executed. + +/numargsdict 100 dict def +/! % ! - + { //numargsdict 3 index 3 -1 roll put def + } bdef +/~ % ~ - + { exch cvx 1 packedarray cvx exch ! + } bdef + +% ---------------- Graphics state stack ---------------- % + +% PDF adds a number of parameters to the graphics state. +% We implement this by pushing and popping a dictionary +% each time we do a PDF gsave or grestore. +% The keys in this dictionary are as follows: +% self % identifies the dictionary as one of ours +% Show +% TextOrigin % origin of current line, in text space +% TextSaveMatrix % matrix at time of BT +% (The following correspond directly to PDF state parameters.) +% FillColor +% FillColorSpace +% StrokeColor +% StrokeColorSpace +% TextSpacing +% TextHScaling +% Leading +% TextFont +% TextMatrix +% TextRise +% TextRenderingMode +% WordSpacing + +/nodict 1 dict def +nodict /self { //nodict } executeonly put +nodict readonly pop + +/beginpage + { //nodict 20 dict .copydict begin graphicsbeginpage textbeginpage + } bdef +/endpage + { showpage end + } bdef + +/graphicsbeginpage { initgraphics 0 g 0 G } bdef + +/gput % gput - + { exch currentdict //nodict eq { /self dup load end 5 dict begin def } if + % If we're in a Level 1 system, we need to grow the + % dictionary explicitly. + currentdict length currentdict maxlength ge %eq + { currentdict dup length 3 mul 2 idiv 1 add dict .copydict end begin + } + if def + } bdef + +/q_ + { gsave //nodict begin + } bdef +/q /q_ load 0 ! +% Some PDF files have excess Q operators! +/Q_ + { currentdict /self .knownget { exec //nodict eq { end grestore } if } if + } bdef +/Q /Q_ load 0 ! + +% ---------------- Graphics state parameters ---------------- % + +/d /setdash 2 ~ +/i /setflat 1 ~ +/j /setlinejoin 1 ~ +/J /setlinecap 1 ~ +/M /setmiterlimit 1 ~ +/w /setlinewidth 1 ~ + +% ---------------- Color setting ---------------- % + +/fcput % fcput - + { /FillColorSpace gput /FillColor gput + } bdef +/scput % scput - + { /StrokeColorSpace gput /StrokeColor gput + } bdef + +/csdevgray [/DeviceGray] readonly def +/csdevrgb [/DeviceRGB] readonly def +/csdevcmyk [/DeviceCMYK] readonly def + +/CSdict 11 dict dup begin + /DeviceGray { 0 exch } bdef + /DeviceRGB { [0 0 0] cvx exch } bdef + /DeviceCMYK { [0 0 0 1] cvx exch } bdef + /Indexed + { dup 1 get csset exch pop + dup 2 index 1 get eq + { pop } + { exch 4 array copy dup 1 4 -1 roll put } + ifelse 0 exch + } bdef + /setcolorrendering where + { pop + /CalGray + { 1 get dup /Gamma .knownget + { dup length 1 add dict .copydict + dup /DecodeA 4 -1 roll /exp load 2 packedarray cvx put + } + if /CIEBasedA exch 2 array astore 0 exch + } bdef + /CalRGB + { 1 get dup /Gamma known 1 index /Matrix known or + { dup length 2 add dict .copydict + dup /Matrix .knownget { 1 index /MatrixABC 3 -1 roll put } if + dup /Gamma .knownget + { [ exch { /exp load 2 packedarray cvx } forall + ] 1 index /DecodeABC 3 -1 roll put + } + if + } + if /CIEBasedABC exch 2 array astore [0 0 0] cvx exch + } bdef + /CalCMYK { pop //csdevcmyk csset } bdef % not supported yet + } + { /CalGray { pop //csdevgray csset } bdef + /CalRGB { pop //csdevrgb csset } bdef + /CalCMYK { pop //csdevcmyk csset } bdef + } + ifelse +end def +/csset % csset + { dup dup type /nametype ne { 0 get } if //CSdict exch get exec + } bdef + +/g { //csdevgray fcput } 1 ! +/G { //csdevgray scput } 1 ! +/rg { 3 array astore cvx //csdevrgb fcput } 3 ! +/RG { 3 array astore cvx //csdevrgb scput } 3 ! +/k { 4 array astore cvx //csdevcmyk fcput } 4 ! +/K { 4 array astore cvx //csdevcmyk scput } 4 ! +/cs { csset fcput } 1 ! +/CS { csset scput } 1 ! +% We have to break up sc according to the number of operands. +/sc1 { /FillColor gput } 1 ! +/SC1 { /StrokeColor gput } 1 ! +/sc3 { /FillColor load astore pop } 3 ! +/SC3 { /StrokeColor load astore pop } 3 ! +/sc4 { /FillColor load astore pop } 4 ! +/SC4 { /StrokeColor load astore pop } 4 ! + +% ---------------- Color installation ---------------- % + +% Establish a given color (and color space) as current. +/setfillcolor { FillColor FillColorSpace setgcolor } def +/setstrokecolor { StrokeColor StrokeColorSpace setgcolor } def +/CIdict mark % only used for Level 1 + /DeviceGray 1 /DeviceRGB 3 /DeviceCMYK 4 + /CIEBaseA 1 /CIEBaseABC 3 /CIEBasedDEF 3 /CIEBaseDEFG 4 +.dicttomark def +/Cdict 11 dict dup begin % -proc- - + /DeviceGray { pop setgray } bdef + /DeviceRGB { pop setrgbcolor } bdef + /DeviceCMYK { pop setcmykcolor } bdef + /CIEBasedA + { dup currentcolorspace eq { pop } { setcolorspace } ifelse setcolor } bdef + /CIEBasedABC /CIEBasedA load def + /CIEBasedDEF /CIEBasedA load def + /CIEBasedDEFG /CIEBasedA load def + /Indexed /setcolorspace where + { pop /CIEBasedA load } + { /setindexedcolor cvx } + ifelse def +end def +/setindexedcolor % [/Indexed base hival proc|str] + % setindexedcolor - (only used for Level 1) + { mark 3 -1 roll + 2 index 3 get % Stack: cspace -mark- index proc|str + dup type /stringtype eq + { //CIdict 4 index 1 get 0 get get % # of components + dup 4 -1 roll mul exch getinterval { 255 div } forall + } + { exec + } + ifelse + counttomark 2 add -2 roll pop + 1 get setgcolor + } bdef +/setgcolor % (null | ) setgcolor - + { 1 index null eq + { pop pop } + { dup 0 get //Cdict exch get exec } + ifelse + } bdef +/fsexec % fsexec - + { % Preserve the current point, if any. + { currentpoint } stopped + { $error /newerror false put cvx exec } + { 3 -1 roll cvx exec moveto } + ifelse + } bdef + +% ---------------- Transformations ---------------- % + +/cmmatrix matrix def +/cm { //cmmatrix astore concat } 6 ! + +% ---------------- Path creation ---------------- % + +/m /moveto 2 ~ +/l /lineto 2 ~ +/c /curveto 6 ~ +/h /closepath 0 ~ +/v { currentpoint 6 2 roll curveto } 4 ! +/y { 2 copy curveto } 4 ! +/re + { 4 2 roll moveto exch dup 0 rlineto 0 3 -1 roll rlineto neg 0 rlineto + closepath + } 4 ! + +% ---------------- Path painting and clipping ---------------- % + +/S_ { setstrokecolor /stroke fsexec } bdef +/S { S_ } 0 ! +/f { setfillcolor /fill fsexec } 0 ! +/f* { setfillcolor /eofill fsexec } 0 ! +/n_ { newpath } bdef % don't allow n_ to get bound in +/n { n_ } 0 ! +/s { closepath S_ } 0 ! +/B_ { gsave setfillcolor fill grestore S_ } bdef +/B /B_ load 0 ! +/b { closepath B_ } 0 ! +/B*_ { gsave setfillcolor eofill grestore S_ } bdef +/B* /B*_ load 0 ! +/b* { closepath B*_ } 0 ! + +% Clipping: + +/Wdict 4 dict dup begin +/S_ { gsave setstrokecolor stroke grestore n_ } bdef +/f { gsave setfillcolor fill grestore n_ } 0 ! +/f* { gsave setfillcolor eofill grestore n_ } 0 ! +/n_ { end clip newpath } bdef +end readonly def +/W { //Wdict begin } 0 ! +/W*dict 4 dict dup begin +/S_ { gsave setstrokecolor stroke grestore n_ } bdef +/f { gsave setfillcolor fill grestore n_ } 0 ! +/f* { gsave setfillcolor eofill grestore n_ } 0 ! +/n_ { end eoclip newpath } bdef +end readonly def +/W* { //W*dict begin } 0 ! + +% ---------------- Images ---------------- % + +% We mustn't bind these now, since they reference Level 2 operators. +/Is % Is + { dup /DataSource get string /readstring cvx /currentfile cvx + % Stack: imagedict string -readstring- -currentfile- + 3 index /FilterProc .knownget + { dup dup 0 get /ASCIIHexDecode eq exch length 2 eq and + { pop exch pop /readhexstring cvx exch } + { exch exec exch exec } + ifelse + } + if 3 1 roll /pop cvx 4 packedarray cvx + } bdef +/EI { } def % placeholder, only needed when writing PostScript +% Note that ID* take a dictionary, not separate values; +% ColorSpace must be a name if it has no parameters; +% DataSource is the size of the row buffer in bytes; +% FilterProc is an optional procedure for constructing the decoding filter; +% and ImageMask is required, not optional. +/csimage + { /setcolorspace where + { pop dup /ColorSpace get csset setcolorspace pop image } + { .colorspaceimage } + ifelse + } def % don't bind, because of Level 2 +/ID % ID - + { Is dup 3 -1 roll dup /ImageMask get + { setfillcolor dup /Interpolate .knownget not { false } if + { dup /DataSource 4 -1 roll put /imagemask cvx exec + } + { { /Width /Height /Decode /ImageMatrix } + { 1 index exch get exch } + forall pop exch 0 get 0 ne exch + 5 -1 roll imagemask + } + ifelse + } + { dup /ColorSpace get /DeviceGray eq + 1 index /BitsPerComponent get 8 le and + 1 index /Decode get dup 1 get 1 eq exch 0 get 0 eq and and + 1 index /Interpolate .knownget not { false } if not and + { { /Width /Height /BitsPerComponent /ImageMatrix } + { 1 index exch get exch } + forall pop 5 -1 roll image + } + { dup /DataSource 4 -1 roll put csimage + } + ifelse + } + ifelse + % If we were reading with readhexstring, + % skip the terminating > now. + % Stack: datasource + dup type /filetype ne % array or packedarray + { dup 2 get /readhexstring eq + { { dup 0 get exec read pop (>) 0 get eq { exit } if } loop + } + if pop + } + { pop + } + ifelse EI + } 1 ! +% IDx handles general images. +/IDx % IDx - + { Is 1 index /DataSource 3 -1 roll put + csimage EI + } 1 ! + +% ---------------- Text control ---------------- % + +/textbeginpage + { /TextSpacing 0 def % 0 Tc + /TextLeading 0 def % 0 TL + /TextRenderingMode 0 def % 0 Tr + /TextRise 0 def % 0 Ts + /WordSpacing 0 def % 0 Tw + /TextHScaling 1.0 def % 100 Tz + /TextFont null def + /Show { showfirst } def + } bdef + +% Contrary to the statement in the PDF manual, BT and ET *can* be nested, +% if the CharProc for a Type 3 font does a BT/ET itself. +% Since we always call the CharProc inside a q_/Q_, we simply ensure that +% the text state is saved and restored like the rest of the extended +% graphics state. + +/settextmatrix + { TextMatrix concat + TextHScaling 1 ne { TextHScaling 1 scale } if + TextRise 0 ne { 0 TextRise translate } if + } bdef +/settextstate { TextSaveMatrix setmatrix settextmatrix } bdef + +/BT + { currentdict /TextMatrix .knownget + { identmatrix pop } + { matrix /TextMatrix gput } + ifelse + currentdict /TextOrigin .knownget + { dup 0 0 put 1 0 put } + { [0 0] cvx /TextOrigin gput } + ifelse + { showfirst } /Show gput + currentdict /TextSaveMatrix .knownget not + { matrix dup /TextSaveMatrix gput } + if currentmatrix pop settextmatrix 0 0 moveto + TextFont dup null eq { pop } { setfont } ifelse + } bind 0 ! +/ET + { TextSaveMatrix setmatrix + } bind 0 ! +/Tc_ { /TextSpacing gput { showfirst } /Show gput } bdef +/Tc { Tc_ } 1 ! +/TL { /TextLeading gput } bind 1 ! +/Tr { /TextRenderingMode gput { showfirst } /Show gput } bind 1 ! +/Ts { /TextRise gput settextstate } bind 1 ! +/Tw_ { /WordSpacing gput { showfirst } /Show gput } bdef +/Tw { Tw_ } 1 ! +/Tz { 100 div /TextHScaling gput settextstate } bind 1 ! + +/Tf % Tf - + { dup 1 eq { pop } { scalefont } ifelse + dup setfont /TextFont gput + } 2 ! + +% Copy a font, removing its FID. If changed is true, also remove +% the UniqueID and XUID, if any. If the original dictionary doesn't have +% the keys being removed, don't copy it. +/.copyfontdict % .copyfontdict + { 1 index /FID known + 1 index { 2 index /UniqueID known or 2 index /XUID known or } if + { % We add 1 to the length just in case the original + % didn't have a FID. + exch dup length 1 add dict exch + { % Stack: changed newfont key value + 1 index /FID eq 4 index + { 2 index /UniqueID eq or 2 index /XUID eq or } + if not { 3 copy put } if pop pop + } + forall exch + } + if pop + } bdef + +% Insert a new Encoding or Metrics into a font if necessary. +% Return a possibly updated font, and a flag to indicate whether +% the font was actually copied. +/.updatefont % .updatefont + % + { 2 index 4 1 roll + dup null ne + { 3 -1 roll true .copyfontdict dup /Metrics 4 -1 roll put exch } + { pop } + ifelse + dup null ne 1 index 3 index /Encoding get ne and + { exch false .copyfontdict dup /Encoding 4 -1 roll put } + { pop } + ifelse exch 1 index ne + } bdef + +% ---------------- Text positioning ---------------- % + +/Td_ + { TextOrigin exch 4 -1 roll add 3 1 roll add + 2 copy /TextOrigin load astore pop moveto + } bdef +/Td { Td_ } 2 ! +/TD { dup neg /TextLeading gput Td_ } 2 ! +/T*_ { 0 TextLeading neg Td_ } bdef +/T* { T*_ } 0 ! +/Tm + { TextMatrix astore pop settextstate + 0 0 /TextOrigin load astore pop + 0 0 moveto + } 6 ! + +% ---------------- Text painting ---------------- % + +/textrenderingprocs [ % (0 is handled specially) + { tf } { tS } { tB } { tn } + % We don't know what the clipping modes mean.... + 4 copy +] readonly def +/setshowstate + { WordSpacing 0 eq TextSpacing 0 eq and + { TextRenderingMode 0 eq + { { setfillcolor show } } + { { false charpath textrenderingprocs TextRenderingMode get exec } } + ifelse + } + { TextRenderingMode 0 eq + { WordSpacing 0 eq + { { setfillcolor TextSpacing exch 0 exch ashow } } + { TextSpacing 0 eq + { { setfillcolor WordSpacing exch 0 exch 32 exch widthshow } } + { { setfillcolor WordSpacing exch TextSpacing exch 0 32 4 2 roll 0 exch awidthshow } } + ifelse + } + ifelse + } + { { WordSpacing TextSpacing 2 index + % Implement the combination of t3 and false charpath. + % Stack: xword xchar string + 0 1 2 index length 1 sub + { 2 copy 1 getinterval false charpath + % Stack: xword xchar string i + 4 copy get 32 eq { add } { exch pop } ifelse 0 rmoveto + pop + } + for pop pop pop pop + textrenderingprocs TextRenderingMode get exec + } + } + ifelse + } + ifelse /Show gput + } bdef +/showfirst { setshowstate Show } def + +/Tj { Show } 1 ! +/' { T*_ Show } 1 ! +/" { exch Tc_ exch Tw_ T*_ Show } 3 ! +% TJ expects a mark followed by arguments, not an array. +/TJ + { counttomark -1 1 + { -1 roll dup type /stringtype eq + { Show } + { neg 1000 div 0 rmoveto } + ifelse + } + for pop +% Adobe implementations don't accept /[, so we don't either. + } ([) cvn ! + +/tf { setfillcolor currentpoint fill moveto } bdef +/tn { currentpoint newpath moveto } bdef +% For stroking characters, temporarily restore the graphics CTM so that +% the line width will be transformed properly. +/Tmatrix matrix def +/tS + { setstrokecolor + currentpoint //Tmatrix currentmatrix TextSaveMatrix setmatrix stroke + setmatrix moveto + } bdef +/tB { gsave tf grestore tS } bdef + +end readonly put % GS_PDF_ProcSet + +setglobal diff --git a/pstoraster/gs_pdf_e.ps b/pstoraster/gs_pdf_e.ps new file mode 100644 index 0000000000..ca1e934d26 --- /dev/null +++ b/pstoraster/gs_pdf_e.ps @@ -0,0 +1,48 @@ +% Copyright (C) 1994 Aladdin Enterprises. All rights reserved. +% +% This file is part of GNU Ghostscript. +% +% GNU Ghostscript is distributed in the hope that it will be useful, but +% WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to +% anyone for the consequences of using it or for whether it serves any +% particular purpose or works at all, unless he says so in writing. Refer to +% the GNU General Public License for full details. +% +% Everyone is granted permission to copy, modify and redistribute GNU +% Ghostscript, but only under the conditions described in the GNU General +% Public License. A copy of this license is supposed to have been given to +% you along with GNU Ghostscript so you can know your rights and +% responsibilities. It should be in a file named COPYING. Among other +% things, the copyright notice and this notice must be preserved on all +% copies. +% +% Aladdin Enterprises is not affiliated with the Free Software Foundation or +% the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, +% does not depend on any other GNU software. + +% Define the PDFDoc encoding vector. +/currentglobal where + { pop currentglobal { setglobal } true setglobal } + { { } } +ifelse +/PDFDocEncoding +ISOLatin1Encoding 0 24 getinterval aload pop + /breve /caron /circumflex /dotaccent /hungarumlaut /ogonek /ring /tilde +ISOLatin1Encoding 32 7 getinterval aload pop + /quotesingle +ISOLatin1Encoding 40 56 getinterval aload pop + /grave +ISOLatin1Encoding 97 31 getinterval aload pop +% \20x + /bullet /dagger /daggerdbl /ellipsis /emdash /endash /florin /fraction + /guilsinglleft /guilsinglright /minus /perthousand + /quotedblbase /quotedblleft /quotedblright /quoteleft + /quoteright /quotesinglbase /trademark /fi /fl /Lslash /OE /Scaron + /Ydieresis /Zcaron /dotlessi /lslash /oe /scaron /zcaron /.notdef +% \24x + /.notdef +ISOLatin1Encoding 161 12 getinterval aload pop + /.notdef +ISOLatin1Encoding 174 82 getinterval aload pop +256 packedarray .defineencoding +exec diff --git a/pstoraster/gs_pdfwr.ps b/pstoraster/gs_pdfwr.ps new file mode 100644 index 0000000000..6b982bdecf --- /dev/null +++ b/pstoraster/gs_pdfwr.ps @@ -0,0 +1,288 @@ +% Copyright (C) 1996 Aladdin Enterprises. All rights reserved. +% +% This file is part of GNU Ghostscript. +% +% GNU Ghostscript is distributed in the hope that it will be useful, but +% WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to +% anyone for the consequences of using it or for whether it serves any +% particular purpose or works at all, unless he says so in writing. Refer to +% the GNU General Public License for full details. +% +% Everyone is granted permission to copy, modify and redistribute GNU +% Ghostscript, but only under the conditions described in the GNU General +% Public License. A copy of this license is supposed to have been given to +% you along with GNU Ghostscript so you can know your rights and +% responsibilities. It should be in a file named COPYING. Among other +% things, the copyright notice and this notice must be preserved on all +% copies. +% +% Aladdin Enterprises is not affiliated with the Free Software Foundation or +% the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, +% does not depend on any other GNU software. + +% gs_pdfwr.ps +% PDF writer additions to systemdict. + +% This file should be included iff the pdfwrite "device" is included +% in the executable. + +% Redefine pdfmark to pass the data to the driver. +/.pdf===dict mark + /arraytype + { dup xcheck { ({) (}) } { ([) (]) } ifelse + % Stack: file obj left right + 4 1 roll 2 index exch writestring () exch + { exch 2 index exch writestring + 1 index exch pdfmark===only ( ) + } + forall pop exch writestring + } bind + /packedarraytype 1 index + /dicttype + { 1 index (<<\n) writestring + { 2 index 3 -1 roll pdfmark===only 1 index ( ) writestring + 1 index exch pdfmark===only dup (\n) writestring + } + forall (>>) writestring + } bind +.dicttomark readonly def +/pdfmark===only % pdfmark===only - + { .pdf===dict 1 index type .knownget { exec } { write==only } ifelse + } bind def +/.pdfcvs % .pdfcvs + { % We can't handle long values yet. + =string /NullEncode filter dup 2 index pdfmark===only + dup (\n\000) writestring closefile pop + =string (\n\000) search + { dup length string copy exch pop exch pop } + { % The converted representation didn't fit. Punt. + pop (???) + } + ifelse + } bind def +/.pdfputparams % .pdfputparams + { currentdevice null false mark 6 -2 roll exch + % Don't allow the page device to get cleared.... + {.putdeviceparams} 0 get .currentpagedevice pop {.setpagedevice} 0 get + 3 array astore cvx exec + } bind def +/pdfmark + { ] 1 2 2 index length 1 sub { 2 copy 2 copy get .pdfcvs put pop } for + /pdfmark .pdfputparams + type /booleantype ne { cleartomark pop pop } if pop + } odef +userdict /pdfmark .undef + +% Define setdistillerparams / currentdistillerparams. +% Distiller parameters are currently treated as device parameters. +/.distillerparamkeys mark + % General parameters + /CoreDistVersion { } + /DoThumbnails { } + /LZWEncodePages { } + /ASCII85EncodePages { } + % Color sampled image parameters + /DownsampleColorImages { } + /ColorImageResolution { } + /EncodeColorImages { } + /ColorImageFilter { } + /ColorImageDict { } + /ColorImageDepth { } + /AntiAliasColorImages { } + /ConvertCMYKImagesToRGB { } + % Grayscale sampled image parameters + /DownsampleGrayImages { } + /GrayImageResolution { } + /EncodeGrayImages { } + /GrayImageFilter { } + /GrayImageDict { } + /GrayImageDepth { } + /AntiAliasGrayImages { } + % Monochrome sampled image parameters + /DownsampleMonoImages { } + /MonoImageResolution { } + /EncodeMonoImages { } + /MonoImageFilter { } + /MonoImageDict { } + /MonoImageDepth { } + /AntiAliasMonoImages { } + % Font embedding parameters + /AlwaysEmbed + { dup length 0 gt + { dup 0 get false eq + { dup length 1 sub 1 exch getinterval exch pop /~AlwaysEmbed exch + } if + } if + } + /NeverEmbed + { dup length 0 gt + { dup 0 get false eq + { dup length 1 sub 1 exch getinterval exch pop /~NeverEmbed exch + } if + } if + } + /EmbedAllFonts { } + /SubsetFonts { } + /MaxSubsetPct { } +.dicttomark readonly def +/.distillerdevice + { currentdevice .devicename /pdfwrite eq + { currentdevice } + { /pdfwrite finddevice } + ifelse + } bind def +/setdistillerparams % setdistillerparams - + { .distillerdevice null false mark 5 -1 roll + { //.distillerparamkeys 2 index .knownget { exec } { pop pop } ifelse } + forall .putdeviceparams + type /booleantype eq { pop } { cleartomark pop pop pop } ifelse + } odef +/currentdistillerparams % - currentdistillerparams + { .distillerdevice //.distillerparamkeys .getdeviceparams .dicttomark + } odef + +% Patch the 'show' operators to pass the data to the device. +% We use a pseudo-parameter named /show whose value is a dictionary: +% /String (str) +% /Values [cx cy char ax ay px py] +% /Matrix [xx xy yx yy tx ty] +% /FontName /fontname +% /Color [r g b] +% /Encoding [e0 .. e255] +% /BaseEncoding [e0 ... e255] +% THIS IS A BIG HACK. +/.findorigfont % .findorigfont + { % Check for a known font with this name and + % the same UniqueID. + dup /UniqueID .knownget + { 1 index /FontName .knownget + { % Stack: font uniqueid fontname + FontDirectory exch .knownget + { dup /UniqueID .knownget + { % Stack: font uniqueid knownfont knownid + 3 -1 roll eq { true } { pop false } ifelse + } + { pop pop false + } + ifelse + } + { pop false + } + ifelse + } + { pop false + } + ifelse + } + { false + } + ifelse + % Stack: font knownfont -true- | font -false- + { exch pop + } + { { dup /OrigFont .knownget not { exit } if exch pop } loop + } + ifelse + } .bind def +/.pdfdoshow % .pdfdoshow + % + { mark /String 8 2 roll + currentpoint transform 7 array astore /Values exch + % Concatenate the "quotient" of the current FontMatrix + % and the FontMatrix of the original font. + % Be sure to include any translation. + /Matrix + currentfont .findorigfont /FontMatrix get matrix invertmatrix + currentfont /FontMatrix get 1 index concatmatrix + matrix currentmatrix dup 4 0 put dup 5 0 put dup concatmatrix + /FontName currentfont /FontName get + /Color [ currentrgbcolor ] + /Encoding currentfont /Encoding .knownget not { [] } if + % Make a reasonable guess at the base encoding. + /BaseEncoding StandardEncoding + .dicttomark /show .pdfputparams + dup type /booleantype eq + { pop pop true } + { dup /undefined eq + { cleartomark pop pop pop false } + { dup mark eq { /unknown /rangecheck } if + counttomark 4 add 1 roll cleartomark pop pop pop + /.pdfshow cvx exch signalerror + } + ifelse + } + ifelse + } .bind def +/.pdfexecshow % .pdfexecshow - + { matrix currentmatrix gsave nulldevice setmatrix + exec currentpoint grestore moveto + } .bind def +% Create a 1-element cache for currentdevice .devicename /pdfwrite eq. +userdict begin + /.pdfwritedevice null def + /.pdfwriteenabled false def % place-holder +end +/.pdfwrite? % - .pdfwrite? + { currentdevice .pdfwritedevice eq + { .pdfwriteenabled + } + { currentdevice .devicename /pdfwrite eq + userdict /.pdfwriteenabled 2 index put + userdict /.pdfwritedevice currentdevice put + } + ifelse currentfont /FontType get 1 eq and + } .bind def +/.pdfshow % + % .pdfdoshow - + { 7 1 roll .pdfwrite? + { .pdfdoshow } + { 6 { pop } repeat false } + ifelse + { .pdfexecshow } + { exec } + ifelse + } .bind def +/show + { dup 0 0 32 0 0 { show } .pdfshow + } .bind odef +/ashow + { dup 0 0 32 6 index 6 index dtransform { ashow } .pdfshow + } .bind odef +/widthshow + { 4 copy 4 -2 roll dtransform 4 -1 roll 0 0 { widthshow } .pdfshow + } .bind odef +/awidthshow + { 6 copy 6 -2 roll dtransform 6 -3 roll dtransform { awidthshow } .pdfshow + } .bind odef +/glyphshow + { .pdfwrite? + { currentfont /Encoding .knownget not { {} } if + 0 1 2 index length 1 sub + { % Stack: glyph encoding index + 2 copy get 3 index eq { exch pop exch pop null exit } if pop + } + for null eq + { (X) dup 0 4 -1 roll put show } + { glyphshow } + ifelse + } + { glyphshow + } + ifelse + } .bind odef +% The remaining operators aren't implemented correctly. +/kshow + { .pdfwrite? + { { (X) dup 0 4 -1 roll put show dup exec } forall pop } + { kshow } + ifelse + } .bind odef +/xshow + { .pdfwrite? { pop show } { xshow } ifelse + } .bind odef +/yshow + { .pdfwrite? { pop show } { yshow } ifelse + } .bind odef +/xyshow + { .pdfwrite? { pop show } { xyshow } ifelse + } .bind odef diff --git a/pstoraster/gs_pfile.ps b/pstoraster/gs_pfile.ps new file mode 100644 index 0000000000..5d49a64480 --- /dev/null +++ b/pstoraster/gs_pfile.ps @@ -0,0 +1,184 @@ +% Copyright (C) 1994, 1995 Aladdin Enterprises. All rights reserved. +% +% This file is part of GNU Ghostscript. +% +% GNU Ghostscript is distributed in the hope that it will be useful, but +% WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to +% anyone for the consequences of using it or for whether it serves any +% particular purpose or works at all, unless he says so in writing. Refer to +% the GNU General Public License for full details. +% +% Everyone is granted permission to copy, modify and redistribute GNU +% Ghostscript, but only under the conditions described in the GNU General +% Public License. A copy of this license is supposed to have been given to +% you along with GNU Ghostscript so you can know your rights and +% responsibilities. It should be in a file named COPYING. Among other +% things, the copyright notice and this notice must be preserved on all +% copies. +% +% Aladdin Enterprises is not affiliated with the Free Software Foundation or +% the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, +% does not depend on any other GNU software. + +% Runtime support for minimum-space fonts and packed files. + +% ****** NOTE: This file must be kept consistent with +% ****** packfile.ps and wrfont.ps. + +% ---------------- Packed file support ---------------- % + +% A packed file is the concatenation of several file groups, each of which +% is the result of compressing several files concatenated together. +% The packed file begins with a procedure that creates an appropriate +% decoding filter for each file group, as follows: +% -proc- +% Thus, accessing an individual file requires 4 parameters: +% the starting address and length of the outer compressed file, +% and the starting address and length of the inner file. +/.packedfilefilter % + % .packedfilefilter + { 4 index systemdict begin token pop end 6 1 roll + % Stack: fproc file ostart olength istart ilength + 4 index 5 -1 roll setfileposition + % Stack: fproc file olength istart ilength + 4 -2 roll () /SubFileDecode filter + % Stack: fproc istart ilength ofilter + 4 -1 roll exec + % Filters don't support setfileposition, so we must skip data + % by reading it into a buffer. We rely on the fact that + % save/restore don't affect file positions. + % Stack: istart ilength dfilter + save exch 1000 string + % Stack: istart ilength save dfilter scratch + 4 index 1 index length idiv { 2 copy readstring pop pop } repeat + 2 copy 0 8 -1 roll 2 index length mod getinterval readstring pop pop pop + % Stack: ilength save dfilter + exch restore exch () /SubFileDecode filter + } bind def + +% Run a packed library file. +/.runpackedlibfile % + % .runpackedlibfile + { 5 -1 roll findlibfile + { exch pop dup 6 2 roll .packedfilefilter + currentobjectformat exch 1 setobjectformat run + setobjectformat closefile + } + { 5 1 roll /findlibfile load /undefinedfilename signalerror + } + ifelse + } bind def + +% ---------------- Compacted font support ---------------- % + +% Compacted fonts written by wrfont.ps depend on the existence and +% specifications of the procedures and data in this section. + +/.compactfontdefault mark + /PaintType 0 + /FontMatrix [0.001 0 0 0.001 0 0] readonly + /FontType 1 + /Encoding StandardEncoding +.dicttomark readonly def + +/.checkexistingfont % + % .checkexistingfont + % {} ( on d-stack) + % + % .checkexistingfont + % -save- --restore-- ( on d-stack) + { FontDirectory 4 index .knownget + { dup /UniqueID .knownget + { 4 index eq exch /FontType get 1 eq and } + { pop false } + ifelse + } + { false + } + ifelse + { save /restore load 6 2 roll } + { {} 5 1 roll } + ifelse + dict //.compactfontdefault exch .copydict begin + dict /Private exch def + Private begin + /MinFeature {16 16} def + /Password 5839 def + /UniqueID 1 index def + end + /UniqueID exch def + /FontName exch def + } bind def + +/.knownEncodings [ + ISOLatin1Encoding + StandardEncoding + SymbolEncoding +] readonly def + +/.readCharStrings % .readCharStrings + { exch dup dict dup 3 -1 roll + { currentfile token pop dup type /integertype eq + { dup -8 bitshift //.knownEncodings exch get exch 255 and get } if + currentfile token pop dup type /nametype eq + { 2 index exch get + } + { % Stack: encrypt dict dict key value + 4 index { 4330 exch dup .type1encrypt exch pop } if + readonly + } + ifelse put dup + } + repeat pop exch pop + } bind def + +% ---------------- Synthetic font support ---------------- % + +% Create a new font by modifying an existing one. paramdict contains +% entries with the same keys as the ones found in a Type 1 font; +% it should also contain enough empty entries to allow adding the +% corresponding non-overridden entries from the original font dictionary, +% including FID. If paramdict includes a FontInfo entry, this will +% also override the original font's FontInfo, entry by entry; +% again, it must contain enough empty entries. + +% Note that this procedure does not perform a definefont. + +/.makemodifiedfont % .makemodifiedfont + { exch + { % Stack: destdict key value + 1 index /FID ne + { 2 index 2 index known + { % Skip fontdict entry supplied in paramdict, but + % handle FontInfo specially. + 1 index /FontInfo eq + { 2 index 2 index get % new FontInfo + 1 index % old FontInfo + { % Stack: destdict key value destinfo key value + 2 index 2 index known + { pop pop } + { 2 index 3 1 roll put } + ifelse + } + forall pop + } + if + } + { % No override, copy the fontdict entry. + 2 index 3 1 roll put + dup dup % to match pop pop below + } + ifelse + } + if + pop pop + } forall + } bind def + +% Make a modified font and define it. Note that unlike definefont, +% this does not leave the font on the operand stack. + +/.definemodifiedfont % .definemodifiedfont - + { .makemodifiedfont + dup /FontName get exch definefont pop + } bind def diff --git a/pstoraster/gs_res.ps b/pstoraster/gs_res.ps new file mode 100644 index 0000000000..6b955e9016 --- /dev/null +++ b/pstoraster/gs_res.ps @@ -0,0 +1,555 @@ +% Copyright (C) 1994, 1996 Aladdin Enterprises. All rights reserved. +% +% This file is part of GNU Ghostscript. +% +% GNU Ghostscript is distributed in the hope that it will be useful, but +% WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to +% anyone for the consequences of using it or for whether it serves any +% particular purpose or works at all, unless he says so in writing. Refer to +% the GNU General Public License for full details. +% +% Everyone is granted permission to copy, modify and redistribute GNU +% Ghostscript, but only under the conditions described in the GNU General +% Public License. A copy of this license is supposed to have been given to +% you along with GNU Ghostscript so you can know your rights and +% responsibilities. It should be in a file named COPYING. Among other +% things, the copyright notice and this notice must be preserved on all +% copies. +% +% Aladdin Enterprises is not affiliated with the Free Software Foundation or +% the GNU Project. GNU Ghostscript, as distributed by Aladdin Enterprises, +% does not depend on any other GNU software. + +% Initialization file for Level 2 resource machinery. +% When this is run, systemdict is still writable, +% but everything defined here goes into level2dict. + +level2dict begin + +(BEGIN RESOURCES) VMDEBUG + +% We keep track of (global) instances with another entry in the resource +% dictionary, an Instances dictionary. For categories with implicit +% instances, the values in Instances are the same as the keys; +% for other categories, the values are [instance status size]. + +% Note that the dictionary that defines a resource category is stored +% in global memory. The PostScript manual says that each category must +% manage global and local instances separately. However, objects in +% global memory other than systemdict can't reference objects in local memory. +% This means that the resource category dictionary, which would otherwise be +% the obvious place to keep track of the instances, can't be used to keep +% track of local instances. Instead, we define a dictionary in local VM +% called localinstancedict, in which the key is the category name and +% the value is the analogue of Instances for local instances. + +% We don't currently implement automatic resource unloading. +% When and if we do, it should be hooked to the garbage collector. +% However, Ed Taft of Adobe says their interpreters don't implement this +% either, so we aren't going to worry about it for a while. + +currentglobal false setglobal systemdict begin + /localinstancedict 5 dict def +end true setglobal +/.emptydict 0 dict readonly def +setglobal + +% Resource category dictionaries have the following keys (those marked with +% * are optional): +% Standard, defined in the Red Book: +% Category (name) +% *InstanceType (name) +% DefineResource +% UndefineResource +% FindResource +% ResourceStatus +% ResourceForAll +% *ResourceFileName +% Additional, specific to our implementation: +% Instances (dictionary) +% .LocalInstances +% - .LocalInstances +% .GetInstance +% .GetInstance -true- +% .GetInstance -false- +% .CheckResource +% .CheckResource +% .DoLoadResource +% .DoLoadResource - (may give an error) +% .LoadResource +% .LoadResource - (may give an error) +% .ResourceFile +% .ResourceFile -true- +% .ResourceFile -false- +% All the above procedures expect that the top dictionary on the d-stack +% is the resource dictionary. + +% Define enough of the Category category so we can define other categories. +% The dictionary we're about to create will become the Category +% category definition dictionary. + +12 dict begin + + % Standard entries + +/Category /Category def +/InstanceType /dicttype def + +/DefineResource + { dup .CheckResource + { dup /Category 3 index cvlit .growput readonly + dup [ exch 0 -1 ] exch + Instances 4 2 roll put + } + { /typecheck signalerror + } + ifelse + } bind def +/FindResource % (redefined below) + { Instances exch get 0 get + } bind def + + % Additional entries + +/Instances 25 dict def +Instances /Category [currentdict 0 -1] put + +/.LocalInstances 0 dict def +/.GetInstance + { Instances exch .knownget + } bind def +/.CheckResource + { dup gcheck currentglobal and + { /DefineResource /FindResource /ResourceForAll /ResourceStatus + /UndefineResource } + { 2 index exch known and } + forall exch pop + } bind def + +Instances end begin % for the base case of findresource + +(END CATEGORY) VMDEBUG + +% Define the resource operators. I don't see how we can possibly restore +% the stacks after an error, since the procedure may have popped and +% pushed elements arbitrarily.... + +mark +/defineresource % defineresource + { /Category findresource dup begin + /InstanceType known + { dup type InstanceType ne + { dup type /packedarraytype eq InstanceType /arraytype eq and + not { /typecheck signalerror } if + } if + } if + /DefineResource load stopped end { stop } if + } +/findresource % findresource + { dup /Category eq + { pop //Category 0 get } { /Category findresource } ifelse + begin + /FindResource load stopped end { stop } if + } +/resourceforall %